Support for Drupal 7 is ending on 5 January 2025—it’s time to migrate to Drupal 10! Learn about the many benefits of Drupal 10 and find migration tools in our resource center.
If an entity representation (JSON-LD, XML etc.) is received and deserialized to an entity object we should make sure that the fields on the entity are valid. This has to be done on write operations that create or update on entity ==> POST, PATCH and PUT in our case.
Example: A node title must not be longer than 256 characters. If a node is submitted with a title length of 257 characters the node should not be saved and a HTTP response with status 400 should be returned.
Before we can start to implement this we need a working entity validation system in place. Issues:
Comment | File | Size | Author |
---|---|---|---|
#13 | rest-validation-1910658-13.patch | 4.97 KB | klausi |
#13 | rest-validation-1910658-13-interdiff.txt | 3.77 KB | klausi |
#5 | rest-validation-1910658-5.patch | 4.61 KB | klausi |
#5 | rest-validation-1910658-5-interdiff.txt | 2.56 KB | klausi |
#2 | rest-validation-1910658-2.patch | 2.03 KB | klausi |
Comments
Comment #1
effulgentsia CreditAttribution: effulgentsia commentedComment #2
klausiHere is a first patch that adds the validate() invocation to the entity resource plugin.
TODO: test case that actually triggers a constraint violation (e.g. for nodes), so this depends on #2002156: Create validation constraints on nodes to entity validation.
Comment #3
moshe weitzman CreditAttribution: moshe weitzman commentedAdd tag.
Comment #4
moshe weitzman CreditAttribution: moshe weitzman commentedComment #5
klausiActually we can use a test for an over long UUID to trigger one example validation error response. Note that we only want to test an example here, the rest should be tested with explicit entity validation API tests for every entity (as we are doing already in the various issues outlined in #1696648: [META] Untie content entity validation from form validation.
Comment #6
BerdirDoesn't need to be here but is it possible to provide a separate validate possibility? There are many use cases where you just want to check if the object you have (maybe a user is changing it) is still valid, without actually submitting it.
Comment #7
klausiInteresting idea. No, that is currently not planned nor supported by core's REST module. Not sure how that could be implemented - maybe with a URL request parameter like POST /entity/node/1?validate_only=1 ?
Comment #8
BerdirTried to google this a bit, what I found is http://restfulobjects.org/download/. They define validation like this:
That x-ro-validate-only argument is not a GET argument, but is part of the body payload, older versions of that spec also used a HTTP header I think. Not sure if part of the payload is possible for us, but mixing POST and GET arguments sounds like a bad idea :)
Comment #9
klausiMixing the serialized body with request metadata is bad idea, too, we are not going to do that.
You could also use GET for the validation operation, since it does not change any data. It is just a bit uncommon to send a request body along with a GET request, but I think it does not violate the HTTP spec.
Or you could use a custom HTTP header like X-Validate-Only.
422 instead of 400 as response code on validation errors sounds interesting, looks like it is part of WebDAV; RFC 4918. Should we use that?
Comment #10
corvus_ch CreditAttribution: corvus_ch commentedI consider it quite valid to use a data transfer object in a service that also holds metadata.
Since we have guzzle as part of core, no we can't. Guzzle does not support to add body data in a GET request. See https://github.com/guzzle/guzzle/blob/master/src/Guzzle/Http/Message/Req... and https://github.com/guzzle/guzzle/blob/master/src/Guzzle/Http/Message/Req....
Using the query string certainly will exceed the limit of the url length. And it will be a data leak when using https.
The HTTP standard is unclear about this. The result will be at least unpredictable. See http://redmine.lighttpd.net/boards/2/topics/3346. I am not sure if Lighttpd still does not allow a message body in a GET request but there are others (see Guzzle).
That certainly is an option. I am not sure if I really like it or not.
Personally I would prefer to go with the suggestion of RestfullObjects or at least something similar. We already have meta data in the body coming from HAL. I feel we could really profit from adding metadata as an embedded resource. There certainly will come other use cases this will come in handy. Using it for validation is just one use case I can see and it is the approach that leaves room for other use cases.
Sure. We should get the maximum out of the HTTP standard. Using all available response codes were ever they makes sense will make things a lot easier for error handing.
Comment #11
klausiIn REST the body contains a representation of a resource and nothing else. Sure, the data contains references and hypermedia controls pointing to other resources, but it never contains metadata about the current request.
The use case of validation only sounds like you would use a separate resource for that: POST to /entity/node/validation or PATCH to /entity/node/1/validation feels like a better fit.
I agree that query parameters on POST and a body on GET requests are also wrong, so the alternative would be to use a custom HTTP header or a custom media type used by an Accept header like application/vnd.drupal.validation+json.
Comment #12
corvus_ch CreditAttribution: corvus_ch commentedWhat is in the body and what not is the freedom of the service architect. Working directly with the entity is fine. Using a DTO is too. Think about attributes you do not want to expose for security reasons or because they are calculated based on some business rules. Or it may also be that the entity you expose through a service does not exist on the server but is built up from several ones. I agree that for Drupal normally this should not be the case.
I can live with that.
That I also can live with.
I disagree. By using Accept you tell the server what you would like to have as a response format. There is no guarantee that you will get it and it is also not meant to tell the server to change its behavior.
If I must choose between HTTP header and validation resource, I would choose the resource.
Comment #13
klausiPutting the (interesting) validation resource discussion aside, please open a separate issue for that.
Here is a rerolled patch that uses 422 in the validation error case.
Comment #14
moshe weitzman CreditAttribution: moshe weitzman commentedLooks good to me. If we reroll this, I think we could remove the text ""Unprocessable Entity". I think "Entity validation failed" works better.
Comment #15
alexpottCommitted dc3ba2b and pushed to 8.x. Thanks!
re #14 "422 Unprocessable Entity" is a http status message see https://en.wikipedia.org/wiki/List_of_HTTP_status_codes so looks good to me.
Comment #16.0
(not verified) CreditAttribution: commentedadded issue