Problem/Motivation
It's not clear how to POST a comment (and probably other entities having relations like book page, entity referenced entity).
Submitting a node by following the REST+HAL node POST on https://www.drupal.org/node/2098511 is running ok.
Trying to accomplish this for a comment fails with 422 Unprocessable Entity code without the build message by EntityResource::validate()
Adding throw new \RuntimeException($message); like
protected function validate(EntityInterface $entity) {
...
throw new \RuntimeException($message);
throw new HttpException(422, $message);
}
}
reveils in apache error log in my case shows
Uncaught PHP Exception RuntimeException: "Unprocessable Entity: validation failed.\nentity_id: This value should not be null.\n" at /.../core/modules/rest/src/Plugin/rest/resource/EntityResource.php line 214
What must I do now?
Proposed resolution
This needs documentation and debugging tools for REST client builders.
Remaining tasks
- Write documentation
- Move forward #1925618: Ensure Drupal's web services are self-documenting: Swagger support OR rest_api_doc to Drupal core as an experimental module?
- Should we throw an error or provide a JSON error struct as discussed in #1996130: REST views: not adding dependencies on Serializer providers and #1916302: RFC 7807: "Problem Details for HTTP APIs" — serve REST error responses as application/problem+json
Collateral issue:
- Is Symfony in err not using getMessage()? File a bug for Symfony?
Comments
Comment #1
clemens.tolboomComment #2
larowlanDoes it help to create a comment in the ui and then export it? That format should be what needs to be sent back.
Comment #3
clemens.tolboomI rewrote my code to always 'relay' a comment. That made it progress a little
Still degugging through apache errorlog
give
Editing the comment through site results into a exection for my testing tool
which is cause by $entity->save()
Removing the UUID from the json fixed it finally.
So how to move on with these DX hickups?
Comment #4
clemens.tolboomDeleting all nodes and comments then trying to POST new data failed on the comment as I did not know it's node yet.
For linking the comment to the new node I had to change an entry in "_embedded". Why? Where is that documented?
Comment #5
clemens.tolboomComment #6
vivekvpandya commentedPOSTING comment on /entity/comment works for me with proper permission and Authorization header.
here is JSON for the same
Comment #7
clemens.tolboom@vivekvpandya thanks for the update. Did you found some documentation on this? Esp. on node__comment and entity_id.
Do you mind to test #1925618: Ensure Drupal's web services are self-documenting: Swagger support OR rest_api_doc to Drupal core as an experimental module? where ie
currently don't have that information.
Comment #8
vivekvpandya commented@clemens.tolboom
REST and related modules are lacking with documentation badly, What I do is every time first I will try to execute GET on specific REST endpoint with Accept-Type as 'hal+json' then I analyze the response and try to POST on same REST endpoint and try various combinations and eventually I find out minimal "hal+json" for POST different entities.
I will test test your patches on issue #1925618 give me some time I am not regular PHP developer I am working on "example iOS app for Drupal 8".
Comment #9
clemens.tolboom@vivekvpandya I document my steps @ https://github.com/build2be/drupal-rest-test :)
Comment #10
kylebrowning commentedI get this error when trying to post a comment,
Drupal\Component\Plugin\Exception\PluginNotFoundException: The "" entity type does not exist. in Drupal\Core\Entity\EntityManager->getDefinition() (line 227 of /Users/kylebrowning/Development/PHP/drupal-8/core/lib/Drupal/Core/Entity/EntityManager.php).
Comment #11
dawehnerAre you sure you used hal+json not only for the getting but also for the posting?
Comment #12
vivekvpandya commented@kylebrowning
Are you trying on localhost ? if yes then your please check for your URLs in your JSON object. : )
Comment #13
kylebrowning commentedYes its localhost.
It still doesn't seem to be working.
Comment #14
kylebrowning commentedComment #15
berdirYou need to post the actual error, enable error display or check watchdog.
From looking at this, it is at least missing the correct entity_type and field_name.
Comment #16
kylebrowning commentedDrupal\Component\Plugin\Exception\PluginNotFoundException: The "" entity type does not exist. in Drupal\Core\Entity\EntityManager->getDefinition() (line 227 of /Users/kylebrowning/Development/PHP/drupal-8/core/lib/Drupal/Core/Entity/EntityManager.php).
Whats the correct entity type, this information doesn't seem to be document anywhere, At least I haven't found it yet.
Comment #17
berdirThe correct entity_type is whatever you want to add the comment to. node, if it's for nodes.
The easiest way to create comments should be to create one in the UI and then GET that through rest.
Comment #18
kylebrowning commentedThank you!
Comment #19
kylebrowning commentedExample of working post
Comment #20
clemens.tolboomWith the patch [edit] #1964034: Pass entity_type into Serializer via context
#2100637: REST views: add special handling for collections[/edit] we managed to post a comment through json.See our code on https://github.com/build2be/drupal-rest-test/blob/8.x/post-rest.php
@kylebrowning do you mind updating https://www.drupal.org/node/2098511
Comment #21
clemens.tolboomWe should concentrate on #2469581: Add tests for comments CRUD for REST as we are chasing head fixing posting a comment.
Comment #22
droti commentedWhen I post a comment it always shows up as from an "Anonymous User" which is strange because I can post an article and don't have that problem. Does anyone else have this problem?
Comment #23
vivekvpandya commented@droti
I think have faced similar problem. Despite of specifying authentication details it posts comment for "Anonymous User". But I have found the work around at that time ( about a year ago ) I have mentioned User relation in "_links" section it self. However it should not be like this because due to this a user with sufficient privilege can post comments for any other user.
Consider following JSON for it.
Comment #24
droti commented@vivekvpandya, that didn't work for me but I did get it by specfiying a UID, you can see the ecample below:
I'm not really happy with that but it'll do for now.
Comment #25
vivekvpandya commented@droti
As I mentioned in my previous post that I have supplied user id in "_links": section specifically see the code below.
I hope this will work.
Comment #26
vivekvpandya commented@droti
For me following JSON works fine and it also identifies the user who posted the comment
Comment #27
wim leersI'll be working on REST documentation tomorrow.
Comment #28
rashid_786 commentedI am able to create the comments using above format but unable to create child comment as a reply?
Comment #29
rashid_786 commentedOk i have fixed this by adding pid as follows with above format:
"pid": [
{
"target_id": any comment id
}
],
Comment #30
droti commentedSo I was able to create comments using the above example via postman. However I just integrated this into my webapp and get {"error":"Access denied on creating field 'uid'"}.
Which totally makes sense because you can just post a comment from anyone if you knew what you doing.
It would be really nice if this could pick up the user from the token.
Comment #31
droti commentedI hate to be asking question after question, but I'm having problems with caching now. Here is the data I'm posting:
But I get a 500 error and the error looks like this:
If I comment that out, then I'm good but I'm not sure how prevent this caching from happening...
Comment #32
clemens.tolboom@droti search for issues with https://www.drupal.org/project/issues/search/drupal?text=cache&assigned=... I see 2 having comment in their description.
#2631774: Impossible to update Comment entity with REST (HTTP PATCH): bundle field not allowed to be updated, but EntityNormalizer::denormalize() requires it
#2678682: Getting 500 Internal Error while running comment update resource service
How you can help resolve one :)
Comment #33
droti commentedThank so much! I tried searching but I was not looking in the right spots! That patch did the trick for me.
Comment #35
kier.heyl commentedI just wanted to second @droti and @vivekvpandya.
Currently when you post a comment using basic_auth you create an anonymous comment.
If you're authorizing with an user who has privileges to administrate comments you can pass in a uid, but this is not and should not be available to basic authenticated users.
Desired fix would be that it assigns the created comment to the authenticated user in the same way a created node is done.
Does this need to be a separate ticket?
Comment #36
clemens.tolboom@kier.heyl Is there a difference when creating a session based comment?
Comment #37
kier.heyl commented@clemens.tolboom
I tried it with basic auth, and cookie auth. In both cases despite requiring authentication to post a comment, neither one actually associates the comment with the authenticated user.
Comment #38
wim leersClarifying title, and marked #2676206: How to POST an "entity reference" field to a node ? as a duplicate of this one.
Comment #39
jacov commentedI updated documentation on POST & PATCH pages using examples with 'article' taxonomy entity reference field;
see full documentation here:
https://www.drupal.org/documentation/modules/rest/post
https://www.drupal.org/documentation/modules/rest/patch
and snippet POST ent_ref code example here:
Comment #40
clemens.tolboom@jacov thanks for the update.
Can you use the long options for your curl commands: -k -i -s is a little alien for curl savvies.
Any idea why we only document POST/PATCH using _format=hal_json and not plain _format=json?
Comment #41
jacov commented@clemens.tolboom afaik hal_json format allows many to many nesting, required for joining entities via _link / _embed
Comment #42
wim leersThanks, @jacov. I cleaned up your language/explanations/example: https://www.drupal.org/node/2098511/revisions/view/9909399/9910159.
And because @jacov provided a concrete example, that meant I just had to do touch-ups, so now effectively this missing documentation has been written. So we can finally close this issue :)
Comment #44
pranil_kochar commentedDoes anybody know how to create a user in drupal using rest apis??...
im using post man and my url is "http://localhost/entity/user"
i m not able to form a request body for this ...
Comment #45
pranil_kochar commented@vivekvpandya can u please tell me how to make PATCH request for comments in drupal.
for the PATCH request do we need to change the request body, we formed while creating the comment?
Comment #46
pranil_kochar commented@vivekvpandya,
my url: http://localhost/comment/7 (PATCH)
Content-Type:application/hal+json
Accept:application/hal+json
Authorization:Basic cHJhbmlsOnJvb3Q=
and REQUEST body:
{
"_links": {
"type": {
"href": "http://localhost/rest/type/comment/comment"
},
"http://localhost/relation/comment/comment/entity_id": [
{ "href": "http://localhost/rest/type/comment/comment/node/10"}
]
},
"entity_id": [
{
"target_id": "10"
}
],
"langcode": [
{
"value": "en"
}
],
"subject": [
{
"value": "aaaaaaaaaaaaaaa......"
}],
"uid":[
{
"target_id": 1
}
],
"status": [
{
"value": "1"
}
],
"entity_type": [
{
"value": "node"
}
],
"comment_type": [
{
"target_id": "comment"
}
],
"field_name": [
{
"value": "comment"
}
],
"comment_body": [
{
"value": "................."
}
]
}
ERROR i m GETTING:
{
"error": "Access denied on updating field 'entity_id'."
}
All my permissions are checked...
Comment #47
vivekvpandya commentedHi, @pranil_kochar
For patch request it is not necessary to submit all details that you used while creation but what is necessary is required to be decide by looking at code or by trail and error.
If you read the error message carefully than you will find that your request is trying to change entity_id which is something not allowed in any database based system (i.e primary key) so you need to find out what things are required to be specified for update operation.
My hunch is that with PATCH request URL you are already specifying entity id than remove entity_id from the request body.
Just to give analogous example consider PATCH request body for update the user details
Here User id is specified with in the URL of patch request.
Let me know if this help.
Vivek
Comment #48
pranil_kochar commentedHi, @vivekvpandya
thanks for u r suggestion
now its working fine with the request body:
{
"langcode":[{"value":"en"}],
"subject":[{"value":"UPDATED Subject"}],
"uid":[{"target_id":"1","url":"/localhost/user/1"}],
"status":[{"value":"1"}],
"comment_type":[{"target_id":"comment"}],
"default_langcode":[{"value":"1"}],
"comment_body":[{"value":"updated11"}]
}
Comment #49
pranil_kochar commented@vivekvpandya,
Why some time we use request body in "_link" format and sometime in simple JSON format??
like to create a comment we have used "_link" format but to update the comment we have used simple JSON format? is thr any specify reason?
and have you created a "user" using REST apis? if yes then could you please share your request body if possible?
Comment #50
vivekvpandya commented@pranil_kochar you are welcomed.
"_link" are used to specify relationship among entities and it is usually used by the REST client to figure out various related REST end points. This is also known as HATEOS in terms of REST architecture and for Drupal it is implemented as HAL module so for this type of request/response we need to pass a header value of Content-type = "application/hal+json"
Please read more about REST standards you will get to know more about it. So yes we only use hal+json when it makes sense.
Yes I have created "user" resource with REST API but I don't have a full JSON with me but I am providing you Objective-C code which builds JSON for my application.
It is very simple and that should be enough to help you out.
I hope this will help.
Please let me know if you don't understand any thing.
Comment #51
pranil_kochar commented@vivekvpandya,
thanx man ... u really helped me a lot..
In all thr are 3 objects only right? in drupal(comments,node,user)?
Comment #52
vivekvpandya commented@pranil_kochar welcome any time!
These 3 are basic concepts but Drupal is very powerful and it has other configuration entities too and REST also exposes services for them and Drupal has plans to make this support very robust.
Comment #53
pranilkochar commented@vivekvpandya
thanx a lot.
DRUPAL 8 supports Oauth 2.0 as an authentication mechanism?
if yes, then what all modules we have to include?
Comment #54
prabhakarb commentedHere is the Solution. Working fine.
POST : http://YOURSITE.com/entity/comment?_format=hal_json
Headers:
Accept : application/json
Content-Type : application/hal+json
X-CSRF-Token : get by hitting http://YOURSITE.com/rest/session/token
Optional headers:
Authorization : Basic YZBWdYNJcjpwYXNzQDEyMw==
JSON formatted data to send to Drupal
Comment #55
pim2016 commented@ Prabhakar: Works like charm - unfortunately am not allowed to set username or uid get a 403… All comments created like this are by the anonymous user.
Comment #56
pim2016 commented@ Prabhakar:
Works like charm, but I am not able to set username or uid - get a 403 then. So this way it is only püossible to post anonymous comments.
Any idea how to manage this?
… ok found out myself:
Comment #57
hubobbb commentedhi ,prabhakarb . I use RESTful but ,I get 403 forbidden with Drupal8.3.2 .
if I donot set "name":[{"value":""}], and post sucessful ,but comment's UID is 0.
so I use the services module to do this ,but get the same 403 forbidden .
at last ,I close services 8.4.0
CSRFTokenAccessCheck.php
... if(!\Drupal::csrfToken()->validate($csrf_token, 'services'))..
temp to go on dev .
can anyone help this .
Thankyou .
Comment #58
hubobbb commentedand i work well like this .
remove :
"entity_id":[{"target_id":}],
"entity_type":[{"value":"node"}],
,rest cannot let you edit entity field .
Comment #59
taggartj commented8.4 POST /entity/comment?_format=json
X-CSRF-Token,
Content-Type: application/json
Authorization: Basic codehere
entity_id = node id
thanks @prabhakarb
{ "entity_id": [{ "target_id": 1 }], "entity_type": [{ "value": "node" }], "comment_type": [{ "target_id": "comment" }], "field_name": [{ "value": "comment" }], "subject": [{ "value": "Goodbye World" }], "comment_body": [{ "value": "comment which you want write" }] }