Edit report at https://bugs.php.net/bug.php?id=55815&edit=1

 ID:                 55815
 Comment by:         phazei at gmail dot com
 Reported by:        catch dot dave at gmail dot com
 Summary:            PUT request data should be parsed just like POST
 Status:             Open
 Type:               Feature/Change Request
 Package:            Streams related
 Operating System:   All
 PHP Version:        5.4.0beta1
 Block user comment: N
 Private report:     N

 New Comment:

Has this been reconsidered at all? Any update?


Previous Comments:
------------------------------------------------------------------------
[2012-04-16 19:15:43] catch dot dave at gmail dot com

Hi theanomaly,

I'd like to address your points.

1. As per my original request the manual page of 
"http://php.net/manual/en/features.file-upload.put-
method.php" *does not* solve the problem, as it does not handle multipart form 
requests.

2. Implementing the parsing of multipart form data in PHP seems to be re-
inventing the wheel when the 
code to correctly parse this already exists in PHP itself (to parse POST data).

3. Perhaps I am misunderstanding, but reading through both your quote and the 
rest of the 2616 spec, I 
fail to see how the spec precludes handling form-data in a PUT method, The 
section you quoted is saying 
that:
      * PUT must operate on the URI provided and not another one; and
      * that the difference between PUT and POST, is that POST URI defines the 
resource that operates on 
an entity, whereas a PUT request's URI identifies the entity itself. It is 
common to use the PUT verb to 
operate on existing entities in restful APIs (e.g. modifying the title of an 
existing book, you would send 
the new title as data, and not in the URI itself), which does not seem to 
violate this point either.

The multipart form data is part of the original user request and should 
therefore be parseable--the user 
is sending the data (in multipart form) to operate on the URI using the PUT 
method.

I don't think the spec is saying that you are not allowed to use/consider the 
data sent along with it--
as opposed to your interpretation which suggests the RFC is saying that all 
data 
other than the URI 
itself (whether multipart form encoded or not) should be ignored.

4. I had originally had some code that does exactly what you described, but it 
was nowhere near as 
robust as the existing code in PHP, which lead to me writing this request (re-
invent the wheel). 
Furthermore, other languages (e.g. Ruby) do parse multipart data in PUT (not 
that that should be the 
primary reason).

------------------------------------------------------------------------
[2012-04-11 01:52:33] theanomaly dot is at gmail dot com

First, I'd like to start by noting that the PHP manual already addresses file 
uploads via PUT method by: 

http://php.net/manual/en/features.file-upload.put-method.php

Second, I want to point out that what you're asking is actually a violation of 
the HTTP specification as per RFC 2616 specifically Section 9.6

http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.6

"The fundamental difference between the POST and PUT requests is reflected in 
the different meaning of the Request-URI. The URI in a POST request identifies 
the resource that will handle the enclosed entity. That resource might be a 
data-accepting process, a gateway to some other protocol, or a separate entity 
that accepts annotations. In contrast, the URI in a PUT request identifies the 
entity enclosed with the request -- the user agent knows what URI is intended 
and the server MUST NOT attempt to apply the request to some other resource. If 
the server desires that the request be applied to a different URI, it MUST send 
a 301 (Moved Permanently) response; the user agent MAY then make its own 
decision regarding whether or not to redirect the request."

What this means is the HTTP RFC does not allow us to identify multipart/form-
data in a PUT request.

Thus your proposed implementation to how PHP already handles requests would 
then 
put PHP in a position of having not complied with the spec. PUT is used for a 
different specification than POST and thus modifying PHP to treat them equally 
would not be a sane solution.

However, there are some simple steps to accomplishing what you want even though 
it would be in violation of the HTTP specification. Namely they would be:

1) You can detect whether or not PUT was the REQUEST method via 
$_SERVER['REQUEST_METHOD'] for example (depends on your SAPI).
2) You may then proceed to process the 'php://input' stream through something 
like file_get_contents('php://input'); - as an example.
3) You may then proceed to break up the multipart form data according to its 
defined boundaries in PHP user-space code -- according to the specification at 
http://tools.ietf.org/html/rfc2388
4) Finally you may chose to do with the file as you'd like (save, discard, 
otherwise).

However, it would make no sense at all to create a new superglobal in PHP 
called 
$_PUT since the HTTP PUT verb does not allow for multi-part/form data to begin 
with. So whoever is saying PHP is making it difficult to be RESTful is 
misleading.

------------------------------------------------------------------------
[2011-12-29 17:47:09] thomas dot mery at gmail dot com

Hi,

was wondering if this had been considered

thanks

------------------------------------------------------------------------
[2011-09-29 16:51:39] catch dot dave at gmail dot com

Description:
------------
Data that is posted to PHP via the PUT method is not parsed at all and is not 
available to PHP.
This is particularly problematic for data sent encoded as 'multipart/form-data'.

Basically, a request sent (with files and/or non-file data) via PUT should be 
parsed using the same functions used for requests sent via 
POST.
Ideally, $_FILES and *either* $_POST or a new $_PUT superglobals should be 
populated in PUT requests.


The answer is *not* to simply use parse_str() because that does not handle 
multipart/form-data requests.

This is something that would help every RESTful interface that people are 
trying 
to do with PHP.
There are many people who have these problems and have to implement (usually 
incomplete and/or buggy) PHP solutions, 
eg: 
* Example of someone's wrong and incomplete solution: 
http://stackoverflow.com/questions/5483851/manually-parse-raw-
http-data-with-php
* Example of other people having problems: http://drupal.org/node/1270190


I ended up having to write half a page of code just to parse file and normal 
data out of php://input stream which is not going to be as 
well tested or as stable as PHP's existing C code that parses the data when 
using the POST method.


This could (possibly) be as simple as changing lines such as:
    `if(!strcmp(SG(request_info).request_method, "POST"))`
to
   `if(!strcmp(SG(request_info).request_method, "POST") || 
!strcmp(SG(request_info).request_method, "PUT"))`

or even adding a new superglobal called $_PUT (but still re-using $_FILES).


Test script:
---------------
The request:

#!/bin/sh
curl "https://localhost/restful_server/"; -X PUT -F 
"photo=@my_image.jpg;type=image/jpg" -F "foo=bar"

The php code:

<?php
echo "POST: \n"; var_dump($_POST);
echo "PUT: \n"; @var_dump($_PUT); // obviously this won't exist yet in php 
5.4/5.3
echo "FILES: \n"; var_dump($_FILES);



Expected result:
----------------
POST: 
        array(0) {
}
PUT: 
        array(1) {
  ["foo"]=>
  string(3) "bar"
}
FILES: 
        array(1) {
  ["photo"]=>
  array(5) {
    ["name"]=>
    string(6) "my_image.jpg"
    ["type"]=>
    string(9) "image/jpg"
    ["tmp_name"]=>
    string(26) "/private/var/tmp/my_image.jpg"
    ["error"]=>
    int(0)
    ["size"]=>
    int(1)
  }
}

Actual result:
--------------
POST: 
        array(0) {
}
PUT: 
        NULL
FILES: 
        array(0) {
}


------------------------------------------------------------------------



-- 
Edit this bug report at https://bugs.php.net/bug.php?id=55815&edit=1

Reply via email to