I have a scenario similar to request/ack/poll. So the client posts data and I send status Accepted back. Then a background process takes care of creating the resource.
The client can then go to the location of the "Accepted response" and Poll for status.
If the background process fails and I want to inform the client about this, what status code should I return? HTTP 500 is not that good since it could also happen if the call to the status route fails for any other reason, and the client couldn't tell the difference.
And also, what is the best code to return when the creation of the resource is still in progress? 200 OK?
Any suggestions?
I defined a media type to address this issue. Here is a copy of the readme..
A status document might look like:
<status state="busy" progress="2/75" message="This is a message"/>
It consists of a root node named status and has the properties: state, progress and message.
Only the state property is required, and should be one of the following values : {waiting, busy, warning, error, ok, cancelled}
The progress property is a fraction that can be optionally used to indicate to a user how much longer we expect the resource to remain in a particular state.
The message property is a human readable string intended to qualify the resource state.
Additional information can be provided by embedding links within the status node.
<status state="ok" message="Finshed generating report">
<link rel="related" href="http://example.org/report/99/output"/>
</status>
the JSON equivalent of this would be
{ "status" : {
"state" : "ok",
"message" : "Finished generating report",
"links" : {
"related" : { "href" : "http://example.org/report/99/output"}
}
}
}
The syntax of the links object in the JSON format follows the convention of HAL except that there is no leading underscore for the links object. The underscore is unncessary as this media type does encourage embedding arbitrary additional content, therefore no naming conflicts should occur.
The specification does not prohibit extensions to the content, however it defines no rules for extensions beyond the constraints of the underlying JSON/XML format.
Media Type Identifiers
The intent is to submit this specifcation as a proposal to IANA for registration using the following identifiers:
application/status+xml
application/status+json
Related
Chapter 9.5 POST of the HTTP/1.1 spec includes the sentence:
If a resource has been created on the origin server, the response
SHOULD be 201 (Created) and contain an entity which describes the
status of the request and refers to the new resource, and a Location
header
It is referenced frequently. The itention is clear, but I have issues with the meaning of some of the chosen words.
What does "contain an entity which describes the status of the request and refers to the new resource" exactly mean?
How shall the entity (entity-header fields and entity-body) describe the status of the request? Isn't the status of the request 201 (Created)? Whow shall this status be described? Does "describe the status of the request" mean the result, in other words the current entity status?
Thinking of a Web API with JSON representation does it mean that the entity should be included in a JSON representation after a successful POST that created an entity? Thinking of a created image, should the image data be returned in the response body?
What is meant with refers to the new resource? The uri is already in the location header. Shall it be repeated in the body or does it mean just to add an id?
Is there a good source with examples of different entities and its responses to a creation POST?
I think it varies based on the resource you're creating, suppose your posting to a /profile/ resource maybe a payload containing multiple profile fields to update - your return would indicate it was successful and include a reference to the fields you posted (it can even return the entire profile attributes with fields you've updated including all fields);
Another example in the image sense, suppose you are posting a Base64 encoded image to a service that stores the image, the response should show the status (ie: accepted, rejected, file too larage, MIME type accurate or not, etc.) - and within the returned payload if successful you'd want the response to not be vague but return the path and/or filename of the image uploaded;
The header returns the response code - the body returns information related to the invoked action's entity response (it can be a set of fields, a URL, a useful response that when parsed back it can be actionable or informative);
These are principles of good coding, but also keep note of security and not to expose anything in a return that could potentially be damaging for example; when creating a service you want to be clear and provide concise and useful returns so when the client consumes the API it knows what to do, what to expect, etc.
According to the Docs, I can update the tags on a resource group or resource by making a PATCH request and setting the tags field in the body. This works for setting one or more tags, or deleting one or more tags (I just leave the tagname out of the request).
However, when I try to delete all the tags by passing an empty tags field:
PATCH https://management.azure.com/{....}
{
"tags": {}
}
it doesn't work. For a resource, I get a 400 error Request must specify an account property to update while for a resource group, it just leaves the current tags unchanged.
Is there a way to delete all the tags on a resource/resource group via REST?
You could try to use this api: Resources - Update By Id, it should apply to both the resource and resource group. I have test it with the resource group and a resource(my sample is a web app), all work fine.
The request body:
{
tags: {}
}
Note: If you get a NoRegisteredProviderFound error, change the api-version depends on the error message.
This was actually due to a wart in how the httr package handles empty fields in a request body. If the body is a list, such fields are silently removed before being sent to the host.
The fix is to convert the data into JSON beforehand, rather than relying on httr to do it:
httr::PATCH("https://management.azure.com/{....}",
body=jsonlite::toJSON(body, auto_unbox=TRUE),
encoding="raw",
...)
I want to design my rest endpoint with the appropriate method for the following scenario.
There is a group. Each group has a status. The group can be activated or inactivated by the admin.
Should I design my end point as
PUT /groups/api/v1/groups/{group id}/status/activate
OR
PATCH /groups/api/v1/groups/{group id}
with request body like
{action:activate|deactivate}
The PATCH method is the correct choice here as you're updating an existing resource - the group ID. PUT should only be used if you're replacing a resource in its entirety.
Further information on partial resource modification is available in RFC 5789. Specifically, the PUT method is described as follows:
Several applications extending the Hypertext Transfer Protocol
(HTTP) require a feature to do partial resource modification. The
existing HTTP PUT method only allows a complete replacement of a
document. This proposal adds a new HTTP method, PATCH, to modify an
existing HTTP resource.
The R in REST stands for resource
(Which isn't true, because it stands for Representational, but it's a good trick to remember the importance of Resources in REST).
About PUT /groups/api/v1/groups/{group id}/status/activate: you are not updating an "activate". An "activate" is not a thing, it's a verb. Verbs are never good resources. A rule of thumb: if the action, a verb, is in the URL, it probably is not RESTful.
What are you doing instead? Either you are "adding", "removing" or "updating" an activation on a Group, or if you prefer: manipulating a "status"-resource on a Group. Personally, I'd use "activations" because they are less ambiguous than the concept "status": creating a status is ambiguous, creating an activation is not.
POST /groups/{group id}/activation Creates (or requests the creation of) an activation.
PATCH /groups/{group id}/activation Updates some details of an existing activation. Since a group has only one activation, we know what activation-resource we are referring to.
PUT /groups/{group id}/activation Inserts-or-replaces the old activation. Since a group has only one activation, we know what activation-resource we are referring to.
DELETE /groups/{group id}/activation Will cancel, or remove the activation.
This pattern is useful when the "activation" of a Group has side-effects, such as payments being made, mails being sent and so on. Only POST and PATCH may have such side-effects. When e.g. a deletion of an activation needs to, say, notify users over mail, DELETE is not the right choice; in that case you probably want to create a deactivation resource: POST /groups/{group_id}/deactivation.
It is a good idea to follow these guidelines, because this standard contract makes it very clear for your clients, and all the proxies and layers between the client and you, know when it is safe to retry, and when not. Let's say the client is somewhere with flaky wifi, and its user clicks on "deactivate", which triggers a DELETE: If that fails, the client can simply retry, until it gets a 404, 200 or anything else it can handle. But if it triggers a POST to deactivation it knows not to retry: the POST implies this.
Any client now has a contract, which, when followed, will protect against sending out 42 emails "your group has been deactivated", simply because its HTTP-library kept retrying the call to the backend.
Updating a single attribute: use PATCH
PATCH /groups/{group id}
In case you wish to update an attribute. E.g. the "status" could be an attribute on Groups that can be set. An attribute such as "status" is often a good candidate to limit to a whitelist of values. Examples use some undefined JSON-scheme:
PATCH /groups/{group id} { "attributes": { "status": "active" } }
response: 200 OK
PATCH /groups/{group id} { "attributes": { "status": "deleted" } }
response: 406 Not Acceptable
Replacing the resource, without side-effects use PUT.
PUT /groups/{group id}
In case you wish to replace an entire Group. This does not necessarily mean that the server actually creates a new group and throws the old one out, e.g. the ids might remain the same. But for the clients, this is what PUT can mean: the client should assume he gets an entirely new item, based on the server's response.
The client should, in case of a PUT request, always send the entire resource, having all the data that is needed to create a new item: usually the same data as a POST-create would require.
PUT /groups/{group id} { "attributes": { "status": "active" } }
response: 406 Not Acceptable
PUT /groups/{group id} { "attributes": { "name": .... etc. "status": "active" } }
response: 201 Created or 200 OK, depending on whether we made a new one.
A very important requirement is that PUT is idempotent: if you require side-effects when updating a Group (or changing an activation), you should use PATCH. So, when the update results in e.g. sending out a mail, don't use PUT.
I would recommend using PATCH, because your resource 'group' has many properties but in this case, you are updating only the activation field(partial modification)
according to the RFC5789 (https://www.rfc-editor.org/rfc/rfc5789)
The existing HTTP PUT method only allows a complete replacement of
a document. This proposal adds a new HTTP method, PATCH, to modify
an existing HTTP resource.
Also, in more details,
The difference between the PUT and PATCH requests is reflected in the
way the server processes the enclosed entity to modify the resource
identified by the Request-URI. In a PUT request, the enclosed entity
is considered to be a modified version of the resource stored on the
origin server, and the client is requesting that the stored version
be replaced. With PATCH, however, the enclosed entity contains a set
of instructions describing how a resource currently residing on the
origin server should be modified to produce a new version. The PATCH
method affects the resource identified by the Request-URI, and it
also MAY have side effects on other resources; i.e., new resources
may be created, or existing ones modified, by the application of a
PATCH.
PATCH is neither safe nor idempotent as defined by [RFC2616],
Section
9.1.
Clients need to choose when to use PATCH rather than PUT. For
example, if the patch document size is larger than the size of the
new resource data that would be used in a PUT, then it might make
sense to use PUT instead of PATCH. A comparison to POST is even more
difficult, because POST is used in widely varying ways and can
encompass PUT and PATCH-like operations if the server chooses. If
the operation does not modify the resource identified by the Request-
URI in a predictable way, POST should be considered instead of PATCH
or PUT.
The response code for PATCH is
The 204 response code is used because the response does not carry a
message body (which a response with the 200 code would have). Note
that other success codes could be used as well.
also refer thttp://restcookbook.com/HTTP%20Methods/patch/
Caveat: An API implementing PATCH must patch atomically. It MUST not
be possible that resources are half-patched when requested by a GET.
Since you want to design an API using the REST architectural style you need to think about your use cases to decide which concepts are important enough to expose as resources. Should you decide to expose the status of a group as a sub-resource you could give it the following URI and implement support for both GET and PUT methods:
/groups/api/groups/{group id}/status
The downside of this approach over PATCH for modification is that you will not be able to make changes to more than one property of a group atomically and transactionally. If transactional changes are important then use PATCH.
If you do decide to expose the status as a sub-resource of a group it should be a link in the representation of the group. For example if the agent gets group 123 and accepts XML the response body could contain:
<group id="123">
<status>Active</status>
<link rel="/linkrels/groups/status" uri="/groups/api/groups/123/status"/>
...
</group>
A hyperlink is needed to fulfill the hypermedia as the engine of application state condition of the REST architectural style.
One possible option to implement such behavior is
PUT /groups/api/v1/groups/{group id}/status
{
"Status":"Activated"
}
And obviously, if someone need to deactivate it, PUT will have Deactivated status in JSON.
In case of necessity of mass activation/deactivation, PATCH can step into the game (not for exact group, but for groups resource:
PATCH /groups/api/v1/groups
{
{ “op”: “replace”, “path”: “/group1/status”, “value”: “Activated” },
{ “op”: “replace”, “path”: “/group7/status”, “value”: “Activated” },
{ “op”: “replace”, “path”: “/group9/status”, “value”: “Deactivated” }
}
In general this is idea as #Andrew Dobrowolski suggesting, but with slight changes in exact realization.
I would generally prefer something a bit simpler, like activate/deactivate sub-resource (linked by a Link header with rel=service).
POST /groups/api/v1/groups/{group id}/activate
or
POST /groups/api/v1/groups/{group id}/deactivate
For the consumer, this interface is dead-simple, and it follows REST principles without bogging you down in conceptualizing "activations" as individual resources.
I'm developing a webgame. As part of the game, you start out with a limited set of features, and you unlock more of them as you play.
For instance, you unlock /fields as part of step 3 in the tutorial. But what if you just navigate to /fields in the address bar?
I'm trying to work out what would be the best status code to respond with.
403 seems ideal since the user is forbidden from accessing the page until they unlock it.
404 also makes sense since the page technically "doesn't exist" until it is unlocked and also prevents users from being able to tell the difference between a page that doesn't exist and one that they just haven't unlocked yet.
But in both cases I've had some users report issues with the browser cacheing the 403/404 result and not letting them access the page even after unlocking it unless they purge the cache entirely.
I'm wondering if I should keep using 403 or 404, or should I use an unused 4XX code such as 442 with a custom statusText, or even jokingly send HTTP/1.1 418 I'm A Teapot in response to a user poking around where they shouldn't be.
I need a good, solid reason why one option should be used over the others.
tl;dr 409 Conflict would be an idea, but perhaps you have problems with caching. In this case a cache-buster to force a reload will work.
Long explanation
Perhaps a 409 Conflict status code would make sense:
10.4.10 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.
It would make sense, because the resource is only available after the user did the tutorial. Before that the resource is in an «invalid» state. And the user is able to resolve this conflict by completing the tutorial.
Later I investigated the case a little more and I discovered that the devil is in the detail. Let's read the specification for 403 Forbidden and 404 Not Found.
10.4.4 403 Forbidden
The server understood the request, but is refusing to fulfill it. Authorization will not help and the request SHOULD NOT be repeated. If the request method was not HEAD and the server wishes to make public why the request has not been fulfilled, it SHOULD describe the reason for the refusal in the entity. This status code is commonly used when the server does not wish to reveal exactly why the request has been refused, or when no other response is applicable.
Important is the specification that «the request SHOULD NOT be repeated». A browser which never re-requests a 403 page might do the right thing. However, let's continue with 404:
10.4.5 404 Not Found
The server has not found anything matching the Request-URI. No indication is given of whether the condition is temporary or permanent.
[omitted]
Now we have a problem! Why would your 404 pages be cached if the specification allows them to be temporary?
Perhaps in your setup you have caching configured not correctly for your 403 and 404 pages. If this is so, please consult this answer on StackOverflow. It gives a detailed answer about caching 4xx pages.
If you don't want to mess with caching headers, use a so-called cache-buster and pass the system time like this (assuming PHP as your web language):
<a href="/fields?<?php echo time(); ?>">
This produces URLs like /fields?1361948122, increasing every second. It's a variant of the solution proposed by Markus A.
I assume the querystring 1361948122 is ignored by your resource. If it is not, pass the cache-buster in a querystring parameter instead, for example t=1361948122 and make sure that the parameter t is not evaluated by your resource.
In terms of the intended purpose of the HTTP error codes, I would definitely go with 403 Forbidden, because the page does exist (404 is out), but the user is forbidden to access it for now (and this restriction is not due to a resource conflict, like concurrent modification, but due to the user's account status, i.e. 409 is out as well in my opinion). Another sensible option based on it's intended purpose could have been 401, but as nalply already noted in his comment, this code triggers some, if not all, browsers to display a login dialog, as it implies that using the standard web-authentication mechanism can resolve the issue. So, it would definitely not be an option for you here.
Two things seem a little "misfitting" in the description of 403, so let me address them:
Authorization will not help ...: This only talks about the authorization mechanism inside the HTTP protocol and is meant to distinguish 403 from 401. This statement does not apply to any form of custom authorization or session state management.
... the request SHOULD NOT be repeated ...: A request must always be seen in the session context, so if the session context of the user changes (he unlocks a feature) and then he retries accessing the same resource, that is a different request, i.e. there is no violation of this suggestion.
Of course, you could also define your own error code, but since it probably won't be reserved in any official way, there is no guarantee that some browser manufacturer isn't going to intentionally or accidentally use exactly that code to trigger a specific (debugging) action. It's unlikely, but not disallowed.
418 could be OK, too, though. :)
Of course, if you would like to specifically obscure the potential availability of features, you could also decide to use 404 as that is the only way to not give a nosy user any hints.
Now, to your caching issue:
Neither one of these status codes (403, 404, 409, 418) should trigger the browser to cache the page against your will more than any other. The problem is that many browser simply try to cache everything like crazy to be extra snappy. Opera is the worst here in my opinion. I've been pulling my hair out many times over these things. It SHOULD be possible to work it all out with the correct header settings, but I've had situations where either the browser or the server or some intermediate proxy decided to ignore them and break my page anyways.
The only sure-fire way that I have found so far that absolutely positively guarantees a reload is to add a dummy request parameter like /fields?t=29873, where 29873 is a number that is unique for every request you make within any possibly relevant time scales. On the server, of course, you can then simply ignore this parameter. Note that it is not enough to simply start at 1 when your user first opens your page and then count up for following requests, as browsers might keep the cache around across page-reloads.
I do my web-development in Java (both server and client-side using GWT) and I use this code to generate the dummy "numbers":
private static final char[] base64chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_.".toCharArray();
private static int tagIndex = 0;
/**
* Generates a unique 6-character tag string that is guaranteed to not repeat
* for about 400 days, if this function is, on average, not called more often
* than twice every millisecond.
*
* #return the tag string
*/
public static String nowTag() {
int tag = (int) ((System.currentTimeMillis() >>> 5)); // adjust
char[] result = new char[6];
result[5] = base64chars[(tagIndex++) & 63];
result[4] = base64chars[tag & 63];
tag >>>= 6;
result[3] = base64chars[tag & 63];
tag >>>= 6;
result[2] = base64chars[tag & 63];
tag >>>= 6;
result[1] = base64chars[tag & 63];
tag >>>= 6;
result[0] = base64chars[tag & 63];
return new String(result);
}
It uses the system's clock in combination with a counter to be able to provide up to about two guaranteed unique values every ms. You might not need this speed, so you can feel free to change the >>> 5 that I marked with "adjust" to fit your needs. If you increase it by 1, your rate goes down by a factor of two and your uniqueness time-span doubles. So, for example, if you put >>> 8 instead, you can generate about 1 value every 4 ms and the values should not repeat for 3200 days. Of course, this guarantee that the values will not repeat will go away if the user messes with the system clock. But since these values are not generated sequentially, it is still very unlikely that you will hit the same number twice. The code generates a 6-character text-string (base64) rather than a decimal number to keep the URLs as short as possible.
Hope this helps. :)
I feel there is no need to throw an error code, in spite you just display a message like
You have to be Level XX to access this page or something funny like Come back when you grow-up
with code 200-OK itself, so there will be no cache problem and objective is also achieved.
I'm generally a fan of RESTful API design, but I'm unsure of how to apply REST principles for a validation API.
Suppose we have an API for querying and updating a user's profile info (name, email, username, password). We've deemed that a useful piece of functionality to expose would be validation, e.g. query whether a given username is valid and available.
What are the resource(s) in this case? What HTTP status codes and/or headers should be used?
As a start, I have GET /profile/validate which takes query string params and returns 204 or 400 if valid or invalid. But validate is clearly a verb and not a noun.
The type of thing you've described is certainly more RPC-style in its' semantics, but that doesn't mean you can't reach your goals in a RESTful manner.
There's no VALIDATE HTTP verb, so how much value can you get from structuring an entire API around that? Your story centers around providing users with the ability to determine whether a given user name is available - that sounds to me like a simple resource retrieval check - GET: /profile/username/... - if the result is a 404, the name is available.
What this highlights is that that client-side validation is just that - client side. It's a UI concern to ensure that data is validated on the client before being sent to the server. A RESTful service doesn't give a whit whether or not a client has performed validation; it will simply accept or reject a request based on its' own validation logic.
REST isn't an all-encompassing paradigm, it only describes a way of structuring client-server communications.
We have also encountered the same problem. Our reasoning for having the client defer to the server for validation was to prevent having mismatched rules. The server is required to validate everything prior to acting on the resources. It didn't make sense to code these rules twice and have this potential for them to get out of sync. Therefore, we have come up with a strategy that seems to keep with the idea of REST and at the same time allows us to ask the server to perform the validation.
Our first step was to implement a metadata object that can be requested from a metadata service (GET /metadata/user). This metadata object is then used to tell the client how to do basic client side validations (requiredness, type, length, etc). We generate most of these from our database.
The second part consist of adding a new resource called an analysis. So for instance, if we have a service:
GET /users/100
We will create a new resource called:
POST /users/100/analysis
The analysis resource contains not only any validation errors that occurred, but also statistical information that might be relevant if needed. One of the issues we have debated was which verb to use for the analysis resource. We have concluded that it should be a POST as the analysis is being created at the time of the request. However, there have been strong arguments for GET as well.
I hope this is helpful to others trying to solve this same issue. Any feedback on this design is appreciated.
You are confusing REST with resource orientation, there's nothing in REST that says you cannot use verbs in URLs. When it comes to URL design I usually choose whatever is most self-descriptive, wheather is noun or verb.
About your service, what I would do is use the same resource you use to update, but with a test querystring parameter, so when test=1 the operation is not done, but you can use it to return validation errors.
PATCH /profile?test=1
Content-Type: application/x-www-form-urlencoded
dob=foo
... and the response:
HTTP/1.1 400 Bad Request
Content-Type: text/html
<ul class="errors">
<li data-name="dob">foo is not a valid date.</li>
</ul>
A very common scenario is having a user or profile signup form with a username and email that should be unique. An error message would be displayed usually on blur of the textbox to let the user know that the username already exists or the email they entered is already associated with another account. There's a lot of options mentioned in other answers, but I don't like the idea of needing to look for 404s meaning the username doesn't exist, therefore it's valid, waiting for submit to validate the entire object, and returning metadata for validation doesn't help with checking for uniqueness.
Imo, there should be a GET route that returns true or false per field that needs validated.
/users/validation/username/{username}
and
/users/validation/email/{email}
You can add any other routes with this pattern for any other fields that need server side validation. Of course, you would still want to validate the whole object in your POST.
This pattern also allows for validation when updating a user. If the user focused on the email textbox, then clicked out for the blur validation to fire, slightly different validation would be necessary as it's ok if the email already exists as long as it's associated with the current user. You can utilize these GET routes that also return true or false.
/users/{userId:guid}/validation/username/{username}
and
/users/{userId:guid}/validation/email/{email}
Again, the entire object would need validated in your PUT.
It is great to have the validation in the REST API. You need a validation anyway and wy not to use it on the client side. In my case I just have a convention in the API that a special error_id is representing validation errors and in error_details there is an array of error messages for each field that has errors in this PUT or POST call. For example:
{
"error": true,
"error_id": 20301,
"error_message": "Validation failed!",
"error_details": {
"number": [
"Number must not be empty"
],
"ean": [
"Ean must not be empty",
"Ean is not a valid EAN"
]
}
}
If you use the same REST API for web and mobile application you will like the ability to change validation in both only by updating the API. Especialy mobile updates would take more than 24h to get published on the stores.
And this is how it looks like in the Mobile application:
The response of the PUT or POST is used to display the error messages for each field. This is the same call from a web application using React:
This way all REST API response codes like 200 , 404 have their meaning like they should. A PUT call responses with 200 even if the validation fails. If the call passes validation the response would look like this:
{
"error": false,
"item": {
"id": 1,
"created_at": "2016-08-03 13:58:11",
"updated_at": "2016-11-30 08:55:58",
"deleted_at": null,
"name": "Artikel 1",
"number": "1273673813",
"ean": "12345678912222"
}
}
There are possible modifications you could make. Maby use it without an error_id. If there are error_details just loop them and if you find a key that has the same name as a field put his value as error text to the same field.