I'm developing an API for events management. I have the basic GET and POST methods but now I have to deal with the event resource edition.
A user can edit all the event information using:
PUT /event/:eventId
But also it can cancel the event (not deleting it, but changing it's status property).
I've thinking on using this endpoint:
PATCH /event/:eventId and send a body with only the new status property value.
I think this is a good approach but then I have noticed that the status can only be set to CANCELLED, the other allowed status for the event are changed automatically in the business logic in certain cases.
So sending the status field doesn't make sense at all if you only can change it to one possible value.
Therefore, is it possible and not a bad practice to send no body to a PATCH method? Thanks.
I would suggest to make PATCH endpoint to /event/{eventId}/status.
There is no need to put payload to your PATCH request, payload is optional.
API should be meaningful to end user. With PATCH you are letting user know that you want to do a partial update on the event record for provided eventId and the attribute you want to perform action is status.
In addition, make sure your API doc provides the detail that status will be set to CANCELLED by default. And in future, if required you can scale API by adding payload {"status": "CANCELLED | ENABLED | .." }
I would suggest to add payload to body of PATCH /event/:eventId.
If in any case you need to add a new attribute for updating an event's attribute, you will not be able to decide if you need to update the status or not. This can future proof your endpoint.
Related
I've been learning how to build an ASP.NET Core Web API using the official documentation. However, under the PUT section it says:
According to the HTTP specification, a PUT request requires the client to send the entire updated entity, not just the changes. To support partial updates, use HTTP PATCH.
I know that POST is used to create a new resource and PUT is used to update a particular resource. But I cannot understand what is meant by "entire updated entity, not just the changes".
I cannot understand what is meant by "entire updated entity, not just the changes".
You should review the HTTP specification, which describes the semantics of PUT.
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.
Representation here refers to the bytes that would appear as the payload of the GET request. For a web page, we're talking about the HTML. For a resouce that responds with application/json, we're talking about the entire json document.
In other words, if you want to create/edit a json document, and save it on the web server, then you use HTTP PUT, and the payload of the request should be the entire JSON document.
For cases where the JSON document is very big (much bigger than the HTTP headers) and the changes you are making are small, then you might instead choose to send the changes in a patch request, where the payload of the request is a patch document (probably JSON Patch or JSON Merge Patch
Now, here's the magic trick -- everybody on the web understands HTTP requests the same way. PUT always means PUT, PATCH always means PATCH. So you can use PUT and PATCH to make changes to things on the web that aren't really documents, but might instead be something else (like an entity).
That's pretty much the point of an HTTP API - it's a facade that (when seen from the outside) makes our service look like just another web server.
The fact that your resource is really rows in a database instead of a document on a file system is an implementation detail that is hidden behind the Web API.
Supposed you have a json Data like below
{
"Id":123,
"FirstName":"John",
"MiddleName":"Random",
"LastName":"Doe"
}
Suppose, you want to change middle name here. you want to remove it. You can use both put and patch to do so.
PUT
Here you've to send the whole new entity (the changed state of the json model) in your request. Though you're only changing the Middle name part, the full json data is being sent in the request payload
PUT /user?id=123
{
"Id":123,
"FirstName":"John",
"MiddleName":"", //Only this is being changed.
"LastName":"Doe"
}
PATCH
In this case, you can only send the diff between the old model and the new model, and that will be it. So, here, in this case, only the changes are being sent, not the whole updated entity
PATCH /user?id=123
{
"MiddleName":"", //Only this is being changed.
}
Using PATCH can be handy when you want to edit only a few properties of a huge object.
I'm writing a stateless API. You send it a document, it processes the document, and then returns the processed document. I'm struggling to understand how the RESTFUL rules apply. I'm not retrieving data, creating data or updating data on the server. There is no data on the server. What do I need to use in this case as the http method and why?
Good news - you are right that it is confusing.
Nothing on the server changes in response to the request. That suggests that the request is safe. So GET is the natural choice here... BUT -- GET doesn't support message payloads
A payload within a GET request message has no defined semantics; sending a payload body on a GET request might cause some existing implementations to reject the request.
HEAD, the other ubiquitous safe method, has the same problem (and is unsuitable when you want to return a document in any case).
The straight forward thing to do at this point is just use POST. It's important to realize that POST doesn't promise that a request is unsafe, only that it doesn't promise that it is safe -- generic components won't know that the request is safe, and won't be able to take advantage of that.
Another possibility is to look through the method registry, to see if somebody has already specified a method that has the semantics that you want. Candidates include SEARCH and REPORT, from the WebDAV specifications. My read of those specifications is that they don't actually have the right semantics for your case.
A Lot of ways to do what you want. But here is a small guideline.
I would create an endpoint that receives the document:
/receive_document
with a 'POST' method. Since you are 'sending' your document to the server
I would create an endpoint that serves up the processed document:
/processed_document
with a 'GET' method. Since you want to retrieve / see your document from the server?
The problem that you are trying to solve is mainly related to the document size, and processing time before returning the response.
Theorically, in order to use a restful approach, you have an endpoint, like yourhost.com/api/document-manager (it can be a php script, or whatever you are using as backend).
OK, so instead of naming the endpoint differently for each operation type, you just change the HTTP method, I'll try to make an example:
POST: used to upload the document, returns 200 OK when the upload is completed.
GET: returns the processed document, you can also return a different HTTP code, in case the document is not ready or even different if the document hasn't been uploaded. 204 no content or 412 precondition failed can be good candidates in case of unavailable document. I'm not sure about the 412, seems like it's returned when you pass a header in the request, that tells the server which resource to return. In your case, I think that the user processes one document at time. But to make a more solid api, maybe you can return an ID token to the user, into the POST response, then forward that token to the GET request, so the server will be able to know exactly which file the user is requesting.
PUT: this method should be used when updating a resource that has been already created with POST
DELETE: removes a resource, then return 204 or 404
OPTIONS: the response contains the allowed methods on this endpoint. You can use it to know for example which privileges has the currently logged user on a resource.
HEAD: is the same as a GET call, but it shouldn't return the response body. This is another good candidate for you to know when the document has been processed. You can upload with POST, then when the upload is done, start some kind of polling to the same endpoint with the HEAD method, finally when it will return "found", the polling will stop, and make the final GET call, which will start the download of the processed document.
HTTP methods are a neat way of managing HTTP communications, if used properly are the way to go, and easily understandable by other developers. And not to forget, you don't have to invent lots of different names for your endpoints, one is enough.
Hope that this helped you a little... But there are loads of guides on the net.
Bye!
I have a REST Service that can be used to control databases, I want to allow calls to Stop & Start the databases, but was wondering what would be the correct Method?
By calling the Stop or Start Operation I am changing the state of the resource so a PUT seems sort of right, but is PATCH better or even POST?
Any suggestions?
Replacing the state of a resource
REST is protocol independent and is a resource-oriented architecture. When implementing REST applications over the HTTP protocol, for example, the resource is identified by the URI and the operation over the resource is expressed by the HTTP method.
PUT is the HTTP method used to replace the state of a resource and the new state of the resource will be expressed in the request payload using, for example, JSON and/or XML.
So you could consider the following design to start/stop a database:
PUT /databases/:id/status HTTP/1.1
Content-Type: application/json
{
"value": "started"
}
PUT /databases/:id/status HTTP/1.1
Content-Type: application/json
{
"value": "stopped"
}
To obtain the state of a resource, use GET:
GET /databases/:id/status HTTP/1.1
Response status codes
You certainly will need to inform your client about the result of the operation. To do it, use the HTTP response status codes.
A few status that might be useful:
200: Use this status to indicate that the request has succeeded.
202: Use this status code to indicate the request has been accepted for processing, but the processing has not been completed.
204: Use this status code to indicate the server has successfully fulfilled the request and that there is no additional content to send in the response payload body.
409: Use this indicates that the request could not be completed due to a conflict with the current state of the target resource.
Jim Webber explains that "HTTP is the application protocol of transferring documents" The transitions of state in your application are a side effect triggered by the document transfer.
Think old fashioned paper driven business office: the boss comes along and drops a TODO message in your inbox, which says "stop the database". As a side effect, you swivel your chair around and initiate the clean shutdown procedure.
Idiomatically, therefore, the representation you are sending to the REST server is that of the TODO message, and you are sending it to either (a) a resource that represents the "inbox" -- ie, a specific collection of TODO messages -- or (b) a resource that represents the TODO document itself.
I have a REST Service that can be used to control databases, I want to allow calls to Stop & Start the databases, but was wondering what would be the correct Method?
By calling the Stop or Start Operation I am changing the state of the resource so a PUT seems sort of right, but is PATCH better or even POST?
Since you are sending a complete message, rather than trying to make a modification to a message that the REST server already knows about, PATCH is not appropriate.
DELETE is also not appropriate - delete is analogous to destroying the TODO message in the inbox.
If the media type that you are using to represent application state at the client is HTML, then the verb you use shall be POST, because HTML doesn't support PUT.
If you are delivering a representation of a single message to a resource that represents a collection, then the verb you use shall be POST, because the semantics of PUT imply "create/overwrite" of a resource, and the semantic you are expressing is append.
If you are delivering a representation of a single message to a resource that represents that message alone (ie: you are doing a create of the message resource), then PUT is preferred to POST. The key idea here is that PUT promises that any side effects on the server are idempotent -- the side effect of successfully delivering N > 0 copies of the message are equivalent to the side effect of delivering exactly 1 copy. Using PUT as the verb shares that promise, not just with the client and server, but also with all of the intermediate connectors along the way.
Your idempotent resources can also support POST, and you can document in your API that the messages received are handled idempotently so that clients will understand, but there's no standardized way to inform the other connectors of this fact.
(Example: think about a form post in a browser. The resource at the server knows that the request can be handled idempotently. You can document in the html itself that hitting the button more than once is safe, but you don't have any way to tell the browser that, so the browser throws up a message to the user saying "re-POST might not be safe, are you sure Y/N?")
In summary, you want your choices of HTTP methods to agree with the uniform interface, so that the client, the server, and all of the components acting on the messages in between have a shared understanding of what's going on.
I have to design REST services for security sensitive resources that require dual control. What is an elegant way to design the REST services that implement dual control?
Dual Control
With dual control I mean that a change only becomes effective if multiple people (e.g. 2) were involved in the change.
For example, I have resource called userProfile. It defines all things a user is allowed to do. If someone wants to change such a profile, it can propose a change to it. This change then has to be verified. The result of this verification is either "Approve" or "Reject". Once a change has been approved it becomes effective.
Design
I currently have a userProfile resource and a userProfileChangeProposal resource.
creating a proposal to create a userprofile happens through
POST /userprofiles
This returns the ID of the userprofile. It can now be verified using that {id}
PUT /userprofiles/{id}/changeproposal
Deleting or updating the userprofile requires a proposal again, so:
DELETE /userprofiles/{id}
PUT /userprofiles/{id}
These changes can be verified again via: (there can only be 1 proposal at the same time for a userprofile)
PUT /userprofiles/{id}/changeproposal
Issues
The thing I'm struggling with is that the rest operations seem to operate on the userprofile resource, but in fact they dont. A delete doesn't directly delete the resource. It creates a proposal to delete it.
Also, this approach doesn't allow direct deletion of a userprofile.
On the other hand, if all changes occur through change proposals, then all create/delete/update actions are just
CREATE /userprofilechangeproposal
I havent seen anything on the internet regarding dual control design. The closest was that someone first creates an ORDER resource and only after the order has been approved the actual CAR is created.
Anyone has any best practices?
I think this post on Rest Cookbook answers your question. The same article, but a little more verbose can be found here and here.
Summarizing the info in the URL your workflow should look like this:
User sends a POST to /userprofiles with the profile info in the payload { "username": "user1298232" } (as an example)
The service replies with 202 Accepted and Location: /proposals/12345 header.
User can check the proposal status by sending a GET /proposals/12345 request. This resource might look like this { "status": "waiting for approval" }
When the actual resource has been accepted and created (e.g. with an id of 1) GET /proposals/12345 no longer returns the status, but instead will redirect (with a 303 response status code and Location header) the request to the newly created resource at /userprofiles/1.
4a. Later on the client can either DELETE the proposal resource or the server can expire it and return a 410 Gone (after some time as an element of garbage collection).
4b. If the proposal gets rejected then its status should change accordingly (e.g. { "status": "Rejected" }).
NOTE (from the article):
Don't use a 301 or 302 when a resource has been created. These codes tell the client that the SAME resource can be found at another location. A 303 tells a client that ANOTHER resource can be found at ANOTHER location.
The same workflow can be used to modify/delete a resource.
EDIT: APPROVING PROPOSALS
I forgot to write how to approve requests. The most natural approach to this would be for the authorized user to send a partial update PATCH /proposals/1 including the status change - { "status": "approved" }.
There is a discussion on how the payload of a PATCH request should look like. The above method of describing a partial update (a partial resource including only the attributes to be updated) is implemented e.g. in the GitHub API which by many is considered the role model of a RESTful API. Presented here is another approach, which would require the payload to describe the change itself instead of the partial resource with the attributes to update: { "op": "replace", "path": "/status", "value": "approved" }.
PATCH is not yet an official HTTP method, so theoretically it may cause some problems in certain environments althought personally I haven't yet encountered such a scenario (comment under this SO post suggests that there might be a problem with PATCH in MS Edge, but I haven't checked that). Anyway you could design /proposals/[id] to accept PUT requests just to be on the safe side. Just remember that PUT should replace the resource and should contain the whole resource in the payload, not only the changed properties.
EDIT 2
Regarding the PATCH problem: it seems that GitHub API actually allows partial updates with POST as well because of the mentioned above possible PATCH incompatibility with some clients. So POST in addition to its normal duties (resource creation) gets the partial update capabilities when given resource ID (link -> section HTTP Verbs):
PATCH - Used for updating resources with partial JSON data. For instance, an Issue resource has title and body attributes. A PATCH request may accept one or more of the attributes to update the resource. PATCH is a relatively new and uncommon HTTP verb, so resource endpoints also accept POST requests.
i'm currently trying to build simple REST api with one endpoint or users looking like this:
GET /users - get all
GET /users/{id} - get one
POST /users - create
PUT /users/{id} - update
DELETE /users/{id} - delete
The problem is with DELETE, because DELETE in reality only UPDATE user resource with status REMOVED. Is it ok? And which status should I return? I'm currently returning 202 Accepted, as i believe that saying "Resource is accepted to be removed" is ok, but maybe there should be just 200 OK
When designing an API, you should always consider what the giving action means for the user of the API.
The user would not really want to know what happens behind the scenes, but only want a clean and understandable set of actions.
So for you delete action, you should consider, "will this delete the item, from the users perspective?"
Responding with status code 200 most often fine, but remember to send some content with it to support it.
Using many different status code for success does not really give value, so be careful.
RestApiTutorial says this.
DELETE is pretty easy to understand. It is used to delete a
resource identified by a URI.
On successful deletion, return HTTP status 200 (OK) along with a
response body, perhaps the representation of the deleted item (often
demands too much bandwidth), or a wrapped response (see Return Values
below). Either that or return HTTP status 204 (NO CONTENT) with no
response body. In other words, a 204 status with no body, or the
JSEND-style response and HTTP status 200 are the recommended
responses.
But you can use It for your prupose, if It do your Api logic easier to understand to the user.
I Hope It helps you.
The question that you have to ask yourself is:
Does the resource after the DELETE will still be available to the client?
If the answer is yes then I would suggest to use a PATCH you can even use the RFC6902 for that.
If the answer is no then DELETE is fine.
But since you have mention that the idea is to flag the user with a status delete I guess you have the intention to query all deleted user at some point or do something useful with it. Witch seems to be a client [admin] use case so PATCH sounds appropriate.
Regarding the status for DELETE. Some people may prefer to use the 204 No content since you are expecting the resource to be removed.