Req #37681 [Com]: PUT and DELETE superglobals support
Edit report at https://bugs.php.net/bug.php?id=37681&edit=1 ID: 37681 Comment by: catch dot dave at gmail dot com Reported by:f_kereki at cs dot com dot uy Summary:PUT and DELETE superglobals support Status: Open Type: Feature/Change Request Package:Feature/Change Request Operating System: SUSE 10.0 PHP Version:5.1.4 Block user comment: N Private report: N New Comment: Parsing "php://input" is *not* a workaround because it fails on multipart/encoded input. Which is a common method to send data (and also the only way to send files). See similar/duplicate bug entry here: https://bugs.php.net/bug.php?id=55815 Previous Comments: [2010-06-01 22:15:33] andreas dot s dot t dot jansson at gmail dot com I hit submit prematurely. Here's how to emulate $_DELETE: parse_str(file_get_contents('php://input'), $_DELETE); [2010-06-01 21:59:24] andreas dot s dot t dot jansson at gmail dot com If the only contents of the request body is the urlencoded "DELETE parameters" you can retrieve them by using file_get_contents("php://input"). It's not as clean as $_DELETE, but it's a workaround for now at least. [2009-10-21 12:33:28] cyberspice at cyberspice dot org dot uk I'd like to take this on. I too have come up against a similar issue and I know of another developer who would be appreciative of it. So I propose I make a patch that adds support for PUT, DELETE and HEAD (for completeness) super globals. Per RFC 2616 PUT is similar to post and can have data both in the URI and the body of the request. DELETE and HEAD are like GET. Since there is already support for POST data in the sapi code and php_variables.c has treat_data() for handling GET. It seems it should be relatively simple to extend for the new variables. What do you think? [2006-06-03 13:43:51] f_kereki at cs dot com dot uy I'm coding a Service Oriented system, and according to REST principles, I should be able to call a service with a PUT or DELETE method. For example, using AJAX, in JavaScript I would write something like: objeto= new XMLHttpRequest(); objeto.open("PUT", "my_own_service.php", true); objeto.setRequestHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8"); objeto.onreadystatechange= some_function_of_mine; objeto.send("a_string_like_field=value&field2=value2"); but then, my_own_service.php would have no way of getting to the PUT parameters! With POST or GET methods, you can use the $_POST and $_GET (and even $_REQUEST) arrays, but there are no $_PUT or $_DELETE equivalent arrays. Note, however, that this is *not* just an AJAX problem; if you require a PHP service from within another PHP service, you would code something like: $ch= curl_init(); curl_setopt($ch, CURLOPT_URL, "my_own_service.php"); curl_setopt($ch, CURLOPT_HEADER, 0); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "PUT"); curl_setopt($ch, CURLOPT_POSTFIELDS, "a_string_like_field=value&field2=value2"); $result= curl_exec($ch); curl_close($ch); Of course, this points out yet ANOTHER problem... there is no CURLOPT_PUTFIELDS! Since the format is the same, I assume my way should work, but I cannot even get to test it until I have a way of getting to the PUT parameters from within PHP. So, to resume it all, it seems to me: * there should be $_PUT and $_DELETE arrays * curl should support CURLOPT_PUTFIELDS, *or* make it clearer that CURLOPT_POSTFIELDS is to be used. Hope I was clearer this time! Best regards, Federico Kereki [2006-06-02 19:28:33] m...@php.net Not enough information was provided for us to be able to handle this bug. Please re-read the instructions at http://bugs.php.net/how-to-report.php If you can provide more information, feel free to add it to this bug and change the status back to "Open". Thank you for your interest in PHP. The remainder of the comments for this report are too long. To view the rest of the comments, please view the bug report online at https://bugs.php.net/bug.php?id=37681 -- Edit this bug report at https://bugs.php.net/bug.php?id=37681&edit=1
Req #55815 [Com]: PUT request data should be parsed just like POST
Edit report at https://bugs.php.net/bug.php?id=55815&edit=1 ID: 55815 Comment by: catch dot dave 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: 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). Previous Comments: [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
[PHP-BUG] Req #55815 [NEW]: PUT request data should be parsed just like POST
From: Operating system: All PHP version: 5.4.0beta1 Package: Streams related Bug Type: Feature/Change Request Bug description:PUT request data should be parsed just like POST 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: 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 bug report at https://bugs.php.net/bug.php?id=55815&edit=1 -- Try a snapshot (PHP 5.4): https://bugs.php.net/fix.php?id=55815&r=trysnapshot54 Try a snapshot (PHP 5.3): https://bugs.php.net/fix.php?id=55815&r=trysnapshot53 Try a snapshot (trunk): https://bugs.php.net/fix.php?id=55815&r=trysnapshottrunk Fixed in SVN: https://bugs.php.net/fix.php?id=55815&r=fixed Fixed in SVN and need be documented: https://bugs.php.net/fix.php?id=55815&r=needdocs Fixed in release: https://bugs.php.net/fix.php?id=55815&r=alreadyfixed Need backtrace: https://bugs.php.net/fix.php?id=55815&r=needtrace Need Reproduce Script: https://bugs.php.net/fix.php?id=55815&r=needscript Try newer version: https://bugs.php.net/fix.php?id=55815&r=oldversion Not developer issue: https://bugs.php.net/fix.php?id=55815&r=support Expected behavior: https://bugs.php.net/fix.php?id=55815&r=notwrong Not enough info: https://bugs.php.net/fix.php?id=55815&r=notenoughinfo Submitted twice: https://bugs.php.net/fix.php?id=55815&r=submittedtwice register_globals: https://bugs.php.net/fix.php?id=55815&r=globals PHP 4 support discontinued: https://bugs.php.net/fix.php?id=55815&r=php4 Daylight Savings:https://bugs.php.net/fix.php?id=55815&r=dst IIS Stability: https://bugs.php.net/fix.php?id=55815&r=isapi Install GNU Sed: https://bugs.php.net/fix.php?id=55815&r=gnused Floating point limitations: https://bugs.php.net/fix.php?id=55815&r=float No Zend Extensions: https://bugs.php.net/fix.php?id=55815&r=nozend MySQL Configuration Error: https://bugs.php.net/fix.php?id=55815&r=mysqlcfg
Req #55815 [Opn]: PUT request data should be parsed just like POST
Edit report at https://bugs.php.net/bug.php?id=55815&edit=1 ID: 55815 User updated by:catch dot dave 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: Whilst evert's example of providing access to the API might solve my original issue, I would still lean towards creating a new superglobal called _PUT. 1. PHP already has too many inconsistencies, let's not introduce another one. POST, GET exist, adding PUT is an obvious and consistant addition. Unless you wanted to deprecate existing superglobals over time, I would strongly suggest against providing a new way to do the same thing. 2. Whilst there are other HTTP methods, very few of them require/support parsing multi-form data like POST and PUT do (think of PATCH, DELETE, HEAD, etc). Previous Comments: [2012-10-31 15:09:47] evert at rooftopsolutions dot nl I just wanted to chime in this one.. I personally think that while having a _POST superglobal is convenient (and needed, for BC) it's not necessarily a great design pattern. Especially in the case where you actually want access to php://input, but PHP pre-emptively decided to parse it, and I'm left with an empty stream. So instead of extending this pattern to other HTTP methods (and don't kid yourself, there's a bunch more than just PUT [1]), I feel a much better alternative would be to expose the API that can actually parse multipart/form-data and takes a stream as input. I feel this would solve the OP's use-case, is more flexible, and avoids the creation of additional evil super-globals. [1] http://tools.ietf.org/html/draft-ietf-httpbis-method-registrations-10 [2012-10-22 05:23:06] tylerromeo at gmail dot com The http/1.1 RFC does not specify any data type for the request body of any request type, nor does the RFC for multipart/form-data specify the request type it must be used with in HTTP. And as has been demonstrated by previous comments, there exist legitimate cases where multipart/form-data would be useful in a PUT request. Let me first say that putting PUT data into $_POST is a bad idea. Hopefully that is obvious enough. If this were to be implemented, it should use $_PUT (and $_FILES, if necessary, along with it). The real question that needs to be asked is whether it's worth implementing. Technically, POST requests do not have any restriction on data types either. So really we could just tell all web developers to parse their POST requests from stdin like is suggested here for PUT. The reason PHP doesn't do that is because POST data is so often encoded in a standard data format and used as such that it helps developers tremendously to not force them to do such transformations themselves. So the issue is whether enough users will be using multipart/form-data in PUT requests to warrant developers implementing a feature for it. Personally, I'm a fan of uniformity, and I believe that if we're parsing the request body for a POST request, then a PUT request should be treated no differently unless the spec has a restriction (which it doesn't). [2012-07-08 18:38:30] johnston dot joshua at gmail dot com Hi, in regards to RFC 2616 and the comment: "What this means is the HTTP RFC does not allow us to identify multipart/form- data in a PUT request." This section addresses the meaning of the request URI and NOT the request body. In a POST request, the request URI should point to an entity that HANDLES the request body in whichever way it sees fit. This COULD be by appending the enclosed entity as an annotation to the given request URI, or appending a new entity to a collection, etc. In a PUT request, the enclosed entity should BE STORED AT or REPLACE the entity that exists at the given request URI. There is no reason why the Entity in question cannot be a multipart entity. Here is a real-world example to illustrate this point using a messageboard as an example. A User creates a new topic: (minimal headers shown for brevity) POST /topics HTTP/1.1 Content-Type: multipart/form-data; boundary=-- -11401160922046879112964562566 Content-Length: ??? -11401160922046879112964562566 Content-Disposition: form-data; name="comment" This is a comment here -11401160922046879112964562566 Content-Disposition: form-data; name=&quo