REST: Mapping 404 HTTP Status codes - web-services

Our team is developing RESTFul applications...we are debating the "BEST PRACTICE" approach.
Should 404 status code response be returned for a filter-like query? Say my GET URL is
.../1/service/startsWith/a.json
and it returns all values that start with A in my database...but if no "a" values are found should i just return status code 200 with an empty json string? or status code 404.
Thanks!

See this question, in the update to my answer I address your issue.
Specifically this bit,
I think the answer to whether to
return 404 depends on the what is the
resource that is being retrieved. Is
it a representation of a search
result, or is it a representation of a
product? To know this you really need
to look at the link relation that led
us to the URL.
If the URL is supposed to return a
Product representation then a 404
should be returned if the code does
not exist. If the URL returns a search
result then it shouldn't return a 404.
The end result is that what the URL
looks like is not the determining
factor. Having said that, it is
convention that query strings are used
to return search results so it is more
intuitive to use that style of URL
when you don't want to return 404s.

It may be more sensible to return a 204 code, which means 'No Content'. This would be slightly more efficient as a 204 status cannot have any document content, plus you can detect the code instead of having to parse the response.

Related

Jmeter : One request - two or more responses - how to Regular Expression Extractor?

Hello.
I met the following problem.
What I should do:
I need to make a performance test of services. I don't have documentation. In this case, I record the requested services and responses using Jmeter and the browser. Then I review every one sample and add a regular expression extractor - if it's needed.
What's the problem?
The problem that I met is when I run the script from Jmeter, some requests have two or more responses. When I use regular expression extractor or response assertion, I noticed that the extractor or assertion is applied only to the last response. So can I apply the regular expression extractor and response assertion to responses that I need?
Here are some screenshots for more details:
This picture shows that we have two responses from one request and you can see details about the first response.
This picture shows details about the second response.
This picture shows the response code for the first response.
Same as the previous picture, but I added a Response Assertion - to check if the assertion works for the first response.
This picture shows the response code for the second response.
This picture shows the assertion failure.
Why has this has happened?
Probably this happened because I hit an URL (endpoint), and this URL forces other requests, that weren't recorded. So... maybe I need to configure the recorder options in another way.
Whats the questions:
Is there is a way to choose what response I can use with a regular expression extractor? For example, there are two responses and I want to use a regular expression extractor to the first one.
Which are the best settings for recording using Jmeter?
"Whats the answers":
No, you have choice between Main sample and sub-samples, main sample only, sub-samples only or JMeter Variable
The ones which are defined in the Recording Template are most probably the best, at least they're better than anything else I've seen so far. The general approach of "recording" might be a big mistake itself, at least for Web 2.0, I believe there are way better options of replicating browser traffic.
Coming back to your first question and possible solutions: you're basically being redirected that's why you're getting 2 subresults, one with status code 302 and another one with 200
With normal Response Assertion you can only amend its configuration to take both status codes as successful:
If you want to test that exactly the first subresult has status code of 302 - you will have to go for JSR223 Assertion and implement the acceptance criteria in Groovy.
Example code:
if (prev.getSubResults().first().getResponseCode() != '302') {
AssertionResult.setFailure(true)
AssertionResult.setFailureMessage('Response code mismatch, expected: 302, got: ' + prev.getSubResults().first().getResponseCode())
}

Postman - turn off matching algorithm

I'm trying to build a decent mock API using Postman, and I stumbled upon its Matching algorithm.
Is there a way to turn it off, so that, for example, when I target the wrong query params, or simply the wrong URL, it does return a 404?
Currently the response from
my/api/path/endpoint?myParam=Test
is returned even when I submit to
my/api/path/endp
Which I really don't want.
Currently, there is no way to turn off query param matching. If the query params do not match the algorithm falls back to match the path. The path matching is based on a fuzzy string matching algorithm which is why you are getting a response even though you were expecting a 404. One workaround for this is to save another example response for with a response code of 404 for my/api/path/endpoint and then send the x-mock-response-code header key with the value 404. This should return the example you have stored with the 404 status code.

Designing of a WebService API for paths between two points

I have a Web Service which returns details of path between given two input points if exists. The Web Service API is something like getPath(Point start,Point end). Now if the path doesn't exist between given start & end points, how should API behave among below options
Return a null object
Throw a PathNotFoundException
Always include a status code in the response along with path details. In this case return empty path and status code as appropriate error code like "PATH_NOT_FOUND" / "ERROR"
Any other option? Please suggest.
Please let me know your views
Thanks,
Harish
Suggestion: 1. return null or empty path.
Throwing exceptions across http is probably not the best idea and returning status codes is a way to workaround throwing exceptions. The lack of a path is not something that should occur as error at the client side.
I would reserve exceptions/status codes for wrong parameters, wrong number of parameters, some server-side problems like inaccessible database etc.
Suppose you are querying the database for a list of customers from NY. Would you throw an exception if the list is empty or just return an empty list? This sounds exactly like your scenario.

