Slim: Slim v3 does not parse multipart/form-data from PUT requests
When sending a POST, I can fetch all the fields using $request->getParsedBody() and it works perfectly. With a similar PUT request, the body is null hence parsing fails.
This is a long story. Because it is so intertwined with HTTP and streams, I couldn’t easily write a failing testcase… 😢
$app->post('/test', function ($request, $response) {
var_dump($request->getParsedBody());
});
$app->put('/test', function ($request, $response) {
var_dump($request->getParsedBody());
});
Requests are sent using Google Chrome and with javascript:
var data = new FormData
data.append('foo', 'bar')
request('POST', '/test', data, function() {
console.log('POST success')
})
request('PUT', '/test', data, function() {
console.log('PUT success')
})
request (method, uri, data, callback) {
var request = new XMLHttpRequest()
request.open(method, uri, true)
request.onload = function() {
if (request.status >= 200 && request.status < 400) {
callback(request);
}
}
request.send(data)
}
The POST does show an array ['foo' => 'bar'], the PUT is null. Checking php’s input (php://input) marks clearly the input is there (also, Chrome devtools show this as expected). As Slim\Http\Body is a slight wrapper around streams, I started digging in Slim\Http\Request::getParsedBody():
public function getParsedBody()
{
echo "getParsedBody()\n";
if ($this->bodyParsed) {
echo "Has already parsed body\n";
return $this->bodyParsed;
}
if (!$this->body) {
echo "Has no body\n";
return;
}
$mediaType = $this->getMediaType();
$body = (string)$this->getBody();
if (isset($this->bodyParsers[$mediaType]) === true) {
echo "Has parser\n";
$parsed = $this->bodyParsers[$mediaType]($body);
if (!is_null($parsed) && !is_object($parsed) && !is_array($parsed)) {
throw new RuntimeException('Request body media type parser return value must be an array, an object, or null');
}
$this->bodyParsed = $parsed;
} else {
echo "Has no parser\n";
}
echo "Ready to return body\n";
return $this->bodyParsed;
}
Output:
// POST: iterating double and 2nd time it has the body parsed?
getParsedBody()
Has no parser
Ready to return body
getParsedBody()
Has already parsed body
// PUT: no parser, single iteration
getParsedBody()
Has no parser
Ready to return body
About this issue
- Original URL
- State: closed
- Created 9 years ago
- Reactions: 3
- Comments: 16 (7 by maintainers)
I think that if someone needs
multipart/form-datain a PUT request, then they can write their own media type parser and register it with theRequestobject.@micheh kinda weird answer imho. Slim is a general purpose framework, it should not be opinionated in the case it does not allow PUT or DELETE requests with multipart/form-data bodies. If you want to support all common HTTP verbs and support all common body encodings, it should be part of Slim.
Either way, I have done like @akrabat said already, it’s now a custom parser in my own app. If anyone need this for their own use in the future, just ping me and I’ll explain.
application/x-www-form-urlencodedis no good if you want to send binary data…It should be noted if you are using the _METHOD overloads that, this is not an issue iirc.