Hi,

2010/11/26 Nicolas A. Bérard-Nault <[email protected]>

> Hi,
>
> I am writing a test for a REST controller which uses the PUT http method.
> Here is an excerpt of code showing how Symfony 2's test client handles
> request parameters:
>
> if (in_array(strtolower($method), array('post', 'put', 'delete'))) {
>             $request = $parameters;
>             $query = array();
>             $defaults['CONTENT_TYPE'] =
> 'application/x-www-form-urlencoded';
> }
>
> Unfortunately, that is not PHP's default behavior for PUT. This works as
> expected for POST but not for PUT, as the request has to be explicitly read
> from php://input, as explained on
> http://php.net/manual/en/features.file-upload.put-method.php. According to
> my tests, the content body of the request is not parsed into $_POST when the
> method is PUT. The test client's behavior is different from PHP's behavior.
> Hence, I have two questions:
>
> 1) What would be the best way to support this in the test client ? I doubt
> it is possible for the test client to write on php://input so I fail to see
> what options we have there.
> 2) What would be the best way to support this  seamlessly with the Request
> object, considering that PUT can be used to send something else than files,
> especially in a REST context ?
>
> After crawling through the code, here are my conclusions, albeit rather
shallow.

The HttpFoundation\Request class' constructor has the following parameters:
    array $query = null, array $request = null, array $attributes = null,
array $cookies = null, array $files = null, array $server = null

The two first parameters are hashmaps that map directly to $_GET and $_POST.
Although sufficient for many applications, this is unfortunately a huge
limitation. It becomes very apparent when one deals with, for example, JSON
requests, which need to be read and parsed differently than url encoded
requests. $_POST is only meaningful in a very limited, although very common,
subset of requests bodies, namely url encoded key-values, mostly passed by
html forms.

The request can in fact be of any content-type and this is unfortunately
currently unsupported. Hence, when dealing with a JSON request:

1) In the code, it is impossible to use the Request object :
file_get_contents('php://input') has to be used directly to read the
content, which defeats the purpose of having an abstraction.
2) It is impossible to test any code that uses php://input as the test
client assumes url encoded data and does not provide any facility to hijack
PHP's stream.

My proposition is simple: the Request class should lay its bases closer to
the HTTP RFC rather than using PHP's superglobals.

1) For the request parameter, the default constructor should only accept
low-level, unparsed data. In the event that the content-type of the request
happens to be url-encoded, then it would be possible to obtain the parsed
array of parameters using a method on the object with code along the lines
of:

$urlencodedRequest =  file_get_contents('php://input');
$_POST == $queryParameters = parse_str($urlencodedRequest); // Equality only
there for illustration purposes

2) A factory method could be used to create a vanilla Request object with an
url encoded request body, which is really a "specification" of the much
broader concept of an HTTP request. Other such specifications (although I
can't think of any right now) could also warrant factory methods. Such a
method could use $_POST directly.

Now, I fear this is not trivial to implement and will need a lot of
discussions and love, which I'm ready to give in profuse amount. Since I'm
not that well acquainted with the framework, I'll need your advice and I
hence thank you in advance for your time.

NABN.


> Thank you for your comments,
> --
> Nicolas A. Bérard-Nault ([email protected])
>



-- 
Nicolas A. Bérard-Nault ([email protected])

-- 
If you want to report a vulnerability issue on symfony, please send it to 
security at symfony-project.com

You received this message because you are subscribed to the Google
Groups "symfony developers" group.
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/symfony-devs?hl=en

Reply via email to