Merb Router: how to return a 406 error - router

Is it possible to have the router return an error code (or an entire rack response) in response to a matched route?
E.g. I have move from WordPress to a home grown blogging solution. Search engines are hitting URLs like '/?tag=ruby' that need to return a 406 error. Instead, the router dutifully routes them to the same place as '/' I can match the URLs I want to get rid of but I don't know what to do with them

This is not obvious, but it is effective.
Solution:
match('/',:query_string=>/.+/).defer_to do |request, params|
raise Merb::ControllerExceptions::NotAcceptable,
"Query String Unknown: #{request.query_string}"
end
Explanation:
In order to trigger a 406 error we need to raise Merb::ControllerExceptions::NotAcceptable but if we do this while setting up the routes it helps exactly no one. Instead we need to wait until Merb is handling the request. this is what the defer_to block does. When the request comes in we raise the error and it is caught and handled just as it would be if we through this error from a controller.
Problems
One of the goals of my original question was to avoid having to go through all of the dispatching overhead. Instead this solution is dispatched through the exceptions controller which more computationally expensive then [406,{'content-type'=>'text/plain},['406 Not Acceptable']]

Related

I need simple proxy between 2 rest APIs

My code is working ok for GET/POST/PUT to/from restApi1 and restApi2.
However, my problem I need to implement HEAD/OPTIONS (no body!) and GET uri1
HEAD/OPTIONS could return 204 or 200 depends on a process status. I am getting error "Stream closed". Sounds like Camel want body bytes, but I don't indend to have it. Even I set ExchangePattern.InOnly or optional etc error occur...
What is correct way to see responses and handle requests WITHOUT body, just statuses exchange?
How to see response from restApi2 on Camel rest("/restApi1").head().route().routeId("id1")
.to("direct:restApi2").routeId("/id1").setHeader(Exchange.HTTP_METHOD,constant("HEAD"))
setExchanggePattern(ExchangePattern.OutOptionalIn).recepientList(simple(restApi2));
I figured it out. Need to set '.convertBodyTo(String.class)' even I don't have a body.

Is it correct to return 404 when a REST resource is not found?

Let's say I have a simple (Jersey) REST resource as follows:
#Path("/foos")
public class MyRestlet extends BaseRestlet
{
#GET
#Path("/{fooId}")
#Produces(MediaType.APPLICATION_XML)
public Response getFoo(#PathParam("fooId") final String fooId)
throws IOException, ParseException
{
final Foo foo = fooService.getFoo(fooId);
if (foo != null)
{
return response.status(Response.Status.OK).entity(foo).build();
}
else
{
return Response.status(Response.Status.NOT_FOUND).build();
}
}
}
Based on the code above, is it correct to return a NOT_FOUND status (404), or should I be returning 204, or some other more appropriate code?
A 404 response in this case is pretty typical and easy for API users to consume.
One problem is that it is difficult for a client to tell if they got a 404 due to the particular entity not being found, or due to a structural problem in the URI. In your example, /foos/5 might return 404 because the foo with id=5 does not exist. However, /food/1 would return 404 even if foo with id=1 exists (because foos is misspelled). In other words, 404 means either a badly constructed URI or a reference to a non-existent resource.
Another problem arises when you have a URI that references multiple resources. With a simple 404 response, the client has no idea which of the referenced resources was not found.
Both of these problems can be partially mitigated by returning additional information in the response body to let the caller know exactly what was not found.
Yes, it is pretty common to return 404 for a resource not being found. Just like a web page, when it's not found, you get a 404. It's not just REST, but an HTTP standard.
Every resource should have a URL location. URLs don't need to be static, they can be templated. So it's possible for the actual requested URL to not have a resource. It is the server's duty to break down the URL from the template to look for the resource. If they resource doesn't exist, then it's "Not Found"
Here's from the HTTP 1.1 spec
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. 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.
Here's for 204
204 No Content
The server has fulfilled the request but does not need to return an entity-body, and might want to return updated metainformation. The response MAY include new or updated metainformation in the form of entity-headers, which if present SHOULD be associated with the requested variant.
If the client is a user agent, it SHOULD NOT change its document view from that which caused the request to be sent. This response is primarily intended to allow input for actions to take place without causing a change to the user agent's active document view, although any new or updated metainformation SHOULD be applied to the document currently in the user agent's active view.
The 204 response MUST NOT include a message-body, and thus is always terminated by the first empty line after the header fields.
Normally 204 would be used when a representation has been updated or created and there's no need to send an response body back. In the case of a POST, you could send back just the Location of the newly created resource. Something like
#POST
#Path("/something")
#Consumes(...)
public Response createBuzz(Domain domain, #Context UriInfo uriInfo) {
int domainId = // create domain and get created id
UriBuilder builder = uriInfo.getAbsolutePathBuilder();
builder.path(Integer.toString(domainId)); // concatenate the id.
return Response.created(builder.build()).build();
}
The created(URI) will send back the response with the newly created URI in the Location header.
Adding to the first part. You just need to keep in mind that every request from a client is a request to access a resource, whether it's just to GET it, or update with PUT. And a resource can be anything on the server. If the resource doesn't exist, then a general response would be to tell the client we can't find that resource.
To expand on your example. Let's say FooService accsses the DB. Each row in the database can be considered a resource. And each of those rows (resources) has a unique URL, like foo/db/1 might locate a row with a primary key 1. If the id can't be found, then that resource is "Not Found"
Though this question already have an accepted answer, I believe it's really an opinionated thing. Adding my two cents to help you make a more informed decision about the response code.
404 - Not Found. (Reference)
The origin server did not find a current representation for the target resource or is not willing to disclose that one exists.
The resource may exist and you may not have permission to see the resource, will also be equivalent of Not Found. So 404 for a call where data doesn't exist is a very apt thing to do.
Now as for a non-existing URL; though 404 is a widely adapted response code 400 is a more appropriate code.
400 - Bad Request (Reference)
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).
If you put an invalid parameter in the request, what would be the response code?
If query param has a typo, what should be response code?
Answer to both is 400.
Most of the file-servers, return 404 for invalid URL because for an invalid URL they try to look for a file, which they can't find on the storage ~= Resource Not Found
Apart from the HTTP Status Code, the response will have some info about the error details, where one can be more descriptive about the error and can clear the ambiguity.
If client is calling with an invalid URL, it's an integration issue and should be caught at least during the sanity. No-way they will push the code to production without testing and catching this. Even if they do, God bless them!
tl;dr - 404 for not-found resource; 400 for not-found URL.
A 4XX error code means error from the client side.
As you request a static resource as an image or a html page, returning a 404 response makes sense as :
The HTTP 404 Not Found client error response code indicates that the
server can't find the requested resource. Links which lead to a 404
page are often called broken or dead links, and can be subject to link
rot.
As you provide to clients some REST methods, you rely on the HTTP methods but you should not consider REST services as simple resources.
For clients, an error response in the REST method is often handled close to errors of other processings.
For example, to catch errors during REST invocations or somewhere else, clients could use catchError() of RxJS.
We could write a code (in TypeScript/Angular 2 for the sample code) in this way to delegate the error processing to a function :
return this.http
.get<Foo>("/api/foos")
.pipe(
catchError(this.handleError)
)
.map(foo => {...})
The problem is that any HTTP error (5XX or 4XXX) will terminate in the catchError() callback.
It may really make the REST API responses misleading for clients.
If we do a parallel with programming language, we could consider 5XX/4XX as exception flow.
Generally, we don't throw an exception only because a data is not found, we throw it as a data is not found and that that data would have been found.
For the REST API, we should follow the same logic.
If the entity may not be found, returning OK in the two cases is perfectly fine :
#GET
#Path("/{fooId}")
#Produces(MediaType.APPLICATION_XML)
public Response getFoo(#PathParam("fooId") final String fooId)
throws IOException, ParseException {
final Foo foo = fooService.getFoo(fooId);
if (foo != null){
return Response.status(Response.Status.OK).entity(foo).build();
}
return Response.status(Response.Status.OK).build();
}
The client could so handle the result according to the result is present or missing.
I don't think that returning 204 brings any useful value.
The HTTP 204 documentation states that :
The client doesn't need to go away from its current page.
But requesting a REST resource and more particularly by a GET method doesn't mean that the client is about terminating a workflow (that makes more sense with POST/PUT methods).
The document adds also :
The common use case is to return 204 as a result of a PUT request,
updating a resource, without changing the current content of the page
displayed to the user.
We are really not in this case.
Some specific HTTP codes for classical browsing matche finely with return codes of REST API (201, 202, 401, and so for...) but this is not always the case.
So for these cases, rather than twisting original codes, I would favor to keep them simple by using more general codes : 200, 400.

REST design - An operation with multiple possible non-success payloads

I'm trying to design a REST method for an 'Add person' operation that has a bunch of business rules. There are multiple possible non-success payloads (for the business purposes), requiring defined structure (to allow the consumer to parse the detail).
For 'Add a person', one of the following non-successes could happen:
We believe the system already has person.
Payload: The ID of that person
There are some possible matches.
Payload: A list of possible duplicates, and an override code to submit the record 'for sure'
General validation errors
Payload: Array of 'Error' object. (Standard across the API)
Question - Response object
If they're all to return under a single HTTP error status code, would it be right to have a varied object like:
OverrideCode (for (1))
PersonPossibleMatches [] (also for (1))
PersonDuplicateId (for (2))
ErrorList [] (for (3))
And have the consumer + documentation explain the interpretation?
Question - Response code
Is 400 (Bad Request) the correct (or correct enough) HTTP status code for this? We use it largely for the field validation (also scenario (3) - just wondering if business rule / 'intermediate state' things like this are any different.
Are there a more appropriate codes to spread the 3x scenarios over? And is it ok for the payloads to be different?
Thanks.
There are two aspects you need to consider
HTTP response code.
Error response payload.
Point number 1 is relatively simple. You have 400 error code for bad requests. And 409 for conflicting resources. So far simple.
Now let us consider your scenarios:
We believe the system already has person.
Payload: The ID of that person
Design suggestion: you can send a response like below
Response code: 409
{
"error_code": "resource_exists",
"error_description": "Resource person with ID XXX already exists"
"debug_info": "",
"link" : [
{
"href": "http://host-name/persons/123456",
"rel": "person"
}
]
}
2. There are some possible matches.
Payload: A list of possible duplicates, and an override code to submit the record 'for sure'
Design suggestion:
In this case - you may want to use PUT to override the resource. No need to use special code.
Response Code: 400
{
"error_code": "potential_duplicates",
"error_description": "Potentially the resource is duplicate of one of the following. Please use PUT with the resource ID to update"
"debug_info": "",
"link" : [
{
"href": "http://host-name/persons/234",
"rel": "person"
},
{
"href": "http://host-name/persons/456",
"rel": "person"
},
{
"href": "http://host-name/persons/789",
"rel": "person"
}
]
}
General validation errors
Payload: Array of 'Error' object. (Standard across the API)
Design suggestion: Here you can simply use 400 response code and a meaningful response like the examples above.
This depends in part on how the operation is performed. Since you said the operation has a bunch of business rules, and the system returns a payload with an ID when the person already exists, let's assume the operation is non-idempotent due to unrelated side-effects, performed with a POST to a factory endpoint.
1. We believe the system already has person.
This is a no-brainer. As suggested by others, you should use a 409 Conflict status code, with a body describing the nature of the conflict. In this case, it seems like there's nothing else the user needs to do, and he can move forward to the next step in the workflow. If there's something he can do, it should follow a procedure similar to the next case.
2. There are some possible matches.
Assuming that the clients don't have any key to unambiguously identify a person, which seems to be your case since you're considering possible matches, here you should also use a 409 Conflict status code, with a body describing the nature of the conflict, but with instructions on how to solve it.
Some other answer suggests you to allow an overwrite parameter that could be used any time, other suggests using a PUT, but I disagree with that since there's nothing preventing a client from using the overwrite all the time, or skipping the POST and use the PUT to replace an existent close-match. Also, you may have concurrent clients trying to add or change a person that match each other, or a common existent group, which will lead to an ABA conflict.
The conflict resolution body should return a valid tag for each possible match, and the client should be instructed to resubmit the same request with the If-Match header and the collection of tags. It may be a single tag, as long as it's generated from key data from each member in the collection. This will enforce that the user first must try the request without any override. If there's a conflict the user is forced to specify the exact entities that will be overwritten, and you're protected from inconsistent updates in case someone changes the current state between the first and the second request.
If the tags don't match in the second request, meaning the state was changed by something else between them, you should fail with a 412 Precondition Failed error.
3. General validation errors
This is also a no-brainer. A 400 Bad Request detailing the error, which seems to be standard across your API.
You could use 409 for the duplicate entry - and arguably for the possible duplicate entries with the extra info in the payload.
http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.4.10
A 400 for validation errors would be the expected response.
It is a judgement call at the end of the day and it depends what would be easier for your rest clients and what they are doing.
Here's the design process I use when creating RESTful API responses for error cases:
Design the response payload for the error condition. Regardless of the error code that's used, it is always good practice to return some content within error responses so that clients can learn more about the error and how to avoid it in the future.
If there is an HTTP status code that accurately describes this error already, and it's not already in use for another error case, use that.
If the closest matching error code is already being used for another error case, it's still OK to use that code, but the response payload becomes the place where the different error cases under that code get distinguished from each other. Your documentation should clearly state that inspecting this code wouldn't be enough, and that clients should then also look into the response to see exactly what happened.
If none of the above are applicable, use the closest error code that's appropriate. Just as in #3, the documentation of your response payloads makes this approach possible. If it's an error that the client influenced, make it a 400-range error, probably 400 - Bad Request. If it's the server's fault, then it should be a 500-range error, probably 500 - Internal Server Error.
Please, please, never throw 200 - OK for errors. The world left that nonsense behind in SOAP land, and nobody wants to go back.
Now let's apply that thinking to your error cases:
We believe the system already has that person. As correctly stated in another answer, 409 - Conflict accurately describes that error, so you should just use that. Putting some descriptive error information in the response payload would help new users of your API, even with such a definitive and understandable code.
There are some possible matches. There really isn't an HTTP code that describes this, and it's something that the client could influence, so the closest would be the catch-all code of 400 - Bad Request. Including the list of possible duplicates is an interesting idea, but make sure you don't end up returning enormous responses with huge numbers of possible matches. Also, make sure to also return URIs to those matching resources so that your clients can easily consume them. As for the "override code" suggestion, I wouldn't return that in the payload. Rather, I'd just document a parameter to your "Add a Person" operation that would allow for overrides to occur at any time, not just after a failed first attempt. For example: POST /people?overwrite=true.
General validation errors This is definitely a job for 400 - Bad Request, along with a descriptive error payload. It sounds like you're already allowing an array of errors to be returned from any API call, so that should be good enough to capture all the validation failures for the client-supplied data.
How about explaining it with a payload back; That is how we deal with REST responses for clients.
Response HTTP 409 with following payload response indicating to client what should they do next
`
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<request-result>
<http-code>200</http-code>
<description>REST Request is successfully processed</description>
<internal-error-info>Person already Exists</internal-error-info>
<message>Person with <id> already exists in sytem. Try picking different ID/Name combination</message>
<requested-operation>Add a Person</requested-operation>
<resource-name>Person</resource-name>
<status>SUCCESSFUL</status>
</request-result>
`

Picking HTTP status codes for errors from REST-ful services

When a client invokes my REST-ful service, it needs to know if the response came back was 'from me' or rather a diagnosis from the containing web server that something awful happened.
One theory is that, if my code is called, it should always return an HTTP OK(=200), and any errors I've got to return should be just represented in the data I return. After all, it's my code that gets the response, not the naked browser.
Somewhat self-evidently, if I'm using REST to generate HTML read directly by a browser, I absolutely must return an error code if there's an error. In the case I care about, it's always Javascript or Java that is interpreting the entrails of the response.
Another possibility is that there is some family of HTTP status codes that I could return with a high confidence that it/they would never be generated by a problem in the surrounding container. Is this the case?
I use the following:
GET
200 OK
400 Bad Request (when input criteria not correct)
POST
202 Accepted (returned by authorization method)
401 Unauthorized (also returned by authorization)
201 Created (when creating a new resource; I also set the location header)
400 Bad Request (when data for creating new entity is invalid or transaction rollback)
PUT
Same as POST
201 Ok
400 Bad Request
DELETE
200 OK
404 Not Found (same as GET)
I would not know how to avoid that some container returns codes like 404.
4xx codes are meant to handle client errors along with possibly some entity that describes the problem in detail (and thus would mean a combination of both of your mentioned approaches). Since REST relies on HTTP and the according semantics of status as well as methods, always returning 200 in any possible case is a violation of this principle in my opinion.
If you for instance have a request such as http://foo.com/bar/123 which represents a bar ressource with id=123 and you return 200 with some content, the client has no chance to figure out if this was the intended response or some sort of error that occured. Therefore one should try to map error conditions to status codes as discussed in REST: Mapping application errors to HTTP Status codes for example.

Proper way to convey error messages during calls to a REST service?

I'm writing a REST based web service, and I'm trying to figure out the best way to handle error conditions.
Currently the service is returning HTTP Errors, such as Bad Request, but how can I return extra information to give developers using the web service an idea what they're doing wrong?
For example: creating a user with a null username returns an error of Bad Request. How can I add that the error was caused by a null username parameter?
According to the HTTP spec, the text that comes after the three digit response code, the "Reason-Phrase", can only be replaced with a logical equivalent. So you can't respond with 400 null user and expect anything useful to happen. Indeed, The client is not required to examine or display the Reason- Phrase.
In general, the HTTP response entity (typically the page that accompanies the response) should contain information useful to the client to guide them forward, even when the response is an error. On the web, most such errors are HTML, and are devoid of machine readable information, but most browsers do show the error to the user (and SO's error page is pretty good!).
So for a primarily machine readable resource you have two options:
Pass a human readable message anyway. Return 400 Bad Request with a HTML response, which the client may opt to show to the user. It's dead easy but it's a bit like throwing an unchecked exception, it passes all the hard work to the client, or indeed the end user.
Allow clients to recover. Return 400 Bad Request with a machine readable response which is part of your API, so clients can recover from known error conditions. This is harder, like throwing a checked exception, it becomes part of the API, and it allows clients to recover gracefully if they want to.
You could even make the server support both scenarios by defining a media type for the machie readable error recovery document, and allow clients to "accept" them: Accept: application/atom+xml, application/my.proprietary.errors+json
Clients that forget the mandatory field can opt in to getting machine readable errors or human readable errors by choosing to Accepting the error media type.
It's stated in the HTTP spec that most error codes should return some basic text that gives a clarification of why the error is being returned. The basic Java Servlet Spec defines the HttpServletResponse.sendError(int Code, String message) for this purpose.
String desc = "my Description";
throw new WebApplicationException(Response.status(Status.BAD_REQUEST).entity(desc).type("text/plain").build());