REST API Framework. Recommended behavior for invalid querystring parameter - api

I am implementing a REST API Framework, and I wonder what the recommendedbehavior is, when a client submits an invalid querystring parameter.
I will illustrate what I mean with a specific example:
Say, I have an API handler on the /api/contacts/ endpoint, and the handler provides a querystring filter named id, which enables clients to select certain contacts with the provided IDs.
So, a GET or DELETE request could be /api/contacts/?id=2&id=4&id=lalalala.
Clearly, there is no such thing as a Contact with id=lalalala. In this case, what should the server behave like?
Ignore the invalid Contact with id=lalalala, and only filter the contacts on the valid ids, 2 and 4.
Respond with an error code that indicates this error. If yes, which error code should be provided?
Thanks in advance.
Edit: To clarify; The main focus of the framework I develop, is having a predictable behavior and hence response codes. For this reason, I want the clients consuming an API built on this framework, to expect the least possible surprises.
So, the question basically is: Should the API return an error in this case(and if yes, which)? Or ignore invalid filter entries, and only filter on the correct querystring parameters?

Since this is a REST call, we are talking about resources. And whenever we have a wrong filter, we should return a proper error code.
In this case i would go for 400 - bad request as the resource was found and correctly mapped (/api/contacts), but there was a problem with the query string part. Therefore a 400 and not a 404.
Would return a 404 if someone requested /api/contacts-all or some non-existant resource.
EDIT based on comments below
Agree to your comment. Ideally a 400 is a problem with the request. Going by that, you could use a 422 Unprocessable Entity. Please look at the stackoverflow link below and it talks about the same thing.
I would guess that developers around the world would be more comfortable seeing a 400 than 422 for such logical errors due to the fact that bigger companies are using 400 and not 422.
References:
Http status codes and
400 for logical error vs malformed request

Following the letter of the law, the response should be a 404 Not found. However, nobody is going to get too upset with you if you prefer to return 400 - bad request.
I would definitely return a 4XX status code though. You want the client to know that they made an error.

Related

Rest API: Response HTTP status code for applicative semantic error

Suppose to have a REST API which updates the stock of some products in an e-commerce portal:
URL : /products/stock
METHOD : PUT
BODY :
{
"PRD001": 3,
"PRD002": 2
}
Where the request body is a map made of <<PRODUCT_CODE>> : <<USER_REQUIRED_QUANTITY>> entries
At some point, the server receives a well-formed syntactic request, but the logic behind the API fails because:
One or more of the sent PRODUCT CODES do not exist.
The USER_REQUIRED_QUANTITY requested for one of the products having PRODUCT_CODE is unavailable because of insufficient stock.
Which HTTP CODE should the REST API return for these "semantic applicative errors"?
In my opinion:
It shouldn't return 400 - BAD REQUEST because the REQUEST is well-formed from a syntactic perspective.
In the case of an inexistent product, it shouldn't return 404 -NOT FOUND because the resource is related to a stock and not to a specific product. Returning 404 - NOT FOUND could lead the client intto an error.
It could return a 409 - CONFLICT (The request could not be completed due to a conflict with the current state of the resource)
It could return a 422 Unprocessable Entity (The server understands the content type and syntax of the request entity, but still server is unable to process the request for some reason). Anyway, this status code is part of WebDAV specific and not part of the HTTP)
What do you think about this specific use case?
And, in a more general way, in which way do you handle HTTP Status codes according to applicative semantic errors?
Thank you
Important idea - status codes are metadata of the transfer of documents over a a network domain; they describe the semantics of the HTTP response so that general purpose HTTP components can do intelligent things (e.g. invalidate cached responses).
Which HTTP CODE should the REST API return for these "semantic applicative errors"?
The fact that the values in the request body are the problem strongly suggests that we want some flavor of 4xx Client Error semantics.
I'm inclined to guess that the simplest approach would be to use 403 Forbidden
The 403 (Forbidden) status code indicates that
the server understood the request but refuses
to fulfill it.
Any nuance that you need to share with the user/bespoke client is described in the body of the 403 response.
From what I can tell, 409 Conflict isn't right, but also isn't going to get you into a lot of trouble.
For a general purpose component, 403 and 409 are handled essentially the same way -- in theory a general purpose component could try to "resolve the conflict" on its own and resubmit the request, but in practice we don't have a standard for describing the nature of the conflict, which means that the component isn't going to know a way to modify the request.
So while I would decline a pull request (PR) that used a 409 here, I would also accept a PR that used a 409 and also included a decision record documenting the trade offs that the implementer had considered in this specific context (for example - it might be important that your human operators easily be able to distinguish this case from authentication issues when scanning access logs).
In other words, make the boring choice unless you have really good reasons to do something else. If you have really good reasons to do something else, write them down.
422
My doubt about this one is that it is not part to the HTTP specs.
Don't be worried at that. HTTP status codes are intended to be extensible. Anything you find in the IANA status code registry should be considered safe to use.
Also, today, the registered reference for 422 is the current HTTP Semantics specification (RFC 9110).
That said, I wouldn't use it here, because I don't think the semantics are as good a fit for your circumstance as 403.
The 422 (Unprocessable Content) status code indicates that the
server understands the content type of the request content
(hence a 415 (Unsupported Media Type) status code is inappropriate),
and the syntax of the request content is correct, but it was unable
to process the contained instructions. For example, this status
code can be sent if an XML request content contains well-formed
(i.e., syntactically correct), but semantically erroneous XML
instructions.
My interpretation of this is that we're trying to indicate that there's a problem specific to the semantics of the request body (ex: a required field is missing). It announces that we're unable to process the request, rather than announcing that the processing failed.
In other words, 422 is "I don't know what this means", where 403 is "I know what this means, but I won't do it."
We also have considered using the 403 - FORBIDDEN code, but it seems to be more related to authorization issues.
The specification gives wider latitude than the most common usage.
a request might be forbidden for reasons unrelated
to the credentials.
That said, choosing a different status code can be the right engineering trade off. If the benefits of doing the right thing are small, and the costs (in particular, the support and operational costs) are large, well... maybe being successful is more important than being right.

