Location vs Content-Location on post requests - rest

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.

Related

Should I use POST or PUT for login request, and why?

I know the difference between them generally but for the login form, I'm not sure why the POST method is recommended.
Broadly: because PUT has more specific semantics in HTTP, and those semantics don't match the typical login form case very well.
POST serves many useful purposes in HTTP, including the general purpose of “this action isn’t worth standardizing.” -- Fielding 2009
POST /foo HTTP/1.1
Content-Type: text/plain
username=foo&password=this_is_a_secret
That request can mean almost anything; it might or might not be idmpotent, it might or might not be "effectively read only". It's very non-committal. From RFC 7321:
The POST method requests that the target resource process the representation enclosed in the request according to the resource's own specific semantics.
In contrast, PUT means something much more specific
A successful PUT of a given representation would suggest that a subsequent GET on that same target resource will result in an equivalent representation being sent in a 200 (OK) response.
Thus
PUT /foo HTTP/1.1
Content-Type: text/plain
username=foo&password=this_is_a_secret
Suggests that when someone later does
GET /foo HTTP/1.1
You expect a response like
HTTP/1.1 200 OK
Content-Type: text/plain
username=foo&password=this_is_a_secret
In other words, the semantics of PUT are very close to those of "save" or "upsert". "Make your copy of this resource look like the payload of this request."
Remember, general purpose HTTP components don't necessarily know that these message are about "login"; they only see messages with semantics of the transfer of documents over a network domain. That's means that when they see your "login" PUT request, they are going to assume that the semantics are exactly the same as a PUT to any other resource on the web, and act accordingly.

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

RESTful API: Delete Entity - What should I return as result?

I am implementing a RESTful API and an endpoint of one controller is Delete. Delete does two actions depending of the entity to be removed: it updates the entity or it deletes the entity from the database. If delete updates the entity I would send the HttpStatus 200 and the updated entity. But if the delete removes the entity from the database I would send only the HttpStatus 200. In one case I am returning an object. But in the other case, the object doesn't existe any more. Is it a good approach or I am missing anything?
Short answer
The suitable status codes for a DELETE request that has succeeded are 200, 202 and 204.
Long answer
DELETE does two actions depending of the entity to be removed: it updates the entity or it deletes the entity from the database. [...] Is it a good approach or I am missing anything?
The DELETE method is not meant for performing updates.
See the following quote from the RFC 7231, one of the documents the define the HTTP/1.1 protocol, for details on what the DELETE method is about:
4.3.5. DELETE
The DELETE method requests that the origin server remove the
association between the target resource and its current
functionality. In effect, this method is similar to the rm command
in UNIX: it expresses a deletion operation on the URI mapping of the
origin server rather than an expectation that the previously
associated information be deleted. [...]
If the delete operation has succeded, the server can return one of the following status codes:
202: Indicates that the request has been accepted for processing, but the processing has not been completed.
204: Indicates that the server has
successfully fulfilled the request and that there is no additional
content to send in the response payload body.
200: Indicates that the request has succeeded and the request payload includes a representation of the status of the action.
See the following quote from the same document:
If a DELETE method is successfully applied, the origin server SHOULD
send a 202 (Accepted) status code if the action will likely succeed
but has not yet been enacted, a 204 (No Content) status code if the
action has been enacted and no further information is to be supplied,
or a 200 (OK) status code if the action has been enacted and the
response message includes a representation describing the status.
The commonly considered HTTP Statuses for DELETE include:
200 OK (MDN)
202 Accepted (MDN)
204 No Content (MDN)
204 is ideal if your service is not returning any additional info. It is also popular for PUT update requests. Many services return 204 including Docker as shown below:
Ref: https://docs.docker.com/engine/api/v1.24/
However, if you are implementing HATEOAS, it is better to use 200 OK and provide some links for the service. Think of an application that has just issued a delete and needs to navigate a user to a location. Without providing a URL for that location, the client app needs to keep state. Providing a 200 OK with a link allows the REST API to keep state for the client.
The following article describes this issue well (read the blog for more discussion):
Avoid 204 responses if you're building a HATEOAS application.
This is a lesson about REST API design that I learned while building non-trivial REST APIs. In order to be as supportive of the client as possible, a REST API should not return 204 (No Content) responses.
From the service's perspective, a 204 (No Content) response may be a perfectly valid response to a POST, PUT or DELETE request. Particularly, for a DELETE request it seems very appropriate, because what else can you say?
However, from the perspective of a proper HATEOAS-aware client, a 204 response is problematic because there are no links to follow. When hypermedia acts as the engine of application state, when there are no links, there's no state. In other words, a 204 response throws away all application state.
If a client encounters a 204 response, it can either give up, go to the entry point of the API, or go back to the previous resource it visited. Neither option is particularly good.
Ref: http://blog.ploeh.dk/2013/04/30/rest-lesson-learned-avoid-204-responses/

What HTTP code return when record is in inappropriate state?

