Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PATCH and PUT Request Does not Working with form-data

I am using Laravel to create a RESTFUL application and I test the application with Postman. Currently, there is an issue for PATCH or PUT if the data sent from Postman with form-data.

// Parameter `{testimonial}` will be sent to backend.
Route::post  ('testimonials/{testimonial}', 'TestimonialController@update');

// Parameter `{testimonial}` will not be sent to backend (`$request->all()` will be empty) if sent from Postman with form-data.
Route::patch ('testimonials/{testimonial}', 'TestimonialController@update');
Route::put   ('testimonials/{testimonial}', 'TestimonialController@update');
  • Using form-data, $request->all() will be okay for POST.
  • Using x-www-form-urlencoded, $request->all() will be okay for PATCH, PUT, and POST.
  • However, if I am sending PUT and PATCH with form-data from Postman, the $request->all() will be empty (the parameters will not be sent to backend).

Right now the solution is to use POST for updating a model. I want to know why PATCH and PUT is not working when sent with form-data from Postman.

like image 932
notalentgeek Avatar asked Jun 05 '18 04:06

notalentgeek


People also ask

Is PATCH idempotent?

A PATCH is not necessarily idempotent, although it can be. Contrast this with PUT ; which is always idempotent. The word "idempotent" means that any number of repeated, identical requests will leave the resource in the same state.

How do I put form data into a postman?

POST request to send a form (multipart/form-data) To send a POST request, select the POST request method, click on Body, and select form-data. If you look at the response body, you will notice that the data you have submitted.


4 Answers

This is a known issue and the workaround suggestion as per the following Github comment is that when sending a PATCH / PUT requests you should do the following:

You should send POST and set _method to PUT (same as sending forms) to make your files visible

So essentially you send a POST request with a parameter which sets the actual method and Laravel seems to understand that.

As per the documentation:

Since HTML forms can't make PUT, PATCH, or DELETE requests, you will need to add a hidden _method field to spoof these HTTP verbs. The @method Blade directive can create this field for you:

<form action="/foo/bar" method="POST">
    @method('PUT')

    ...
</form> 

Alternatively, you can use the method_field helper function to do the above:

The method_field function generates an HTML hidden input field containing the spoofed value of the form's HTTP verb. For example, using Blade syntax:

<form method="POST">
    {{ method_field('PUT') }}
</form>
like image 189
Script47 Avatar answered Oct 12 '22 19:10

Script47


I learnt how to solve it here on this post and I'd like to share what did I do.

The following image is how I setup the Postman to send a HTTP POST request and go into PUT Request and make it receive my files.

I'm not sure whether it is the right way to do a RESTFul API. But it works fine

An example on Postman how to setup your HTTP Request

like image 22
Caique Andrade Avatar answered Oct 12 '22 21:10

Caique Andrade


so as everyone mentioned above and explained everything, but still i dont see the answer for cases when using a REST API so i fallowed @Caique Andrade answer and send a POST request and formed my URL link like this:

url = 'https://yourwebsite.com/api/v1/users/$id?_method=PUT';

$id is the variable id for the user.

?_method=PUT is added to the url POST request to spoof the request and it works

in my case i used Dart in flutter and sent a post request using Http package Laravel catches that POST request as a PUT request

like image 13
Ridha Rezzag Avatar answered Oct 12 '22 19:10

Ridha Rezzag


Laravel PATCH and PUT method does not work with form-data, it's known issue of Symfony and even PHP (Google for that - Laravel use many Symfony foundation packages, include Request).

  1. If you do not need to pass file(s) via request, change form-data to raw with json content-type. E.g: {"name":"changed"}. It will be read as php://input and your code should work well ($request->all() is now ["name" => "changed]).

  2. If you need to pass file(s), in my opinion, DO NOT pass it within the REST API methods. You can write another method to do whatever you need with your file(s) (E.g: POST form-data -> upload file -> update db -> return a file path/url/even its base64 content), then you can use its output/result to continue with your patch/put method (raw with json content-type). I always do that when I work with files in API.

Hope this help!

like image 10
vietanhyt Avatar answered Oct 12 '22 20:10

vietanhyt