Support parsing urlencoded request body (RequestBodyParserMiddleware)#220
Conversation
| /** | ||
| * @param bool $keepOriginalBody Keep the original body after parsing or not | ||
| */ | ||
| public function __construct($keepOriginalBody = false) |
There was a problem hiding this comment.
Shouldn't this be true by default to replicate PHP's default behaviour (and that of most PSR-7 implementations)?
There was a problem hiding this comment.
I agree 👍 I'd also vote to completely remove this parameter for now as the motivation is a bit unclear, plus we can still add this in a follow-up PR.
|
I'd prefer a dedicated |
I'd also prefer a dedicated middleware per type but on the other |
| } | ||
|
|
||
| try { | ||
| $value = $this->types[$type]; |
There was a problem hiding this comment.
$value might be a bit unclear here. Maybe something more readable like $request = $parser($request) ?
| /** @var ServerRequestInterface $request */ | ||
| $request = $value($request); | ||
| } catch (\Exception $e) { | ||
| return $next($request); |
There was a problem hiding this comment.
Should we log somehow the parsing failure?
There was a problem hiding this comment.
We could allow a PSR-3 logger as constructor argument and log errors to it, or emit errors as Server does
There was a problem hiding this comment.
It'd be interesting what PHP's behaviour is in case of invalid request bodies. I think we should probably follow that behaviour.
|
@jsor @christoph-kluge The thing is this set up allows us to add more types in the future, infect I already have a multipart PR ready for when this PR is merged: final class RequestBodyParserMiddleware
{
private $types = array();
public function __construct()
{
$this->addType('application/x-www-form-urlencoded', function (ServerRequestInterface $request) {
$ret = array();
parse_str((string)$request->getBody(), $ret);
return $request->withParsedBody($ret);
});
$this->addType('multipart/form-data', function (ServerRequestInterface $request) {
return MultipartParser::parseRequest($request);
});
$this->addType('multipart/mixed', function (ServerRequestInterface $request) {
return MultipartParser::parseRequest($request);
});
}
} |
|
@WyriHaximus That would be the |
|
@jsor With solid defaults, which can be extended. But I get your point will file a PRs for both |
|
After discussing this PR with @clue and @jsor we decided to go with a slight alteration in this middleware. or view command line instructions: removing the ability to add additional parsers for custom types and only to include parsers for body types from the HTTP 1.0/1.1/2.0 specs. I'll add documentation later today |
|
|
||
| ```php | ||
| $middlewares = new MiddlewareRunner([ | ||
| new RequestBodyParserMiddleware(), |
There was a problem hiding this comment.
Should probably have added the RequestBodyBufferMiddleware before to document the requirement.
| { | ||
| $type = $request->getHeaderLine('Content-Type'); | ||
|
|
||
| if ($type === 'application/x-www-form-urlencoded') { |
There was a problem hiding this comment.
I'm trying to find out since ever if header field values are case-sensitive. I'm talking only about the values, as header names are clearly defined case-insensitive. I've only found some definitions for specific header values, eg. for Connect or Transfer Coding names.
Not sure, but it probably won't hurt to lowercase $type here.
There was a problem hiding this comment.
Not sure either, but I've updated the middleware forcing it to lowercase 👍
There was a problem hiding this comment.
For the reference: This change is correct 👍 Header field values are not case-insensitive per se, but only for certain header field names, including this one:
The type, subtype, and parameter name tokens are case-insensitive.
https://tools.ietf.org/html/rfc7231#section-3.1.1.1 and https://tools.ietf.org/html/rfc1866#section-8.2.1
README.md
Outdated
|
|
||
| #### RequestBodyParserMiddleware | ||
|
|
||
| Another built-in middleware is `RequestBodyParserMiddleware` which takes a fully buffered request body |
There was a problem hiding this comment.
I think this should read just
The
RequestBodyParserMiddlewaretakes a fully buffered request body...
Referring to previous paragraphs and repeating "built-in middleware..." might be become tedious once we add more and more middleware.
|
@WyriHaximus as successor of #223 this PR is now missing the multipart parts? Will multipart be another middleware or integrated here? |
|
@andig multipart will be filed in a follow up PR once this one is in. |
|
I like the direction this PR is heading and agree that it makes sense to keep "default body parsers" ("what PHP does") in a single middleware because it's unlikely a consumer would want to access individual parsers anyway. As described by @WyriHaximus, multipart handling will be added to the same code base in a separate PR. I'm currently in the process of rebasing and squashing some of these changes and will update this PR with some added tests. Other than that, this LGTM |
| { | ||
| $type = strtolower($request->getHeaderLine('Content-Type')); | ||
|
|
||
| if ($type === 'application/x-www-form-urlencoded') { |
There was a problem hiding this comment.
Feel free to copy from here :) https://github.com/slimphp/Slim/blob/3.x/Slim/Http/Request.php#L204-L241
Great work btw :)
There was a problem hiding this comment.
|
@clue awesome 🎉 |
91d8d5c to
a0c8de7
Compare
clue
left a comment
There was a problem hiding this comment.
Nice! 🎉 I've rebased your changes and squashed a number of related commits after adding some tests to ensure this has 100% coverage, now let's get this in! ![]()
|
|
||
| use Psr\Http\Message\ServerRequestInterface; | ||
|
|
||
| final class RequestBodyParserMiddleware |
There was a problem hiding this comment.
I would like to not see final in this case. There are literally a metric ton of different request body formats and this is rather limiting (from the perspective of a http framework). XML, Json, form-urlencoded are only the most popular however there are many custom encodings as well.
For framework usage it would be nice to be able extend.
Also it's possible to have a mixture of encoding types inside an application (I know it sounds weird, but it happens... a lot).
There was a problem hiding this comment.
@geggleto going to provide a third party middleware that allows this as I also have a use for it 😄
There was a problem hiding this comment.
Body parser for #215
To be used with #216
Todo: