Including created resource in HTTP POST response? - rest

RFC7231 says a server should respond to a resource-creating POST request with status 201 and a Location header to the new resource. In some situations it could be convenient for the server to include a representation of the created resource in its response, but in other cases this would be a waste of bandwidth.
Might this be a good place for content negotiation within the post request? If so, what request headers should be sent to indicate that the client would like the resource returned in addition to the Location header?

I would suggest using the "Prefer" header:
Request:
PUT /xxx
Prefer: return=representation
Response:
201 Created
{ ... created resource representation ... }
See https://www.rfc-editor.org/rfc/rfc7240

Related

Location vs Content-Location on post requests

I am confused about the header Location and Content-Location.
Content-Location
Regarding Content-Location I found this statement in the spec. (Emphasis mine)
For a state-changing request like PUT (Section 4.3.4) or POST (Section 4.3.3), it implies that the server's response contains the new representation of that resource, thereby distinguishing it from representations that might only report about the action (e.g., "It worked!"). This allows authoring applications to update their local copies without the need for a subsequent GET request.
However, in the mdn docs is an example that shows the opposite behaviour. (Emphasis mine)
The site returns a generic success message confirming the post was published. The server specifies where the new post is with Content-Location:
HTTP/1.1 201 Created
Content-Type: text/plain; charset=utf-8
Content-Location: /my-first-blog-post
✅ Success!
These two statements seem to contradict each other.
Now, I am unsure if I should use Content-Location for the case of not including the real entity in the response.
Location
The spec has a sentence about the Location header.
For 201 (Created) responses, the Location value refers to the primary resource created by the request.
And mdn is saying the same.
In cases of resource creation, it indicates the URL to the newly created resource.
I am confused which one to pick for a post response that does not include the entity.
I am guessing the Location header would be most appropriate for a generic post request where the entity can be viewed later. For example, posting a user and viewing it.
What about a POST response with a 202 code? For example, when posting a task to a queue where later only the status of the task can be viewed. So it isn't a real entity like a user. I.e. an email was dispatched to X clients based on the posted task, now I want to communicate where the status (PENDING, FAILURE or SUCCESS) can be viewed.
You are correct, and MDN is wrong about the first example. This example:
HTTP/1.1 201 Created
Content-Type: text/plain; charset=utf-8
Content-Location: /my-first-blog-post
✅ Success!
Suggests that the contents of /my-first-blog-post is ✅ Success!, due to the Content-Location header.
Given that you don't want to return the new resource's body, you should keep Location and omit Content-Location.
And if you have time: report the issue to the MDN maintainers.
What about a POST response with a 202 code? For example, when posting a task to a queue where later only the status of the task can be viewed. So it isn't a real entity like a user. I.e. an email was dispatched to X clients based on the posted task, now I want to communicate where the status (PENDING, FAILURE or SUCCESS) can be viewed.
I would suggest a Link header.

What URI should be returned in HTTP Location header in REST response, if I have two URIs for the same resource?

Let's say I am modeling blogging REST API which has resources Blog, Post and Comment.
Then I add following URIs for Blog and Post resources:
/api/blogs
/api/blogs/{blogId}
/api/blogs/{blogId}/posts
and since deep nesting should be avoided I create separate endpoint for all Posts in order to get their Comment`s:
/api/posts
/api/posts/{postId}
/api/posts/{postId}/comments
Now, if I implement POST action that creates a new Post for a specific Blog on /api/blogs/{blogId}/posts endpoint, should I set Location header value in response to:
/api/blogs/{blogId}/posts/123
or
/api/posts/123
?
In either case I can GET the same resource, but is there some preference, according to REST style, which should be returned to client after successful POST?
If one or more resources has been created on the origin server as a result of successfully processing a POST request, the origin server SHOULD send a 201 (Created) response containing a Location header field that provides an identifier for the primary resource created (Section 7.1.2) and a representation that describes the status of the request while referring to the new resource(s). -- RFC 7231
Which resource is the "primary resource"? That's up to you - priority of the resources is going to depend on your resource model, and REST / HTTP do not care what model you use.
In effect, it comes down to "which URI do you want to see in your access logs?"

REST-way to control whether to return representation of created resource in POST response

Is there a "REST-way" by which a client of a REST-API can indicate whether it is interested in getting a resource representation of the created resource in the POST response or whether it is just interested in HTTP response code (i.e. 201 on success) and location header?
I was thinking on using the Accept header. If the client adds a media type to this header that is supported by the API, the representation will be returned. Otherwise, it will just get a HTTP Created and the location header.
Context: The API will have to types of clients. A Web-UI client, that wants the representation in the response to save a network round-trip. And backend-service clients that will create resources at high rate in fire-and-forget manner. They're only interested in response code and resource URI.
There is a HTTP header:
Prefer: return=representation
The server can signal that it respected the header by returning:
Preference-Applied: return=representation
https://www.rfc-editor.org/rfc/rfc7240

RESTful API POST call request without a body

I want to create a new call in my API that links two already created resources together. Therefore, I don't need to pass any json entities in the post body I just need the resources IDs which I am passing in the URL. Is that a wrong practice? so basically my request now is only a simple path {cid}/projects/{projectID}/subcontractors/{subcontractorID}
and in the post call method I extract the resources IDs from the path and I link them. The response is only either pass or fail {"success":true}. Is that a wrong practice? Is there a better way of doing this?
How you will design your API is really up to you. From a technical point of view, a POST request with an empty payload is completely fine.
However, assuming that you intend to add a contractor to a project, I think it could be better expressed with a payload:
POST /projects/1/contractors HTTP/1.1
Host: api.example.org
Content-Type: application/json
{ "contractorId": 100 }
This approach is specially useful if you need to manage more information for that contractor in that project. If above request succeeds, the response would contain the 201 status code along with a Location header that identifies the newly created resource.
Since you are linking the already existing resources - projects and contractors. I wouldn't prefer the POST method.
Instead I would use the PATCH method (as I am only editing the partial content of the existing resources)
Either the payload or the request URL methods are acceptable.
Request URL:
PATCH /projects/3/contractors/23 HTTP/1.1
HOST example.com/api
Payload
PATCH /projects/3/contractors HTTP/1.1
HOST example.com/api
Content-Type: application/json
{ "contractor_id": 23 }
A successful response is indicated by 200 status code which may contain the payload, or
204 response

Rest endpoint with success and a helpful warning

I have a request from the client - when the user performs an action, there can be 3 actions:
the action succeeds with 200 OK status
the action fails (400) with an error message
the action succeeds but we need to display a helpful warning message to the user. This happens when the allocated amount is almost used up.
There does not seem to be a way for REST APIs to return an indication that the action completed successfully with some helpful information that further action might fail.
Thanks
HTTP response codes are limited and I think, those to be used to indicate any generic response. To have application specific response codes or response strings, it is better to have application level response codes to be communicated via HTTP response payload.
You didn't mention which HTTP method you are preparing for. Using GET should of course not modify anything, so I'm assuming it's either POST or PUT.
For POST, the response should be 201 Created. There should be a Location header line indicating the resource that was created.
For PUT, the response should be 200 OK.
In both cases, you can return a content body, as others suggested. This body can be some status information about the current state of whatever resource you are using. Note, that this status information might be reachable explicitly by some other URI, so it can share a mime-type with that "status" resource.
REST is using HTTP methods and HTTP status to represent the status of reply, by checking HTTP status I can find code 203 I think it could be suitable for your 3rd case :
203 Non-Authoritative Information (since HTTP/1.1)
The server successfully processed the request, but is returning information that may be from another source.