Edit report at https://bugs.php.net/bug.php?id=55815&edit=1
ID: 55815 Comment by: theanomaly dot is 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: 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. Previous Comments: ------------------------------------------------------------------------ [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