There are many ways to handle errors in RESTful api:s. Simplifying a solution is sometimes a need becase of system requirements and domain policys.
Stack Overflow is doing a simplification with their own api using the http status code 400 for all errors (https://api.stackexchange.com/docs/errors) and then embedding their own error codes in the respons.
This is a solution that does follow the REST pattern but probably have other advantages. One advantage I can think of is that error codes within the response can be more system specific than using only errors available in the http protocol. Is there any more advantages of using the Stackoverflow pattern for handling REST errors?
I think that you must leverage the HTTP status codes to notify the REST client what happens (if processing is successful, if an error occurs) but this corresponds to high-level hints.
You generally need to associate an error payload that provides a thinnest description(s) of the error(s) and something structured so programmatic REST client can understand and handle them. You are free to choose the structure of such payload.
Here are what I commonly use (described using the JSON format but it's not linked to a particular format):
{
errors: [
{
"message": "my message",
"code": "ERR12",
},
{
"message": "my message",
"code": "ERR13",
"field": "fieldName"
}
]
}
Some errors can be general but also linked to a particular field of the request representation.
Moreover I think that we can leverage than other 4xx codes since the code 400 is a bit general. Here are some than could be used:
400: a general error telling the request isn't correct
405: if you try to use an HTTP method that isn't supported by the resource
409: error with optimistic locking
412: if the preconditions fail before executing the processing of the resource method
415: if the format of the provided representation isn't correct or the requested media type isn't supported
422: error when validating the input representation. Whereas it comes from WebDAV, you could use it (see for example the Github API).
You can notice that some of these methods (405, 415) are natively supported by REST frameworks (for example Restlet).
In the context of Restlet, the error management can be done like described in this answer: JSON Representation of a HTTP 400 for Restlet Client. This can give you some hints for your implementation even without this framework.
Hope it helps,
Thierry
Related
I'm wondering about good practices about including common error types in Swagger/OpenAPI definition.
Let's consider following controller method:
[HttpGet]
[ProducesResponseType(StatusCodes.Status400BadRequest)] // to be or not to be?
public ActionResult SomeMethod(Foo foo)
{
if (foo.Property != "expectedValue")
{
return BadRequest();
}
return Ok();
}
So, I'm performing some logic in the controller, which might end up in a state in which I want to return 400 BadRequest. Note, that I don't return any content.
Since I develop a REST API that generates Swagger/OpenAPI definition and tools like autorest may be used to generate client code based on that definition, I want to be sure it is as accurate as possible.
My question is:
should I declare explicitly that the user might get 400 Bad Request
OR
this makes sense only in case I want to describe the format of response content (in case 400Bad request has some content)
The same applies to codes like 401, 404 etc.
Even if (in addition to the returned http code, 400, 401, etc..) you do not return any payload at all, you should yet explicitly declare such responses.
Do not forget that in a "code-first" approach, your build chain could automatically generate the OpenApi contract (based on your code) as well as a nice user documentation.
In the contrary approach (contract-first), the code generated based on your OpenApi file would contain these response descriptions.
If you plan to use client code generation, then it's always better to use these declarations, because code generators (like autorest or NSwag) can use this information (usually from a swagger definition aka swagger.json) to generate more correct responses and error handling procedures.
Here, for example, you can see what can happen if you omit such declarations.
Also, remember, that in API controllers you can use web API conventions.
It says that these conventions allow you to:
Define the most common return types and status codes returned from a specific type of action.
Identify actions that deviate from the defined standard.
So, generally speaking, they can help you to make your code more concise.
The object BadRequest is used as a response (Result) with StatusCode=400.
DotNet has several response types with predefined StatusCode, so you can use different methods, for example:
NotFound(404):https://learn.microsoft.com/en-us/dotnet/api/system.web.http.apicontroller.notfound?view=aspnetcore-2.2
InternalServerError(500):https://learn.microsoft.com/en-us/dotnet/api/system.web.http.apicontroller.internalservererror?view=aspnetcore-2.2
Or simply use StatusCode for any other code that is not predefined:https://learn.microsoft.com/en-us/dotnet/api/system.web.http.apicontroller.statuscode?view=aspnetcore-2.2
As of Retrofit2 2.3.0 there seems to be no built in functionality to execute a JSON Patch Request (as defined in RFC 6902. Also, see http://jsonpatch.com/ for some examples).
Using the available #PATCH annotation, the full blown object is sent with the request (as if I would send a PUT request, which is not what I'm looking for)
public interface MyService {
#PATCH("example/{id}")
Call<Example> patchExample(#Path("id") String id, #Body Example example);
}
After a first glance at the Retrofit documentation, there seems to be no clean and easy way to introduce a custom annotation (e.g. #JSONPATCH) to have my own implementation working.
The only related information I was able to find regarding this requirement was this experimental (as he calls it himself --> this is very experimental but it does the job currently) approach at https://medium.com/#andretietz/custom-annotations-with-retrofit-2-8701ca7ce102. I didn't give this example a try, but the complexity seems a little bit out of scale for this simple requirement.
Maybe I'm missing something and there is an easy solution for this?
I'm designing a RESTful api for a large collection of reporting data, I would like to pass a complex set of parameters like in the codeblock below. I'm debating between using POST and GET for this endpoint. Team member seem to favor GET but I am not sure the best way of passing this amount of data as GET parameters, best idea so far is to have one GET parameters called something like jsonparams that would have all of the below json encoded
{
"filters":
[
{
"field": "metric-name",
"gt": (float/int),
"lt": (float/int)
},
{
"field": "metric-name-2",
"gt": (float/int),
"lt": (float/int)
}
],
"sort":
[
{
"field": "metic-name",
"order": "ASC"/"DESC"
},
{
"field": "metic-name-2",
"order": "ASC"/"DESC"
}
]
"limit": 100,
"offset": 0
}
POST is the method to use for any operation that isn't standardized by HTTP. Retrieval is standardized by the GET method, so using POST to retrieve information that corresponds to a potential resource is never RESTful. In theory, you should use GET, regardless of how convoluted your URI turns out to be.
However, since you're performing a query for which there isn't a single resource you could perform a GET to, it seems fine to use POST, as long as you're aware of the disadvantages and your documentation is clear about it. Frankly, I think using a POST is much clearer than encoding that payload as a JSON + base64 and sending it as a querystring merely for purism.
The real issue with using POST is when people use it in such a way that it avoids or prevents using a real URI. That doesn't seem to be the issue in your case, since you have a valid URI for the collection, but the semantics of your query are too complex to be expressed easily.
If you decide to go with GET, there's a catch. While the HTTP specs establish no limit for URIs, most implementations do, and you might hit that limit if you need to feed all those parameters as a querystring. In that case, it's RESTful to circumvent limitations of the underlying implementation, as long as that's decoupled from your application. A convention for doing what you want would be to use the POST method with the payload you described above, and the X-HTTP-Method-Override: GET header.
If you're adding the data to a resource or creating a resource use POST. GET is to get a already existing resource, not change the state of the resources.
Update: While POST request are fine to update a resource, if the action is idempotent (meaning will not result in creating new resource and every time you issue the request with the same parameters and data you can guarantee to the same resulting resource), then it's recommended to use a PUT. If it's not idempotent, but you're not replacing the entire resource, use PATCH if only updating part of the resource.
If the argument to go with a crazy serialized GET parameter based request for some kind of percived simplicity, you're not going to be adhearing to REST.
Now, if you're retrieving resources only (no creation), use GET. While I prefer human typable parameters, it's not required. If your situation is 100% retrieval you could encode the entire set into into a giant encoded param string, but I'd suggest at least splitting it out a bit for improved sanity by doing something like:
/resource?filters=urlencoded_filter_array&sort=urlencoded_sort_array&offset=0&count=100
Or you could go more explicit like:
/resource?filter1=urlencoded_filter_json&filter2=urlencoded_filter_json .... sort2=urlencoded_sort_json&offset=0&count=100
or finally (my favorite) a completely explicit broken out set of params
/resource?filter1_field=bah&filter1_gt=1.0&filter1_lt<2&filter2_field=boo&filter2_lt...
I like the final one because there's no encodeing/decoding of json and then url encoding the entire json string. This format is easy to decipher in access logs and trouble shoot. It's also very cacheable, even if the parameter order gets changed, some proxy caches can still work with this, whereas encoding some of the filters in a json object if they get moved around they look like entirely different values as far as proxies would be concerned. For me it's the most REST friendly (if that makes any sense), even though the first 2 examples are fine REST GET requests.
The added work to parse the parameter name isn't really that much fuss. A simple method could convert your json into the parameter string and another simple one could re-hydrate the json object from the explict filter1_xyz format.
The ZF implementation of the JSON-RPC 2.0 protocol only allows error codes:
const ERROR_PARSE = -32768;
const ERROR_INVALID_REQUEST = -32600;
const ERROR_INVALID_METHOD = -32601;
const ERROR_INVALID_PARAMS = -32602;
const ERROR_INTERNAL = -32603;
const ERROR_OTHER = -32000;
plus, range(-32099, -32000)
These are defined in the JSON-RPC spec as pre-defined and/or reserved. At least this is what get out of the spec:
The error codes from and including -32768 to -32000 are reserved for pre-defined errors. Any code within this range, but not defined explicitly below is reserved for future use. The error codes are nearly the same as those suggested for XML-RPC at the following url: http://xmlrpc-epi.sourceforge.net/specs/rfc.fault_codes.php
code message meaning
-32700 Parse error Invalid JSON was received by the server.
An error occurred on the server while parsing the JSON text.
-32600 Invalid Request The JSON sent is not a valid Request object.
-32601 Method not found The method does not exist / is not available.
-32602 Invalid params Invalid method parameter(s).
-32603 Internal error Internal JSON-RPC error.
-32000 to -32099 Server error Reserved for implementation-defined server-errors.
The remainder of the space is available for application defined errors.
Nowhere does it say that you cannot, for example use -100 or 100. Am I missing something?
Somewhere I think that "server error" and "application error" have been confused by ZF as the same thing, while when reading the sourcefourge link above, clearly the authors of the protocol had something different in mind, allowing the application developers A LOT of space:
In addition, the range -32099 .. -32000, inclusive is reserved for implementation defined server errors. Server errors which do not cleanly map to a specific error defined by this spec should be assigned to a number in this range. This leaves the remainder of the space available for application defined errors.
I use the JSON-RPC component of ZF for a few projects. It works pretty well - but I would hardly consider it an exemplar of the JSON-RPC spec. As far as I know, only a couple clients out there actually test their implementations against Zend_Json_Server, so it's hardly a widely adopted implementation. At one point, I actually had to patch Zend_Json_Server to make it work with one client, as it was not following the spec properly (that's since been fixed).
So basically what I'm saying is "good point, you're probably right." If it itches enough, just fork zf2 and submit a pull request with a better implementation of the spec - much easier to get positive / negative feedback when you're looking at a diff.
If they accept it, submit a patch for zf1 to merge in downstream.
Im developeing a RESTful Service in which Processes can be executed and proivde a resulting calculation. For this i have modeled the process itself as a Resource (Example: /processes/translate). I want to execute the process by sending a GET request with appended Input Parameter as Query Parameter (Example: /processes/translate?input1=xxxx&input2=xxxxx).
Each process has different Input Parameter which are defined during the process creation in the backend. My Question is how should i document or describe which inputs are needed to execute a process in machine readable form. For Example in XML.
Until now ive integrated atom:link elements in the Representation. i thought that maybe including XFORM could be a soluttion?
Best Regards
Andre
I would not model this with a GET. While it's the easier solution, it's also (IMO) the least RESTful. I would have clients POST a document describing what they want you to translate and your service sends them back a URI where their answer can be found (some translations might take a while).
Example (ommiting a lot of HTTP headers/context)
POST /processes/translate
Content-Type: application/xml
...
<translation-request>
<input1 type="type1">....</input1>
<input2 type="type5">....</input2>
</translation-request>
Response:
200 OK
Content-Location: /processes/translate/jobs/1234
....
That's always an interesting question. We have a project called RESTx (http://restx.org), with which you can create RESTful web services very easily. You can write custom component code in either Java or Python and then create RESTful resources by sending parameter sets to the server, which are then stored. Each parameter set gets its own URI, though, so you can always just run the code with those parameters by accessing the new parameter set's URI.
Importantly, the entire RESTful API, is automatically created. RESTx examines the component code and then assembles the API description. We decided to describe parameters in a way that is human as well as machine readable. You can see examples of what that looks like in a browser or in plain JSON.
I'm the lead developer on that, so please feel free to contact me about any questions you might have.