I have an iOS app in which a REST WebService request is made through NSURLConnection. It works fine in all cases except when the service (implemented with .NET - IIS 7) has no data to return. When it has no data, the response shows status 204 alright, and has an empty response body, but it takes a very long time (excess of 45-60 seconds) to trigger the connection:didReceiveResponse delegate.
I noticed that in the C# code, the status code is explicitly set to 204 in these cases, and "null" is returned (which I know is incorrect in itself: 204 responses should return nothing, not even null).
Debugging this WebService with Fiddler, I found a warning stating that there was a mismatch between the response-length header field (which had a value of '4', perhaps from "null"?), and the response-body, which of course was empty.
Now this whole issue (of the NSURLConnection delegates taking a long time to get triggered) was fixed when I stopped setting the status code to 204, but the strange part is, this only happened in my production environment, and not in the staging environment.
Is there any reasonable explanation for this? Perhaps some IIS setting?
Related
I recently joined a new project. In this project, all APIs in service always return status code 200. Even, if that response was should be 400 or 404, the API returns status code 200.
I asked the reason why APIs don't return other response codes, and programmers told me they don't use response code. they put information in the body.
for example, there are some missing required fields, they return response status code 200, but the body returns like this
{"result" : "fail"}
if an unauthorized user tries to access, the status code is 200, the body returns like this
{"result" : "unautherized"}
what I did before was very different, I always specified status code by cases and try to return suitable status code and message. I thought that this is the part of the HTTP protocol. However, they told me specifiying status code like 400, 404, 300, is part of RESTful API, and returning always 200 is the right status code because the server responded and it is alive. APIs, always have to return 200 except 500. Because when the server dies, it can't return anything.
So these are the question.
The server should always return status code 200 except the server dies?
Specifying various status code is the part of REST API?
Not using status code is common?
The server should always return status code 200 except the server dies?
I asked the same on Software Engineering a few years ago: Do web applications use HTTP as a transport layer, or do they count as an integral part of the HTTP server?. See also Should I use HTTP status codes to describe application level events.
Specifying various status code is the part of REST API?
No, REST is transport-agnostic. It can be used on top of HTTP, but doesn't need to. Therefore it doesn't say anything about status codes.
Not using status code is common?
Depends on who you ask.
It's a matter of preference. I extremely dislike "What is the most appropriate status code for scenario X?" questions. Also, there's:
HTTP Status Codes
HTTP Response Status Codes – REST API Tutorial
And plenty of others. I remember there being a site offering a flowchart for determining the (most) appropriate status code.
In general, don't bother. Consistency and thorough documentation is more important than assigning the appropriate number.
I've joined a project that uses exactly the same strategy -- embed status message inside the response body, and leave status code to be always 200. For consistency reason, it is better to follow existed strategy during the software maintenance time. However, it is not recommended for any new project, with reasons listed below:
"Specifying status code like 400, 404, 300" follows the RESTful design, but it is NOT part of REST. Actually, usage of 302 (redirect), 401 (Basic and Digest authentication), 404 (default not-found page in web server), 500 (default server error page) is popular decades ago, long before RESTful API these days (I know RESTful is proposed decades ago, but it is only popular in recent years).
"Returning always 200 is the right status code because the server responded and it is alive". This is incorrect. If it is, then only 200 can be used for status code -- as long as server is "alive", it can return message. 500 is not acceptable either, as in that case, server is still "alive", it does not die... Then, as the status code should always be 200, why do we need the code?
"Not using status code is common?". Actually, it is opposite. As RESTful API design scheme is more and more popular, more projects are using HTTP status code to deliver message semantics. But anyway, this is an opinion-based viewpoint.
What the team is doing may be completely appropriate for the circumstances that they are in. But labeling those patterns as REST sounds inaccurate.
I say this, because it sounds like the team hasn't given any thought to how their current messaging scheme works with generic participants in the message exchange.
For instance, caching is an important concern in the REST architectural style. In HTTP, RFC 7234 describes the caching semantics. In particular, there's a section on how cache invalidation is triggered by status codes. This in turn says that, if you aren't distinguishing between the status codes in successful and unsuccessful cases, then the generic components are going to be invalidating cached entries which shouldn't be invalidated.
We have a route in our API which (when called) hits another 3rd party API.
e.g.
HTTP-GET /account/1
this returns some data from our database AND from .. say .. a 3rd party api like Auth0/Okta/SalesForce/whatever.
Now, if this 3rd party api call fails for any reason (fails == 4**, 5** or even a 200 OK but the content is some error message) then what error status code should I pass back to the client calling my API?
Initially I was thinking an HTTP-500-Server-Error but ... I'm not so sure now because I can prevent this error from occurring in the server if I return a nice error message back to the client. So then I thought, return an HTTP-200-OK which contains some key/value of the downstream issue/error ... but is this really OK (pun intended). To me, HTTP-200-OK is like the answer returned is really ok.
So i'm not sure what people do in this scenario.
I feel like an HTTP-500 is for errors that occur but haven't really been handled and/or accounted for.
Now, if this 3rd party api call fails for any reason (fails == 4**, 5** or even a 200 OK but the content is some error message) then what error status code should I pass back to the client calling my API?
APIs should be designed from the consumer's perspective. In most of situations, the API consumer wont't care if the request is fulfilled by the server they are firing a request to or by a downstream server.
If the request to the downstream server prevents your server from fulfilling the client request, you could go for 500 or 503. Alternatively you could return some cached data (if you have any) and return a 2xx status code.
We are implementing a REST based web service and we have some queries on some of the use cases.
Consider there is a unique account which contains some information (Ex. added to cart information)
What response code should we return if no cart information exists (Ex. 0).
Our understanding was to return 200 with empty response.
User added cart information to his account, but cart is removed by admin.
What HTTP statuscode shall be used?
For situation 1 there are two options:
The cart is empty. I would return 200 OK returning an empty collection.
The cart doesn't exist. The correct case for this is 404.
For situation 2, it's really the same. The only potential difference is that if you returned 404 for situation 1, you could choose 410 gone, as it indicates that a cart was here before, but it's now gone.
Regardless of which you choose, I would recommend you take the same strategy for both situations. E.g.: Either return a 2xx code for both or a 4xx code for both.
If the admin deleted the cart by doing a DELETE request, then the 404/410 status codes are more appropriate.
See This Blog. It explains it very well.
Summary of the blog's comments on 204:
204 No Content is not terribly useful as a response code for a
browser (although according to the HTTP spec browsers do need to
understand it as a 'don't change the view' response code).
204 No Content is however, very useful for ajax web services which may want to indicate success without having to return
something. (Especially in cases like DELETE or POSTs that don't
require feedback).
The answer, therefore, to your question is use 404 in your case. 204 is a specialized reponse code that you shouldn't often return to a browser in response to a GET.
The other response codes are even less appropriate than 204 and 404.
200 should be returned with the body of whatever you successfully fetched. Not appropriate when the entity you're fetching doesn't exist.
202 is used when the server has begun work on an object but the object isn't fully ready yet. Certainly not the case here. You haven't begun, nor will you begin, construction of user 9 in response to a GET request. That breaks all sorts of rules.
400 is used in response to a poorly formatted HTTP request (for instance malformed http headers, incorrectly ordered segments, etc). This will almost certainly be handled by whatever framework you're using. You shouldn't have to deal with this unless you're writing your own server from scratch. Edit: Newer RFCs now allow for 400 to be used for semantically invalid requests.
Wikipedia's description of the HTTP status codes are particularly helpful. You can also see the definitions in the HTTP/1.1 RFC2616 document at www.w3.org
I am setting cachePolicy on url request.
First call to an url (GET) return status code in 200.
Second call to the same url return 200.
If use a rest client i obtain for the first call 200, and for the second, with properly header ( If-None-Match) 304
Reading online i understand that iOS serialize first request with status code 200 and retrieve it for the second call.
There is a way to obtain 304 instead of 200 in UrlCache or understand if it the data came from cache and not from network.
From http://jonathanblog2000.blogspot.com/2017/07/ios-uiwebview-nsurlsession-cache.html :
If you want to test and verify the cache works properly in your app, you have to log the device http traffic, as the delegate of NSURLSession will never see the 304 status code returned from server, it will be automatically replaced by the status code in the cached response.
This is a good thing. This means your app can just pretend you got a successful response, and not worry about how the response was obtained or what sort of optimizations was happening. You just deal with the response the same way regardless of whether it was pulled from the cache or not.
I'm trying to figure out what the correct status code to return on different scenarios with a "rest-like" API that I'm working on.
This example is borrowed from another question about syntax type issues in the body, but my question assumes valid syntax throughout.
Let's say I have an endpoint that allows POST'ing purchases in JSON format. It looks like this:
{
"account_number": 45645511,
"upc": "00490000486",
"price": 1.00,
"tax": 0.08
}
What is the appropriate status code if:
the account number does not exist
the account is closed or the
account identified is not the right kind of account
These are all firmly business layer issues that prevent "processing" from occuring, however, one scenario involves something that in a GET would be a 404.
Note that the account number is not in the URL, so is 404 misleading?
Let's take these one at a time. Each of these codes is a signal to your client that the server is functioning correctly, and that something must be changed in the request before it can be successfully carried out.
HTTP 400
The 400 (Bad Request) status code indicates that the server cannot or will not process the request due to something that is perceived to be a client error (e.g., malformed request syntax, invalid request message framing, or deceptive request routing).
400 typically indicates a syntax error; as a user, I should look at the structure of the request before trying again.
HTTP 404
The server has not found anything matching the Request-URI. No indication is given of whether the condition is temporary or permanent. The 410 (Gone) status code SHOULD be used if the server knows, through some internally configurable mechanism, that an old resource is permanently unavailable and has no forwarding address. 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.
404 is the standard code used when a web server can't match a url path to anything. As a client, I should look at the URL of the request before trying again.
HTTP 422
The 422 (Unprocessable Entity) status code means the server understands the content type of the request entity (hence a 415 (Unsupported Media Type) status code is inappropriate), and the syntax of the request entity is correct (thus a 400 (Bad Request) status code is inappropriate) but was unable to process the contained instructions. For example, this error condition may occur if an XML request body contains well-formed (i.e., syntactically correct), but semantically erroneous, XML instructions.
422 is generally used for content violations. As a user, I should look at the content of my request before trying again.
Now in your case, account number is an identifying number, but is not included in the URL. A 404 would signal to your user that the URL is wrong, not the payload. Stated another way, suppose your url is:
http://www.myservice.net/endpoint
A 404 would indicate to me that no service exists at /endpoint, instead of no account number. No matter what content I submit, the server will not process my request. The fix I should make then would be to look for an error in the URL, instead of the data payload. So to me a 422 would point me in the right direction, unless you begin to include the account number in the URL.
Ultimately these are design preferences, just make sure you communicate them clearly to your users.
If you consider the accounts to be part of the state of the resource (though indirectly) then you might also consider 409 since that state is in conflict with the semantics of the request.
However, 422 is gaining popularity via Ruby on Rails and Dropwizard where it is used to indicate non-syntactic issues with the body. That growing tendency represents a strong signal to a developer using the API that they need to exclude syntax and focus on the body. Developer time is usually the single largest cost your customers will ever incur, so by directing the attention of their developers you will keep them happy.
So 409 is a possible answer, though rather novel, and 422 is the more conventional approach, although obviously RoR and DropWizard are both rather new so these conventions can be said to be changing fast!
I'd say 422 is adequate in your case, but 400 isn't bad if it's consistent with the rest of your API. It's a common convention to use 400 as an umbrella error code when there's something wrong on the client side, but either the error doesn't fit a particular error code, or you don't want to use too many of them.
A 404 is definitely wrong if there's something wrong with the POST payload.
Case 1 : Account number doesn't exist.
This is a standard case for 404.
Case 2 : Account is closed.
This has do with the logic if you keep the account details when you close it.
If you donot keep the account details when the account is closed, you can give 404.
If you keep the account details after it is closed, you must be marking it (like raising some flag) (or whatever logic you have). In this case, Status code 400 with a proper message of why it is failed and possibly remediation will do.
Case 3 : Account identified is not the right kind of account.
403, as the account is not authorised for completing any purchases makes sense to me. If there is no concept like authorised account, 400 with a explanatory message will do. But I would insist to go with 403 in this case.
Actually, in this case 404 sounds good to me.