Framework: [5.4] Cannot access file upload from PUT Request

Created on 26 Jan 2017  路  8Comments  路  Source: laravel/framework

  • Laravel Version: 5.4.3
  • PHP Version: 7.0.14
  • Database Driver & Version: None

Description:

running a curl command
curl -s -S -X PUT -F "key=@/Users/necrogami/.ssh/8192.pub" https://ssh.local.dev/key/[email protected]/
I cannot access the key request attribute (note i do see the whole file uploaded via the content-length header)

however if i run
curl -s -S -X POST -F "key=@/Users/necrogami/.ssh/8192.pub" https://ssh.local.dev/key/[email protected]/
i have access to the key attribute

Steps To Reproduce:

dump($request->key);
dd($request->all());

Most helpful comment

I've spent 2 hours banging my head trying to figure out why $_FILES superglobal isn't being populated for PUT requests and now found this. Since PHP doesn't natively do this, I wonder if there's a reason why the multipart/form-data request body parsing isn't abstracted in the Symfony package?

All 8 comments

This is because Laravel uses a header to override the post request to convert it into a put request due to the fact that most browsers doesn't support the put request or default just yet. By setting the method field to put or x-request-override (not sure if it's the exact name) to request the server with a post request but have it treated as a put request.

Hope @morloderex comments helps, please continue on the forums though since we try to keep this repo for bug reporting only :) Appreciate your understanding.

You didn't read the text of the post. curl -s -S -X PUT That's method of PUT.. The put is working. i can access the put method. But i cannot access the File on the put method. Laravel detects the method is put.

I'm NOT using a browser i'm using curl. Please READ the post.

This method doesn't work. Nothing is returned on value $request->key, $request->hasFile('key')

| => curl -s -S -X PUT -F "key=@/Users/necrogami/.ssh/8192.pub" https://ssh.local.dev/key/[email protected]/ -vvv
*   Trying 127.0.0.1...
* Connected to ssh.local.dev (127.0.0.1) port 443 (#0)
* TLS 1.2 connection using TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
* Server certificate: *.local.dev
> PUT /key/[email protected]/ HTTP/1.1
> Host: ssh.local.dev
> User-Agent: curl/7.43.0
> Accept: */*
> Content-Length: 1641
> Expect: 100-continue
> Content-Type: multipart/form-data; boundary=------------------------3723665f2ba6059e
> 
< HTTP/1.1 100 Continue
< HTTP/1.1 200 OK
< Server: nginx/1.10.2
< Content-Type: text/html; charset=UTF-8
< Transfer-Encoding: chunked
< Connection: keep-alive
< X-Powered-By: PHP/7.0.14
< allow: GET, HEAD, POST
< Cache-Control: no-cache, private
< Date: Thu, 26 Jan 2017 11:41:49 GMT
< Access-Control-Allow-Origin: *
< Access-Control-Allow-Credentials: true
< Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS
< Access-Control-Allow-Headers: DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization
< 
    Route::put('/', function (Request $request, $email) {
        dd($request->key);
    });

This however returns the value without problems.

| => curl -s -S -X POST -F "key=@/Users/necrogami/.ssh/8192.pub" https://ssh.local.dev/key/[email protected]/ -vvv
*   Trying 127.0.0.1...
* Connected to ssh.local.dev (127.0.0.1) port 443 (#0)
* TLS 1.2 connection using TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
* Server certificate: *.local.dev
> POST /key/[email protected]/ HTTP/1.1
> Host: ssh.local.dev
> User-Agent: curl/7.43.0
> Accept: */*
> Content-Length: 1641
> Expect: 100-continue
> Content-Type: multipart/form-data; boundary=------------------------f8d5874d8263d417
> 
< HTTP/1.1 100 Continue
< HTTP/1.1 200 OK
< Server: nginx/1.10.2
< Date: Thu, 26 Jan 2017 11:41:27 GMT
< Content-Type: text/html; charset=UTF-8
< Transfer-Encoding: chunked
< Connection: keep-alive
< X-Powered-By: PHP/7.0.14
< Access-Control-Allow-Origin: *
< Access-Control-Allow-Credentials: true
< Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS
< Access-Control-Allow-Headers: DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization
<
    Route::post('/', function (Request $request, $email) {
        dd($request->key);
    });

I've tested in 5.4.6 and 5.3.30 and neither work for PUT. POST is fine on both.

Yes it looks like it's a PHP thing rather than a laravel core thing, the $_FILES global is empty on PUT on a plain PHP project (non-laravel), however it holds the file in a POST request.

Closing this issue then since it's not laravel related, try the forums though.

http://php.net/manual/en/features.file-upload.put-method.php I just found this when searching for file uploads with put.. apparently php does file uploads for put requests differently.

I've spent 2 hours banging my head trying to figure out why $_FILES superglobal isn't being populated for PUT requests and now found this. Since PHP doesn't natively do this, I wonder if there's a reason why the multipart/form-data request body parsing isn't abstracted in the Symfony package?

Was this page helpful?
0 / 5 - 0 ratings