For example, when you perform an call from summary api of wikipedia, there is this header in the request
accept:application/json; charset=utf-8; profile="https://www.mediawiki.org/wiki/Specs/Summary/1.3.7"
What is the purpose of this particular bit. I would like to understand since the value changes when you, for example, use the VisualEditor or access the api with different mean.
profile="https://www.mediawiki.org/wiki/Specs/Summary/1.3.7"
This specifies the response format and provides convenient access to a human-readable documentation.
The URL in your header leads to nowhere, but https://www.mediawiki.org/wiki/Specs/Summary/1.3.0 does exist and is probably valid for 1.3.7 as well.
Related
I have been working on designing an API that lets client create a product (think of product as something like website domain, something that comes into existence when client makes order for it to the service). Correspondingly with every purchase results in creation of the order object. Which means creation of two resources via a single POST request.
So afaik, the RFC standards recommends sending 201 on resource creation with URI for the resource in the Location header. But in the above scenario, we are creating two resources, domains and orders and I would want response to contain information related to both the resources.
Response would look something similar to this
POST /domains/
Request
body: {"domain_name": "awesome.com"},
Response
Body: {"order_id": "1234"}
Headers:
Location: http://example.com/awesome.com
But does not look very RESTful. I was wondering if there was a RESTful way to do this?
RFC 7231, section 6.3.2
The 201 (Created) status code indicates that the request has been fulfilled and has resulted in one or more new resources being created. The primary resource created by the request is identified by either a Location header field in the response or, if no Location field is received, by the effective request URI.
The 201 response payload typically describes and links to the resource(s) created.
In other words, on the web we would solve your riddle by returning an HTML document that includes hyperlinks to all of the created resources, along with text to describe each, so that the client would know which new identifiers are available.
To make such a response machine readable, we would do the work of documenting the schema of the message, so that specialized clients would know how to identify the semantics of each of the provided links.
The same idea works if you replace HTML with a different media type (for example application/json). You define the schema, and then specialized clients can parse the response to find the identifiers that they need.
Of course, REST is largely about standardizing things so that we can use general purpose components; application/json is somewhat inadequate here, as it doesn't include a URI type (just strings, which are too general). So to be more "RESTful", you would choose one of the specialized JSON types that has a general purpose representation of a link.
Sookocheff's article On Choosing a Hypermedia Type.... is a decent starting point for the kinds of questions you will want to be considering.
I still don't understand how the client knows what data to POST when creating a resource. Most tutorials/articles omit this and in their examples, a client always seems to know a priori what to post (i.e. using out-of-band information). Like in this example, the consumer knows that he has to place the order by setting what <drink\> he wants.
I can only image a few approaches and I don't know if they are valid:
1. Returning an empty resource
The client discovers a link to /resource with a link to /resource/create and relation "create". A GET to /resource/create returns an empty resource (all attributes are empty) and a link to /resource/create with relation "post". The client then sets values to all attributes and POSTs this to /resource/create which returns a 201 (Created). This means that the CRUD operations are not located at the resource endpoint but to URI like /resource/create and that the client might set attributes the server ignores (like a creation date which is set on the server side)
2. Returning a form
Basically the same approach as above, despite the fact that not a resource is returned but some meta-information about what fields to post and what datatypes each attributes needs to have. Like in this example. Still, the creation endpoint is not located at /resource but on /resource/create
3. Creating by updating
A POST to /resource immediatly creates an empty resource and returns a link to this resource. The client then can follow this link to update the resource with the necessary data doing PUTs.
So what is the best approach that still follows the HATEOAs paradigm and why are all of these tutorials (and even books like REST in Practice) omitting this problem?
UPDATE:
I recently found out the Sun Cloud API seems to be pretty close to an "ideal" REST HATEOAS API. It not only defines some resources and does hyperlinking between them, it also defines media types and versioning. With all this theoretical discussion, it's pretty good to have a concrete exmaple. Maybe this helps some readers of this question.
Most tutorials and books about REST are very misleading, because there are many misconceptions about REST and no authoritative source other than Fielding's dissertation itself, which is incomplete.
REST is not CRUD. A POST is not a synonym to CREATE. POST is the method to be used for any action that isn't already standardized by HTTP. If it's not standardized by HTTP, its semantics are determined by the target resource itself, and the exact behavior has to be documented by the resource media-type.
With HATEOAS, a client should not rely on out-of-band information for driving the interaction. The documentation should focus on the media-types, not on the URIs and methods. People rarely get this right because they don't use media-types properly, and instead document URI endpoints.
For instance, in your example, everything has the application/xml media-type. That's the problem. Without proper media-types, there's no way to document resource-specific semantics when everything has the same media-type without relying on URI semantics, which would break HATEOAS. Instead, a drink should have a media-type like application/vnd.mycompany.drink.v1+xml, and your API documentation for that media-type can describe what to expect when using POST with a rel link.
I have a number of services that require an X-Auth-Token header to be sent similar to the below:
X-Auth-Token: 2e5db4a3-c80f-4cfe-ad35-7e781928f7a2
I would like to be able to specify this in my API documentation following the API Blueprint standard. However, from what I can tell from the API Blueprint headers section definition, you can only specify literal values (e.g. Accept-Charset: utf-8) and not a schema for what the header should look like (e.g. something like X-Auth-Token (string)).
I get the impression that Traits might help with this problem but it's a little over my head at the moment. Can anyone tell me how to specify that all requests to a given action (or set of actions) require an X-Auth-Token header?
You are right about not being able to define a schema for headers. Unfortunately, API Blueprint doesn't support it yet.
Until something like that is supported, you can use the literal value for the header like the following:
+ Headers
X-Auth-Token: 2e5db4a3-c80f-4cfe-ad35-7e781928f7a2
API Blueprint also does not support any Traits currently. I am afraid you might have been confused by reading other feature requests.
I'm designing a list endpoint for a resource that merits both full and light version of the resource called /transactions. By default, the response will include the complete resource, but there is also a need to provide clients with the "simplified" version of the resource list.
The first option is to use a custom param (e.g. /transactions?summary=true)
The second option is to use a custom endpoint, though not very RESTful (e.g. /transactions/summary)
The third option is to use content-type to allow a client to declare the alternative response body format. How would this look? (application/json+summary)? Are there any good examples of this being done?
Any other options come to mind?
The third option of using the Accept/Content-Type headers allows the media types to be a representation of a data, separate from the data itself.
A good example of this is github's API: https://developer.github.com/v3/media/
Which uses the http headers to allow clients to choose the format of the data, as well as the version. So in your case, the request could look something like:
curl http://api.host.com/transactions -H "Accept: application/summary+json"
And the response would contain a body of your simplified data format and the Content-Type header set to application/summary+json
If you want to be more pedantic about it, you could also use a vendor media type as application/vnd.yourcompany.summary+json. In this case, vnd implies that the media type is a vendor typically associated with application specific media types.
More Info:
Collection+JSON
A similar answer
A bit from restful API design
Is it a bad practice when writing a RESTful API to use custom HTTP response codes like:
417 - Password not provided
418 - Database error
I see there is a list of standard HTTP response codes. However, from looking at Twitter's API, it appears Twitter tries to return standard HTTP response codes when available but their own error codes when they cannot align the error with a standard HTTP response (correct me if I am wrong).
What is the best practice for response codes (especially for errors) while creating a RESTful API? Any comments on the practice which Twitter chose to use?
Yes, yes it is bad practice... mostly.
One of the tenets of REST is that you work with the underlying protocols, as such HTTP has already defined a good set of response codes.
However, not every situation is catered for perfectly. Take Twitters 'arrest your calm', that response code is used when the request was valid, it simply is not being handled due to too many request being made.
I don't see another response code that quite matches that. The other two options are to either lie, and tell the user the request failed for some other response or give a generic 400 'you did something bad' (then in the body give a more detailed explanation).
I would favour using the generic X00 codes, and use headers or the body to add more detail about what actually went wrong. This at least conforms better to standards and less brittle.
Note though, it is terrible to take an existing error code, and repurpose it. 404 should always be used only for 'not found' errors. Don't start using it because the user can't make that request at this time of day.
The problems in using your own codes are:
The code you choose may get officially assigned to something completely different, and that could break your API in the future. (e.g. compare a 306 with a 301)
Intermediaries don't know what your code means, so cannot optimise anything. The internet works so well because it is a distributed system, not an end-to-end system.
There are generic responses for each category, x00, which should be used if nothing better exists.
You can send your own more specific error code in either the response body or (not as good) a response header. There should be no need to make up your own codes. If you have truly found something that would benefit the rest of the internet and no-one else has thought of until now, you can always submit an Internet Draft to the IETF (this is fairly easy to do).
I would not hold up Twitter as a shining example of good internet practice, though. :)