I need to set particular resource accessible via REST Api to one of defined states - idle, running or stopped. How to inform a REST API client that record is already in requested state? E.g. client wants to start the record and that record is already running? He needs to know that record is running and operation is not processable.
It's definitively client error, so status code from 4xx family should be the answer. I have an idea to use 400, 409 or 412 but not sure.
There is "look-before-you-leap" technique that might be useful here.
You could insert If-Match header in your PUT (I assume its PUT) request
PUT /states HTTP/1.1
Host: www.example.com
Content-Type: text/plain
If-Match: "running"
Running
Either you get 200 or 412 (Precondition Failed).
How to inform a REST API client that record is already in requested state
Closest I could find is
409 Conflict
The request could not be completed due to a conflict with the current state of the resource. This code is only allowed in situations where it is expected that the user might be able to resolve the conflict and resubmit the request. The response body SHOULD include enough information for the user to recognize the source of the conflict. Ideally, the response entity would include enough information for the user or user agent to fix the problem; however, that might not be possible and is not required.
Conflicts are most likely to occur in response to a PUT request. For example, if versioning were being used and the entity being PUT included changes to a resource which conflict with those made by an earlier (third-party) request, the server might use the 409 response to indicate that it can't complete the request. In this case, the response entity would likely contain a list of the differences between the two versions in a format defined by the response Content-Type.
emphasis mine
RFC 2616

RESTful - What should a DELETE response body contain

Let's say I have an API where you can get users:
GET /RESTAPI/user/
And you can delete users by:
DELETE /RESTAPI/user/123
What is the RESTful convention on what the DELETE's response body should contain?
I expected it should be the new list of all users which now doesn't contain the user with id 123 anymore.
Googling around didn't get me any satisfying answers. I only found opinions on how to do that, but isn't there a strict definition of RESTful Services?
This is NOT a duplicate of What should a RESTful API POST/DELETE return in the body? and What REST PUT/POST/DELETE calls should return by a convention?
since this questions asks for a strict definition regarding DELETE. Those questions were answered by loose opinions only.
The reason you get no hard answers is because there is no hard RESTful standard. So I can only suggest that you create a hard standard and stick to it within your own APIs
I used this as a guide for RESTful services http://www.vinaysahni.com/best-practices-for-a-pragmatic-restful-api
It says respond with a 204 status and an empty body
I stick to those standards and document them well for anyone who wants to use my APIs
What is the RESTful convention on what the DELETE's response body should contain?
REST is an architectural style defined by Fielding in the chapter 5 of his dissertation and it describes a set of contraints for applications built with this architecture. REST is designed to be protocol indenpendent but the chapter 6 of the same dissertation describes how REST is applied over HTTP.
Once your REST application is designed on the top of the HTTP protocol, you should be aware of the HTTP semantics. And the semantis of the HTTP/1.1 protocol are currently described in the RFC 7231.
The response payload of a DELETE request that has succeeded may:
Be empty or;
Include a representation of the status of the action.
And the following response status codes are suitable for a DELETE request that has succeeded:
202: The request has been accepted for processing, but the processing has not been completed.
204: The server has successfully fulfilled the request and that there is no additional content to send in the response payload body.
200: The request has succeeded and the request payload includes a representation of the status of the action.
See the following quote from the RFC 7231:
If a DELETE method is successfully applied, the origin server SHOULD
send a 202 (Accepted) status code if the action will likely succeed
but has not yet been enacted, a 204 (No Content) status code if the
action has been enacted and no further information is to be supplied,
or a 200 (OK) status code if the action has been enacted and the
response message includes a representation describing the status.
204 No Content is a popular response for DELETE and occasionally PUT as well.
However, if you are implementing HATEOAS, returning a 200 OK with links to follow may be more ideal. This is because a HATEOAS REST API provides context to the client. Think of the location a user application navigates to after successfully issuing a delete command. Here is a brief article excerpt with more discussion on this. See the blog article for a more complete discussion.
Article: http://blog.ploeh.dk/2013/04/30/rest-lesson-learned-avoid-204-responses/
Avoid 204 responses if you're building a HATEOAS application.
This is a lesson about REST API design that I learned while building non-trivial REST APIs. In order to be as supportive of the client as possible, a REST API should not return 204 (No Content) responses.
From the service's perspective, a 204 (No Content) response may be a perfectly valid response to a POST, PUT or DELETE request. Particularly, for a DELETE request it seems very appropriate, because what else can you say?
However, from the perspective of a proper HATEOAS-aware client, a 204 response is problematic because there are no links to follow. When hypermedia acts as the engine of application state, when there are no links, there's no state. In other words, a 204 response throws away all application state.
This article covers POST, PUT, DELETE and GET. Here's the specific discussion on DELETE:
Responding to DELETE requests
A DELETE request represents the intent to delete a resource. Thus, if the service successfully handles a DELETE request, what else can it do than returning a 204 (No Content)? After all, the resource has just been removed.
A resource is often a member of a collection, or otherwise 'owned' by a container. As an example, http://foo.ploeh.dk/api/tags/rock represents a "rock" tag, but another way of looking at it is that the /rock resource is contained within the tags container (which is itself a resource). This should be familiar to Atom Pub users.
Imagine that you want to delete the http://foo.ploeh.dk/api/tags/rock resource. In order to accomplish that goal, you issue a DELETE request against it. If all your client gets back is a 204 (No Content), it's just lost its context. Where does it go from there? Unless you keep state on the client, you don't know where you came from.
Instead of returning 204 (No Content), the API should be helpful and suggest places to go. In this example I think one obvious link to provide is to http://foo.ploeh.dk/api/tags - the container from which the client just deleted a resource. Perhaps the client wishes to delete more resources, so that would be a helpful link.