Zero-length URL Segments

Using the latest versions of Flask and Flask-RESTful, I have some very basic routes defined as such:
def build_uri_rules(uri_map):
for cls, uri in uri_map.iteritems():
api.add_resource(cls, uri)
uris = {
SampleController: '/samples/<string:hash_or_id>',
SampleFamilyController: '/samples/<string:hash_or_id>/family',
}
build_uri_rules(uris)
This works for uris requested 'properly', but what if the /samples/ endpoint is hit without a parameter, or the sample*family endpoint is hit with an empty sample id? Currently, this results in a 404 error. This works well enough, but I believe the proper thing here would be to throw a 400 error, as they found a proper URL but their data is improperly structured. Is there a way that I can force this behavior?
As a side note:
Looking through the Werkzeug docs, I see that werkzeug.routing allows a minimum length for certain url parameters, but I also see that it's got a minimum of 1. Admittedly, I've not look for why this is the case, but would this be the right tree to bark up? or should I rather simply create a global 404 handler that checks for the length of the parameter and raise the proper error from there?
Thanks!
EDITED: For code correctness.
I would say that hitting /samples/ or /samples/family (or even /samples//family) should result in a 404 as there is nothing at that endpoint.
If, however, you want to do otherwise, the simplest way to handle it would be create a 404 handler for just /samples/ and /samples/family that returns a note with more information about what the consumers of your API are most likely doing wrong.
uris = {
Explanitory400Controller: '/samples/',
SampleController: '/samples/<string:hash_or_id>',
Explanitory400Controller: '/samples/family',
SampleFamilyController: '/samples/<string:hash_or_id>/family',
}

REST: Mapping application errors to HTTP Status codes

Is it to be considered good practice to reuse RFC HTTP Status codes like this, or should we be making up new ones that map exactly to our specific error reasons?
We're designing a web service API around a couple of legacy applications.
In addition to JSON/XML data structures in the Response Body, we aim to return HTTP Status Codes that make sense to web caches and developers.
But how do you go about mapping different classes of errors onto appropriate HTTP Status codes? Everyone on the team agrees on the following:
GET /package/1234 returns 404 Not Found if 1234 doesn't exist
GET /package/1234/next_checkpoint returns 400 Bad Request if "next_checkpoint" and 1234 are valid to ask for but next_checkpont here doesn't make sense...
and so on... but, in some cases, things needs to be more specific than just "400" - for example:
POST /dispatch/?for_package=1234 returns 412 Precondition Failed if /dispatch and package 1234 both exist, BUT 1234 isn't ready for dispatch just yet.
(Edit: Status codes in HTTP/1.1 and Status codes in WebDAV ext.)
RESTful use of HTTP means that you must keep the API uniform. This means that you cannot add domain specific methods (ala GET_STOCK_QUOTE) but it also means that you cannot add domain specific error codes (ala 499 Product Out Of Stock).
In fact, the HTTP client error codes are a good design check because if you design your resource semantics properly, the HTTP error code meanings will correctly express any errors. If you feel you need additional error codes, your resource design is likely wrong.
Jan
422 Unprocessable Entity is a useful error code for scenarios like this. See this question what http response code for rest service on put method when domain rules invalid for additional information.
GET /package/1234/next_checkpoint
returns 400 Bad Request if
"next_checkpoint" and 1234 are valid
to ask for but next_checkpont here
doesn't make sense...
This is the wrong way to think about that URI.
URIs are opaque, so observing that parts of it are 'valid' and others are not doesn't make any sense from a client perspective. Therefore you should 'just' return a 404 to the client, since the resource "package/1234/next_checkpoint" doesn't exist.
You should use 4xx series responses that best match your request when the client makes a mistake, though be careful to not use ones that are meant for specific headers or conditions. I tend to return a human-readable status message and either a plain-text version of the error as the response body or a structured error message, depending on application context.
Update: Upon further reading of the RFC, "procondition failed" is meant for the conditional headers, such as "if-none-match". I'd give a general 400 message for that instead.
Actually, you shouldn't do this at all. Your use of 404 Not Found is correct, but 400 Bad Request is being used improperly. A 400 Bad Request according to the RFC is used solely when the HTTP protocol is malformed. In your case, the request is syntactically correct, it is just an unexpected argument. You should return a 500 Server Error and then include an error code in your REST result.