What response code corresponds in REST API to not finding a resource due to query params?

I found in my job that people are designing a RESTs API that has endpoints that return a single Json object (not a collection) based in query params (not path param).
For example:
/users?name=John&surname=Sparrow
with response body
{id:10, name="John", surname="Sparrow", gender="male"}
But what response code corresponds in REST API to not finding a resource due to query params?
For example:
/users?name=John&surname=Smith
(when John Smith doesn't exist).
I don't think it is a 404 error because /users endpoint exists, but I don't know if I must return a 400 error or a 200 without body (or null value) or other kind of response
Can you help me?
Thanks
What is most appropriate depends on whether an empty result list is OK or a clear failure. Whether parameters are PathParams or QueryParams has no bearing on return codes.
My general approach is that search functions such as findStuffBySearchTerms always return a successful HTTP code such as 200 and either the results or an empty list. On the other hand, fetchStuffById where I expect the entity to be found will return HTTP 404 if it is not found.
What response code corresponds in REST API to not finding a resource due to query params?
404 Not Found.
I don't think it is a 404 error because /users endpoint exists,
The resource identifier includes the query params. Which is to say, the query parameters are part of the identifier in precisely the same sense that path segments are part of the identifier.
In your request body, you can describe the circumstances of your implementation as precisely as you like.
But the audience of HTTP status codes includes general purpose components (browsers, proxies, web crawlers), for whom the response code is the primary mechanism for describing the semantics of the response:
The status-code element is a 3-digit integer code describing the result of the server's attempt to understand and satisfy the client's corresponding request. The rest of the response message is to be interpreted in light of the semantics defined for that status code. -- RFC 7230
That said, your server owns its own resources, and therefore you get to decide whether or not a resource exists, and what it's current representation looks like.
GET /users?name=Dave HTTP/1.1
200 OK
Content-Type: text/plain
Dave's not here, man.
From an HTTP/REST framing, that's a perfectly reasonable exchange; somebody asked for the latest representation of /users?name=Dave, and the latest representation is a plain text document. Absolutely fine.
The key idea here is that that HTTP status-code is metadata of the transfer of documents over a network domain.
HTTP is indifferent to the semantic meaning of the representations of resources.
That said, you should be considering in your design concerns like "what does this look like in our access logs?" If you want your operators to be able to distinguish this case from the similar case where the query parameters match information in your database, 200 vs 404 is the natural way to do that.
You'll normally prefer 404 to the other error status codes for this case because 404 indicates the response is cacheable, which is probably want you want when you are passed a request-target that has a spelling error in it somewhere.

Microservices HttpStatus Codes

this is a question related to good practices in signalling the communication between various APIs in a Microservice architecture.
I am facing the following 'events':
one Microservice is DOWN (physically)
one Microservice is calling another one using a wrong URL
one Microservice is calling another one using a correct URL but wrong arguments (query params for example, or POST body fails validation)
one Microservice is asking another one for a resource and that particular resource cannot be found in DB (lets say a findById type)
I need to find a better way to signal these by using HTTP Status codes and various payloads explaining in detail what's going on.
For example:
for case 1, I could use NOT_FOUND (404) with a payload: API_DOWN
for case 2, I could use BAD_REQUEST (400)
for case 3, I could also use BAD_REQUEST (400) with a validation payload message
for case 4, I could also use NOT_FOUND (404) with a RESOURCE_NOT_FOUND message
everything else could be INTERNAL_SERVER_ERROR if caused by a uncaught exception.
200 OK for good stuff
Any thoughts? I am not 100% happy with my interim solution. Want to make it better. I understand the fact there are 2 animals here: one is client-server signalling and second one is related to data (payloads missing etc)
one Microservice is DOWN (physically) - I could use NOT_FOUND (404) with a payload: API_DOWN
In this instance you will have no control over what response code the consumer receives. Depending on how the service is hosted and managed, you may receive any of 500 Server error, 502 Bad gateway, 503 Unavailable, or 504 Timeout. However, what you will get depends on your infrastructure and stack set up.
one Microservice is calling another one using a wrong URL - I could use BAD_REQUEST (400)
This is semantically identical to the above case. There is very little difference between trying to call a service which is unavailable, and trying to call one which doesn't exist.
one Microservice is calling another one using a correct URL but wrong
arguments (query params for example, or POST body fails validation) - I could also use BAD_REQUEST (400) with a validation payload message
There are a couple of variants of this. One is calling PUT on a resource which only supported PATCH, for example. In this instance there is a status code for this, it's 405 Method not allowed. Again, you're usually not in control here - most service frameworks will automatically return this status code to consumers if you do not define a requested operation against a given resource.
Another variant (as in your example) is incorrect query parameters. Again most frameworks will automatically return 400 Bad request (or 422 Unprocessable) in this instance. If the query parameter is provided but is invalid in some other way, then 400 Bad request is appropriate.
Note: it is not generally appropriate to return a 400 Bad request for an "invalid" path parameter.
one Microservice is asking another one for a resource and that
particular resource cannot be found in DB (lets say a findById type) - I could also use NOT_FOUND (404) with a RESOURCE_NOT_FOUND message
Yes, 404 Not found is the correct status code.
everything else could be INTERNAL_SERVER_ERROR if caused by a uncaught
exception.
Not necessarily. One status code I use often is 409 Conflict for those instances where the input is OK but has caused some kind of problem (like duplicate entities).
200 OK for good stuff
200 is fine in many situations. However, consider 201 Created if something has been added, 202 Accepted if the call had no effect (like if you try to create a resource but the resource was already there), or 204 No Content if you want to explicitly call out that no return type should be expected.
Just a small addition what #tom-redfern already said.
There's a nice map i like. Looks like a plan for an underground.
HTTP Status Map by Restlet
On the bottom right side of the image you have nice summary.
Code 100: Informational
Code 200: Success
Code 300: Redirectional
Code 400: Client Error
Code 500: Server Error
You can hover the status codes and get a nice and short explanation to it. Maybe this helps you for your implementation.
For example we got multiple times the same request nearly at the same time. This lead to duplicate entries in our elasticsearch. We added a servlet filter which catches duplicates and returns a 409 CONFLICT status code.
Description for 409 is in example:
Indicates that the request could not be processed because of conflict
in the request, such as an edit conflict in the case of multiple
updates.

Should Internal Server Error be documented in swagger?

I am writing a new API and documenting it using Swagger/OpenAPI. It seems to be a good standard to document error responses, that the developer can expect to encounter.
But I cannot find any guide lines or best practices about Internal Server Error. Every path could in theory throw an unhandled exception. I do not expect it to happen, but it might. Should all paths have a response with status code 500 "Internal Server Error" or should I only document responses the developer can do anything about, i.e. 2xx, 3xx and 4xx?
The offical documentation shows an example for specifying all 5xx status codes in the responses section, but it does not go into details about the specific status code, or the message returned. It also mentions that the API specification should only contain known errors:
Note that an API specification does not necessarily need to cover all possible HTTP response codes, since they may not be known in advance. However, it is expected to cover successful responses and any known errors. By “known errors” we mean, for example, a 404 Not Found response for an operation that returns a resource by ID, or a 400 Bad Request response in case of invalid operation parameters.
You could follow the same approach and specify it like in the example. I think it's not important or even recommended to try to describe it more specifically, since you might not be able to cover all cases anyway and the client is not expected to act on the message returned for internal server errors (possibly other than retrying later). So for example, I would not recommend specifying a message format for it.
Omitting any responses with 5xx HTTP error codes makes sense as well.

What is the proper HTTP response code for request without mandatory fields

Consider simple case where user is deleting a post. This is simple HTTP DELETE/POST request with one mandatory field, post_id.
What should server do if post_id is not provided?
Apparently, user should never encounter this behaviour, so let's be puristic.
My first take would be 400 bad request, but spec says
The request could not be understood by the server due to malformed syntax. The client SHOULD NOT repeat the request without modifications.
and I'd say missing field is OK from syntax/http POV, it's application domain-specific semantic requirement.
200 OK with explanations is bad, 500 feels weird as this is request problem.
Thoughs?
400 is the correct response.
400 is not restricted to a malformed syntax from an HTTP point of view. Missing a mandatory argument is an error in the syntax defined by the application and thus a "Bad Request"
EDIT
At first it seems strange that there is no separate return code for this, but the return codes are designed to differentiate in what actions the client should take. A 400 error code means that the client should change the POST data or query string to the format defined by the application. Hence it is appropriate for this case.
In a REST scenario, the resource to be deleted should be identified by the URL, so the ID of the resource should be a part of that URL in order to properly identify it. Once that assumption is correct, then the URL either is identifying a different resource fr deletion, or it isn't (which would give a 404)
In the general case of a missing parameter, however, I often use a 403 Forbidden error. The reasoning is that the request was understood, but I'm not going to do as asked (because things are wrong). The response entity explains what is wrong, so if the response is an HTML page, the error messages are in the page. If it's a JSON or XML response, the error information is in there.
From rfc2616:
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. If the server does not wish to
make this information available to the client, the status code 404
(Not Found) can be used instead.