Closed (fixed)
Project:
Drupal core
Version:
8.0.x-dev
Component:
rest.module
Priority:
Major
Category:
Feature request
Assigned:
Unassigned
Issue tags:
Reporter:
Created:
13 Nov 2012 at 13:45 UTC
Updated:
29 Jul 2014 at 21:30 UTC
Jump to comment: Most recent, Most recent file
Comments
Comment #1
klausiTagging.
Comment #2
webchickThis seems pretty important to having web services in core.
Comment #3
klausiHere is the first patch, based on #1834288: RESTfully request an entity with JSON-LD serialized response.
Note that we currently have to create 2 routes per resource operation, because of a limitation in our current route dumper:
De-serialization is not ready yet, so this patch simply creates a dummy test entity on incoming POST requests for testing.
Comment #4
klausiNew patch: instead of 2 routes we do special case POST requests now, which have no ID in our entity creation scenario. Other resource plugins can of course overwrite the ResourceBase::routes() method altogether and provide any routes they want. This is just about providing sensible defaults that also match our entity use case.
Comment #5
klausiTagging for Crell.
Comment #6
Crell commentedThis is worded awkwardly. "Special case for resource creation via POST" would make more sense, I think.
Typo. "available".
That said, I don't see why naming this plugin vs. _plugin is in any way related to the routing issue... It's an internal value with magic meaning not intended for use in the signature of the controller callable. So it gets an _ prefix.
Pedantic nitpick. $result is usually used only when we are getting back an interatable result object. In this case, we're getting back a single record. So, this should be called $record.
I am not comfortable with this sort of flagging. "Pass NULL to mean this thing or pass something else to mean this other thing" is a code smell.
This reads oddly. I think you mean "201 Created responses have an empty body." (Otherwise it sounds like "Create" is a verb, not a noun.)
I think resolving this to not hard code entity_test is an RTBC blocker.
Doesn't the Response class have a getContent() method that works just as well? I'm confused why this is necessary.
False. :-) Test method should test one thing each, only. If there's common setup that needs to be done for them, that's what the setUp() method is for.
Comment #7
klausiCurrently it is used on the method signature of the controller, so leaving it as is for this issue. We should fix that in a follow-up independently of this issue.
The responseData property in ResourceResponse is used to indicate if serialization should be done (value/object present ==> serialize; NULL ==> do not serialize). You mean we should add an additional boolean property that is more explicit? $serialize = TRUE/FALSE that has to be passed to the constructor?
Agreed. So we should get #1838596: Add deserialize for JSON-LD in as soon as possible.
Yes, we discussed simply using the Response class. But since the contract of that class implies that the content must either be a string or an object with a __toString() method we decided to use our own class. We have arbitrary data that does not have to be __toString() compatible. So we would heavily abuse Response if we first put data objects int the $content, then pulling them out, serializing them and pushing them back into $content.
If that were unit tests I would agree. But executing WebTestBase is expensive and installing Drupal again just to test inactive resources does not make sense. So I recommend to keep it this way.
Comment #8
klausiSimple reroll, after #1834288: RESTfully request an entity with JSON-LD serialized response got committed. No other changes.
Comment #8.0
klausiadded link to sandbox
Comment #9
klausiNew patch that includes #1838596: Add deserialize for JSON-LD. Deserialization does not fully work yet, so this contains some ugly workaround hacks in jsonld module. The REST module side should be ready now.
Comment #10
klausiUpdated patch: removed the very cruel hacks I did to jsonld module, interdiff contains only changes against #1838596: Add deserialize for JSON-LD. It works with minor restrictions now!
Comment #12
klausiRerolled patch on top of #1838596: Add deserialize for JSON-LD. Added entity type verification before creating the entity, improved request handler documentation.
Comment #14
klausiRerolled patch on top of #1838596: Add deserialize for JSON-LD.
Comment #16
klausiOf course, we need to remove the currently obsolete jsonld_test module from the test.
Comment #18
klausi#16: rest-post-1839346-16.patch queued for re-testing.
Comment #19
moshe weitzman commentedLooked at the small recent interdiffs and decided that this one is RTBC too. Hopefully we can reroll this quickly its dependency #1838596: Add deserialize for JSON-LD goes in.
Comment #20
moshe weitzman commentedReroll after #1838596: Add deserialize for JSON-LD. I had to fix one conflict in ResourceBase.php that happened (I think) when we renamed to _plugin (with underscore). Hope I got it right.
Comment #21
dries commentedThis seems wrong, or at least weird.
Comment #22
effulgentsia commentedAs I mentioned in #1838676-27: Support dynamic entity type management, I think it would be better to pass the entity type for the 2nd parameter to deserialize() rather than the entity class. According to linclark in #1838676-30: Support dynamic entity type management, this parameter is required to be a class name, but I disagree: in the Symfony update that went in in #1834594-24: Update dependencies (Symfony and Twig) follow up fixes for Composer, the parameter got renamed to $type (in the interface, but not in some of Symfony's implementations), and regardless of its name, it just gets passed to the denormalizer, so it's up to the denormalizer to decide what meaning to give it. But, I'm ok with this patch going in as-is, and me taking up this issue in #1852812: Use cache to get entity type/bundle metadata from JSON-LD @type URI where some discussion of it is already under way.
Comment #23
effulgentsia commentedoops. didn't mean to change status.
Comment #24
moshe weitzman commentedRegarding lowercasing in #21, RestTestbase::httpRequest is lowercasing the headers that the web server sends. It does so for a good reason I'll comment its quote here
So I think this code is robust and reasonable. I assure you that the web server is sending Content-type (mixed case) as is conventional.
Thanks effulgentsia for agreeing to handle #22 in a follow-up.
Tests have passed so back to RTBC.
Comment #25
klausiThis will need some more research and is not committable at this point. Please be patient, I try to get back to this as soon as I have more details.
Comment #26
klausiWe have considered the implications of the current patch in our weekly REST call and decided to move this forward as is. We can fix outstanding issues in followup issues as they arise.
Back to RTBC, I also removed a temporary hack from the creation test case, which is fortunately not needed anymore.
Comment #27
damien tournoud commentedIs it me, or this is *very* sloppy? When we are going to have other operations on a collection (for example, GET), are we *also* going to have an empty variable being passed around? Couldn't we make the resource handler properly handle those collection operations instead of hacking around like this?
Also, in its current form, would the deserializer allow to set the entity id and revision id?
Comment #28
klausiEvery resource plugin operation has the same method signature:
rest.module is aimed at single entity operations currently, retrieving collections is a task for Views display plugins. See #1819760: Add a REST export display plugin and serializer integration.. Since the POST operation creates an entity in the entity resource plugin semantics it does not need the ID parameter and can ignore it.
The deserializer ignores the ID completely right now. I added an isNew() check before saving the new entity. I'm not sure about revision IDs, I think we can ignore them for now and we should create followup issues for that.
Updated patch attached.
Comment #29
damien tournoud commented@klausi: POST is a collection-level action, not a resource-level action. Those should not be handled the same way. It seems like the design needs to be fixed.
Comment #30
Crell commentedPOST is not a collection-level action inherently. It's "instructions presented to a resource for processing", where that processing is undefined by HTTP. There's no reason you can't POST to a resource.
Comment #31
effulgentsia commentedYes. But in the context of this issue, only a POST to create a new resource is implemented. I don't mind the extra unused $id in the signature, since it creates consistency with the other http methods in the module, though if a follow up wants to explore cleaning that up, that's cool too.
Comment #32
dries commentedIt seems like Moshe, Crell and others are fine with the implementation (myself included), despite DamZ not being fully on board with the implementation details. I decided to go ahead and commit this. We can do clean up in a follow-up patch if enough people care.
Comment #33.0
(not verified) commentedadded deserilaize dependency.