Not a great title but I'm looking more for some guidance, have searched quite a bit. I'm building a web app with an MVC framework (but I think this is a more generic question). I'm trying to make many views that do a lot of AJAX style calls and say I have a site with users and they can add folders and files to their profile page. So the URL maybe like:
/profile/{id}
I have a Profile controller that returns a view with various information. I'd like files and folders listed on the profile to be dynamic so I want to populate it through AJAX calls. I was thinking I would have a URL like
/listFolders/{userId}
and
/listFiles/{folderId}
Is it reasonable to have these URLs return a JSON object for these two URLs and not even provide an HTML view (since, for the browser, the view will just be the whole profile page)? Also, what should I return for errors, say if the user/folder doesn't exist or the current logged in user doesn't have access the data? Is it reasonable to just set 404 or 403 HTTP error codes or do they need to return some kind of HTML? What if there are multiple reasons for it to fail and I'd like to pass that along? Should I arbitrarily choose HTTP error codes or define integer return codes like 0, 1, 2, etc? Also, should the URL specify that they are JSON, like listFoldersJSON instead of listFolders?
I have used JSON in my previous projects. For errors, we return error codes.
We decided to do so because we were dealing with API clients. So we want to deal with error codes (REST is based on HTTP, so it was appropriate to return error codes).
Since you are writing your own application, you can pretty much choose how you want to send your errors to the view. You can create a error json object and in the view you have to check whether this object is not null.
pretty much a if-else in the view. Else you can return error codes and check for the code before rendering the JSON into whatever view you want to.
I would go with error codes, because that complies with the REST philosophy.
Generally speaking, I handle this situation by throwing a 500 internal server error with a status message. Most client libraries such as jQuery provide built in error handling with a failure callback like:
jQuery.ajax({
success:function(response){
//do some success stuff
},
error:function (xhr, ajaxOptions, thrownError){
//handle error
alert(xhr.responseText);
}
});
It's entirely feasible to return JSON objects as opposed to actual views.
As far as the url, you can use listFolders and listFiles without taking on the JSON. However, I recommend you use lower case urls for the sake of how the server is setup. For instance, I know on Apache that sometimes listFiles would be fine, but listfiles would lead to missing page exception.
With regards to errors: You could setup a header of sorts in your JSON response and use whatever system you'd like. For instance, you could do something like
status_code: 0 //where 0 means successful
status_detail:success!
Where, if the status_code is something other than 0, you'd check the status_detail and know to ignore everything else inside the response.
Also, what should I return for errors, say if the user/folder doesn't exist or the current logged in user doesn't have access the data?
These are basic HTTP Error codes:
401 : Unauthorized
404 : Not found
There's a whole slew of error messages in the HTTP spec:
HTTP Status Code Definitions
Also, should the URL specify that they are JSON, like listFoldersJSON instead of listFolders?
Generally, a good way to handle this is for the client to set the 'accepts' header to something like 'text/json' or 'text/xml' and for the server to parse it out and respond with the correct response. This way you can use the same URL but send back different views of the data (if you ever wanted)
Related
To simplify, say you have a REST API with a frontend that has login form in the frontend and you want to check whether a User exists or not. Front-end HTTP/POST some data to the back-end and back-end queries the database. The result is the user does not exist and you want to return that result to the front-end.
I know there might be tons of ways to return the result, but is there any "standard" or "more correct way" to return "User does not exist" result as JSON? Some posibilities i'm thinking:
Return a JSON as a string with the result?
Return empty object?
Return empty User object with a boolean doesNotExist=false?
Return 404 not found or some other http code response?
A mix between 4 and 1?
Solution:
Responding with a HTTP 404 Code is enough, no JSON body is needed. Keep in mind for this login use case, as pointed out by the answers, it is not recommended to repond with a 404 HTTP when the user is not found for security purposes.
Useful resource:
Understanding REST: Verbs, error codes, and authentication
The standard way to handle the situation where you don't find a resource is to return a 404 error status. If, for example, your uri is something like /user/{id} then this is an attempt to access a resource/document of type user with the given id, and in this case, if the user is not found then a 404 would be entirely appropriate. You do not need to specifically return a json response in this case.
However, you should be aware that for security purposes it is considered insecure to validate the existence of a user in this way. If an attacker knows a valid username or id they can try to brute-force their password. A lot of systems return the same error for invalid user identifiers and invalid password -- invalid credentials -- so that attackers cannot know if they have guessed the username correctly. A 401 error is often considered a useful response when attempting to authenticate a user. If the user does not exist or the given creds are invalid, then a 401 should be returned.
There is some standard way, most of the time HTTP status code is sufficient.
In case you think of a custom message with more detail then make a POJO containing error code, detail, or even an exception category and return it to UI.
I want to confirm that I can return an image or a CSS file when I generate a 403 error.
From the documentation, it sounds like I can, as per: any included representation from section 6.5.
6.5. Client Error 4xx
The 4xx (Client Error) class of status code indicates that the client
seems to have erred. Except when responding to a HEAD request, the
server SHOULD send a representation containing an explanation of the
error situation, and whether it is a temporary or permanent
condition. These status codes are applicable to any request method.
User agents SHOULD display any included representation to the user.
Source: https://www.rfc-editor.org/rfc/rfc7231#section-6.5
Would you agree that we do not have to return HTML on a 403 error?
Yes, it's perfectly fine to return something else than HTML for an error.
Image hosts sometimes return errors as images so they would show up when embedded with <img>. Web APIs will often return an error description as JSON/XML. So it's not only perfectly fine, but also common.
Out of curiosity, are there any popular standards for returning server side exceptions (and corresponding details) in an API that returns JSON? The exceptions could be anything from uncaught exceptions in the code or thrown exceptions put in place by the developer.
Currently I'm setting the HTTP Status Code according to their Wiki definitions'
My JSON response would look something like this:
HTTP Code: 401
{'error': 'Authentication required.', 'message': 'You must be authenticated to perform that action.'}
You can take a look at JSON-RPC (http://en.wikipedia.org/wiki/JSON-RPC).
In case of success, the response is like this:
{
"result": ...(returned data)...
...
}
and in case of error, the response is like that:
{
"error": ...(error details)...
...
}
When the error occured, "error" property must be present and "result" property must not be returned. In case there was no error, "error" property must not be set. This way you can distinguish errors from successful responses based solely on the content of the response, without the need to check the headers (like response codes).
The standard structure of native ECMAScript error objects is:
{
name: ...,
message: ...
}
where "name" is the type of the error (the name of the corresponding constructor, like "Error", "SyntaxError", etc.). In your example, you could use the name "AuthentificationError", for instance.
Yes you can do the same.
As we know that Web servers allow us to create custom error pages for HTTP errors, in those custom error pages you have to serve the JSON reply
Example:
Add the following to your WEB-INF/web.xml:
<error-page>
<error-code>401</error-code>
<location>/autherror.jsp</location>
</error-page>
In the autherror.jsp file code the required logic to accomplish your needed JSON reply.
Try being a bit more verbose regarding the error you are sending. This structure has been suggested in some places to give sufficient information both for users and developer using your API
"error":{
"code":"410",
"long":"410001",
"message":"cannot connect to DB",
"developer":"Connection to the DB was unsuccessful due to ...",
"documentation": "mysite.com/help/errors/..."
}
Return the correct HTTP code for error. It is bad practice to return code 200 with error.
Extend the code with your own error IDs
Provide short message that roughly outlines the cause of the error. Consider adding more detailed message for the developers. Have in mind that API error messages are 99.9% of the time read by developers so make them happy by providing technical details (within reason) so that they can resolve ASAP.
In case you keep public documentation about your api and error codes, simply add the url.
I stumbled over a practice that I found to be quite widespread. I even found a web page that gave this a name, but I forgot the name and am not able to find that page on google anymore.
The practice is that every JSON response from a REST service should have the following structure:
{
"status": "ok",
"data": { ... }
}
or in an error case:
{
"status": "error",
"message": "Something went wrong"
}
My question: What is the point why such a "status" property should be required in the JSON? In my opinion that is what HTTP status codes were made for.
REST uses the HTTP means of communication between client and server, for example the "DELETE" verb should be used for deleting. In the same way, 404 should be used if a resource is not found, etc. So inline with that thinking, any error cases should be encoded properly in the HTTP status.
Are there specific reasons to return a HTTP 200 status code in an error case and have the error in the JSON instead? It just seems to make the javascript conditional branches more complex when processing the response.
I found some cases where status could be "redirect" to tell the application to redirect to a certain URL. But if the proper HTTP status code was used, the browser would perform the redirection "for free", maintaining the browsing history properly.
I picture mainly two possible answers from you:
Either there are two quarreling communities with their favorite approach each (use HTTP status always vs. use HTTP status never)
or I am missing an important point and you'll tell me that although the HTTP status should be used for some cases, there are specific cases where a HTTP status does not fit and the "status" JSON property comes into play.
You are right. I think what you are seeing is a side-effect of people not doing REST correctly. Or just not doing REST at all. Using REST is not a pre-requisite for a well-designed application; there is no rule that webapps have to be REST-ful.
On the other hand, for the error condition, sometimes apps want to return a 200 code but an error to represent a business logic failure. The HTTP error codes don't always match the semantics of application business errors.
You are mixing two different Layers here:
HTTP is for establishing (high-level) connections and transferring data. The HTTP status codes thus informs you if and how the connection was established or why it was not. On a successful connection the body of the HTTP request could then contain anything (e.g. XML, JSON, etc.), thus these status code have to define a general meaning. It does not inform you about the correctness or type (e.g. error message or data) of the response.
When using JSON for interchanging data you could certainly omit the status property, however it is easier for you to parse the JSON, if you know if it includes the object you were requesting or an error message by just reading one property.
So, yes, it is perfectly normal to return a 200 status code and have a "status": "error" property in your JSON.
HTTP status codes can be caused by a lot of things, including load balancers, proxies, caches, firewalls, etc. None of these are going to modify your JSON output, unless they completely break it, which can also be treated as an error.
Bottom line: it's more reliable to do it via JSON.
What is the best practice with regard to sending error responses in a JSON web service? I have seen it done several ways and wanted to know whether there were any agreed-upon standards or best practices among the choices.
I've seen it done where the response includes indication of success or failure as well as the data to be returned or a suitable error message, e.g.
[{'success':true, 'data':{...}]
[{'success':false, 'data':{'message':'error'}]
But I've also seen examples where the JSON object only includes data, and the service uses the normal HTTP error codes to indicate a problem (403, 404, 500, etc). (This is how the Twitter API does it.)
Is there a "right" way to do this, or is it just a matter of style? Is the latter method more "RESTful?"
In a "RESTful" approach, the primary error response is indicated by an appropriate status code (4xx/5xx).
Your message should provide addtional, application-specific hints on how to recover from the error. This may include human-readable representations of the error that has occured or some kind of more technical indicator (i.e. providing an Exception class name).
For being generic, keep to a fix syntax for your error messages. This allows you to introduce new error messages withour breaking the clients.
Use the appropriate HTTP codes and put what you now call "data" as the body of the response. This is the only correcty RESTful way to make the API users aware of an error.
Just doing this will not make your API RESTful, but not doing it will surely make your API non RESTful.
An example of well-used HTTP status codes for errors is in the Dropbox v1 API reference, have a look at the "Errors" sections under each method, they explain which error codes you should expect and what is the associated meaning in that particular method.