-
Notifications
You must be signed in to change notification settings - Fork 56
add middleware to validate JSON request body with schema #44
Conversation
private function decodeBody(ServerRequestInterface $request) | ||
{ | ||
return json_decode($request->getBody(), $assoc = false); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I understand the reason of this, but I prefer to delegate the body parsing to other middleware instead. There's a Payload middleware available that, by default, parses the body to array, but we can provide a config setting to change this behaviour.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok that makes sense, i'll make a new commit.
]); | ||
|
||
if (!$validator->isValid()) { | ||
$response->getBody()->write(stripslashes(json_encode($validator->getErrors()))); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please, use the constants options like json_encode($validator->getErrors(), JSON_UNESCAPED_SLASHES)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ah, of course!
@oscarotero what do you think?
|
Mmm, I think I have not explained well. I mean to keep the body parsing process and the body validation process in two different components, so you have to do the following: $middeware = [
Middleware::payLoad(), //parse the body here
Middleware::jsonSchema($config), //validate the json here
]; Currently, $middeware = [
Middleware::payLoad(['assoc' => false]), //parse the body here passing options
Middleware::jsonSchema($config), //validate the json here
]; |
@oscarotero thanks for the feedback. i have implemented it per your suggestion. i have some followup questions based on my implementation:
|
Because they are settings passed to BodyParser (do not affect directly to
I'd change the transformer interface to the following signature: public function resolve($id, array $options = null); So, it's easy to update the other transformers to match this interface with no breaking changes.
I'm not sure. In theory, |
i can update the signature of the change will require an update to the |
Ok, fair enought. +1 to add this to the constructor. |
thanks! then i will add |
Right now, BodyParser always returns an array, so maybe a more json_decode independent option is better, so it can be supported also by csv and urlencode parsers. For example: public function __construct($forceArray = true) |
…d JSON schema files. route-matching is done by prefix.
ah, i do like that name better. i have also updated the BodyParams transformer to accept an extensible array of options, just like the Payload middleware which simply passes the options through. would you prefer to have BodyParams accept a single param? |
no, an array is good, to make it extensible. 👍 |
anything else you'd like me to do here? |
Sorry for the delay. Good job, thank you! 👍 |
no problem. i thought maybe i had forgotten something. thank you for letting me contribute to such a helpful library. |
hi @oscarotero , i had a followup conversation with another dev that i greatly respect and trust. he pointed something out in this merge request that i feel compelled to bring to your attention. the combination of json schema validation with routing encourages duplicate route specification in applications. i think i could easily split a simple single-schema validator from the existing implementation. this new validator would accept a schema as a constructor param. the existing validator-per-route implementation could be safely refactored to delegate to the simple validator. these two independent validators will give developers greater control. if any of that sounds good to you, or gives you some other ideas, i'll get right to work. i'll do my best to maintain compatibility. the name of the component i've outlined is the most challenging piece. i almost wish i had named the existing component JsonSchemaMulti. ah well. what do you think? |
@abacaphiliac As a user of this library, your last comment makes a lot of sense to me... having to split the route definition across multiple places (the routes list, and then duplicate it into the middleware definition) feels like definitions-out-of-sync related bugs waiting to happen. Thanks for taking the alternative into consideration! |
I'm fully agree with this but I think we should create a new different middleware to keep backward compatibility, let's say, for example, |
@sbol-coolblue @oscarotero thank you for the feedback. here is my preliminary work on the solution: #46 i need some more time to review myself, and to update docs, but wanted to get early feedback from you. let me know what you think. |
add JsonSchema middleware to validate request body using route-matched JSON schema files.
uses
justinrainbow/json-schema:>=3.0
. earlier versions resolve schema files differently and i chose not support it. i'd be happy to add support if requested.route-matching is performed by prefix, e.g.:
failed validation and malformed JSON will result in a short-circuited 422 response.
should the status code, message, and/or short-circuit behavior be configurable?