Using Accept request header to branch on JSON vs html - rest

Looking at using the http Accept header to branch if the server should return html or json of a resource. I was thinking of just using:
Accept: application/json
But further research and reading the GitHub API, the standard seems to be:
Accept: application/vnd.company.app+json
What is the advantage of doing this? Why not just use application/json without the vendor prefix of company and app?

The major difference is that application/json is a generic definition. Just because a request document is formatted as "application/json" doesn't mean that it could still be consumed by your application.
For the most part, on the server side you'd find yourself registering your media-type as being provided by your generic serialisation/deserialisation library (e.g. Jackson), so there's very little practical difference which it makes - if the provided document is not deserialisable to the the class you're expecting then there'll be an exception which will duly get turned into a 40x response code.
However, it's useful to be sure that both your server and your client expect to be speaking the same language. That can be logged and it can help to locate problems, either from external clients who expect an 'old' version of the API or from internal issues relating to incompatible client-server combinations.

Related

How to enable gzip at GraphQL server?

According to the this article, it's encouraged that any production GraphQL services enable GZIP and encourage their clients to send the header: Accept-Encoding: gzip
I've tested this in Postman, with "Accept-Encoding" enabled or disable, I didn't see any difference in the responded "content-length".
So my question, how to enable GZIP encoding at graphQL server?
Q: How to enable GZIP encoding at graphQL server?
A: Short answer, you can't.
Why? Because GraphQL is just a library for parsing your graph queries and calling the appropriate functions, supplied by you, to build out a graph response.
It is not about compressing your HTTP response and making sure that the response has the Content-Type=Gzip header in it.
In other words, what that piece of document is trying to say is that the GraphQL response looks pretty much like JSON and therefore they work well when compressed. Mainly because raw graph responses can be quite bloated in size and it is inefficient and slow to transfer them across the network.
Just in case your HTTP server for graphql is implemented in NodeJS, you can use the zlib to do the compression. See documentation.
If you are the majority of people who uses theexpress framework for NodeJs then it is even more easier as there is a compression plugin for it already. See here.

RESTapi's and Multilingual representations --- POST, PUT and DELETE

So, it's quite common to use content-negotiation to get a different language representation for the same resource:
GET /resource/12345 HTTP/1.1
Accept-Language: en-GB;q=9.0, fr;q=0.8, *
Accept: application/json
which would give back a representation in British, French or any other language.
{ "greeting": "Bon Jour" }
And i think this is the right way to do it, so far, i am fine with the concept of content-negotiation.
Somehow, somewhere "Bon Jour" must have been entered... now, somehow, using REST, i want to add also the British representation.
Proposal
I was tempted to introduce:
PUT /resource/12345 HTTP/1.1
Content-Language: en-GB
Content-Type: application/json
{ "greeting" : "Good Morning" }
And one could selectively delete on translation with
DELETE /resource/12345 HTTP/1.1
Content-Language: pt_BR # Portuguese Brasil
Or delete the entire resource without specifying Content-Language
However
These ways to work with multilingual versions of a resource are nowhere being described. There is nothing in the RFCs. Also, Content-Language is mostly considered as a response header, although the old RFC did call it an 'entity' header.
Request for Comments
Please feel free to comment on this proposal in using the Content-Language header field to specify in which specific language the HTTP method should be performed. Naturally, a GET does not have a content body and therefore the content language does not need to be specified.
Question
What is common / best practice, where possible avoiding to add the language in the URL?
There have been several approaches at Web authoring and handling different representations of resources, based on Content-Language as well as other content negotiation features.
One approach was Delta-V and its Variant management.
However, this was never well-enough defined to be interoperable, and was dropped from the DeltaV standard.
Another discussion was around having a PATCH body format specifically defined for modifying resource metadata. A bunch of work would have to be done to define the format and how to express how many variants should exist and how to assign content information to representations.
The gist of the repeated discussions AFAICR is that in order to do Web authoring over HTTP and support content variants would require quite a bit of work, and not just defining how to use a header on PUT/DELETE. Authoring clients would need a way to get lists of variants and how they varied.
In contrast, as you've seen with various implementations of Web servers that serve documents out of file systems or databases, implementors have come up with various non-HTTP ways of authoring language variants, some more and some less RESTful in the way browsers GET the language variants. Filesystems aren't typically capable of supporting variants without a lot of superstructure, and content negotiation doesn't seem to be a top feature of Web servers or CMS servers.
You might try searching some of the archives of IETF HTTP-related mailing lists or posting to those lists; that's where people tend to discuss the theoretical and architectural aspects of this, rather than just worrying about local implementation tradeoffs.

Passing array in GET for a REST call

I have a url to fetch appointments for a user like this:
/user/:userId/appointments
How should the url look like if I want to get appointments for multiple users?
should it be:
/appointments?users=1d1,1d2..
Thanks,
Chris.
Collections are a resource so /appointments is fine as the resource.
Collections also typically offer filters via the querystring which is essentially what users=id1,id2... is.
So,
/appointments?users=id1,id2
is fine as a filtered RESTful resource.
Another way of doing that, which can make sense depending on your server architecture/framework of choice, is to repeat the same argument over and over again. Something like this:
/appointments?users=id1&users=id2
In this case I recommend using the parameter name in singular:
/appointments?user=id1&user=id2
This is supported natively by frameworks such as Jersey (for Java). Take a look on this question for more details.
I think it's a better practice to serialize your REST call parameters, usually by JSON-encoding them:
/appointments?users=[id1,id2]
or even:
/appointments?params={users:[id1,id2]}
Then you un-encode them on the server. This is going to give you more flexibility in the long run.
Just make sure to URLEncode the params as well before you send them!
This worked for me.
/users?ids[]=id1&ids[]=id2
/appointments?users=1d1,1d2..
is fine. It's pretty much your only sensible option since you can't pass in a body with a GET.
Instead of using http GET, use http POST. And JSON. Or XML
This is how your request stream to the server would look like.
POST /appointments HTTP/1.0
Content-Type: application/json
Content-Length: (calculated by your utility)
{users: [user:{id:id1}, user:{id:id2}]}
Or in XML,
POST /appointments HTTP/1.0
Content-Type: application/json
Content-Length: (calculated by your utility)
<users><user id='id1'/><user id='id2'/></users>
You could certainly continue using GET as you have proposed, as it is certainly simpler.
/appointments?users=1d1,1d2
Which means you would have to keep your data structures very simple.
However, if/when your data structure gets more complex, http GET and without JSON, your programming and ability to recognise the data gets very difficult.
Therefore,unless you could keep your data structure simple, I urge you adopt a data transfer framework. If your requests are browser based, the industry usual practice is JSON. If your requests are server-server, than XML is the most convenient framework.
JQuery
If your client is a browser and you are not using GWT, you should consider using jquery REST. Google on RESTful services with jQuery.

Splitting hairs with REST: Does a standard JSON REST API violate HATEOAS?

I was doing some reading on REST this morning and I came across the HATEOAS principle ("hypermedia as the engine of application state").
Quoting the REST Wikipedia page:
Clients make state transitions only through actions that are dynamically identified within hypermedia by the server (e.g. by hyperlinks within hypertext). Except for simple fixed entry points to the application, a client does not assume that any particular actions will be available for any particular resources beyond those described in representations previously received from the server.
And Roy Fielding's blog:
...if the engine of application state (and hence the API) is not being driven by hypertext, then it cannot be RESTful and cannot be a REST API. Period.
I read this as: The client may only request state changes based on the actions made available from the body of the response from the server (the hypertext).
In an HTML world, this makes perfect sense. The client should only be able to request state changes (new actions/pages) based on the links made available to them through the hypertext (HTML).
When the resource is represented in other ways - such as JSON, XML, YAML etc. This is not so apparent.
Let's take an example "REST" JSON API:
I create a new resource (a new comment for example) by sending a POST request to
/comments.json? # with params...
The server responds with:
# Headers
HTTP/1.1 201 Created
Location: http://example.com/comments/3
Content-Type: application/json; charset=utf-8
... Etc.
# Body
{"id":3,"name":"Bodacious","body":"An awesome comment","post_id":"1"}
I know that I can now access this comment at the URI returned in the header: http://example.com/comments/3.json
When I visit http://example.com/comments/3.json I see:
{"id":3,"name":"Bodacious","body":"An awesome comment","post_id":"1"}
Suppose the API's documentation tells me that I can delete this comment by sending a DELETE request to the same URI. This is fairly common amongst "REST" APIs.
However:
The response from the server at GET http://example.com/comments/3.json doesn't tell me anything about being able to delete the comment by sending a DELETE request. All it shows me is the resource.
That I can also DELETE a comment with the same URL is something the client knows through out-of-band information (the documentation) and is not discovered and driven by the response from the server.
Here, the client is assuming that the DELETE action (and possible others) are available for this resource and this information has not been previously received from the server.
Have I misunderstood HATEOAS or am I right in saying than an API matching the above description would not, in the strict sense, be a REST API?
I'm aware 100% adherence to REST is not always possible or the most pragmatic way to go. I've posted this question purely to satisfy my own curiosity about the theory behind REST, not for advice on real world best-practice.
Jon Moore gave an excellent talk in Nov 2010 about the nuts and bolts of writing a truly RESTful (i.e. HATEOAS supporting) API and client. In the first part, he suggests the JSON is not a proper media type for REST because it lacks a commonly understood way of representing links and supported HTTP methods. He argues that good ol' XHTML is actually perfect for this since tools for parsing it (i.e. XPath) are readily available, it supports forms (think GET link templating and PUT, POST, and DELETE methods) and has a well-understood way of identifying hyperlinks, plus some other advantages mainly achieved through the ability to use the API with any standard web browser (eases the jobs for devs, QA, and support staff.)
The argument I'd always made prior to watching his talk is that JSON is so much lower of bandwidth consumer than any *ML language e.g. XML, HTML, XHTML. But by using terse XHTML where possible such as relative links instead of absolute ones (hinted at but not so evident in the example he uses throughout his talk), and by using gzip compression, this argument loses a lot of weight.
I realize efforts such as JSON-Schema and other RFC's are underway to try standardizing things in JSON, but in the meantime, Moore's talk convinced me to give XHTML a try.
JSON as a hypermedia type doesn't define an identifier for application flow. HTML has link and form tag that that guide a user through a process.
If your application is only concerned with PUT, POST, DELETE, GET on a resource, your documentation could easily explain that.
However, if it were more complicated like adding a rebuttal to a comment and that rebuttal was a different resource then the comment you would need hypermedia type that would guide the consumer create the rebuttal.
You could use HTML/XHTML, Create your own 'bodacious+json' or use something else. Here are all the different media types
http://www.iana.org/assignments/media-types/index.html
I'm using HAL and it has a pretty active group. Here are links to it.
http://www.iana.org/assignments/media-types/application/vnd.hal+json
http://stateless.co/hal_specification.html
The book "Building Hypermedia APIs with HTML5 and Node" goes deep into hypermedia and media types. It shows how to create a media type for a specific or general purpose in XML or JSON.
A RESTful solution would be to utilise the Allow-header to inform the client of the available methods/actions:
> GET /posts/1/comments/1 HTTP/1.1
> Content-Type: application/json
>
< HTTP/1.1 200 OK
< Allow: HEAD, GET, DELETE
< Content-Type: application/json
<
< {
< "name": "Bodacious",
< "body": "An awesome comment",
< "id": "1",
< "uri": "/posts/1/comments/1"
< }
Fielding's dissertation sets out two types of metadata: representation metadata; and resource metadata.
The Allow-header in HTTP/1.1 functions as resource metadata because it describes some property of a resource; i.e. the methods it allows.
By fully utilising the features provided by HTTP you eliminate the need for any out-of-bound information, and become more RESTful.
HATEOAS in a simple HTTP context describes how a client can navigate from one representation to another by following URIs using GET, whilst the Allow-header informs the client of the additional methods supported by the resource that generated the representation.
It's a neat design; the client asked for a representation, and additionally received a whole bunch of extra metadata about the resource that enables the efficient requesting of further representations.
I think the quote you have from the Wikipedia REST page is somewhat misleading in its choice of words and hasn't helped here (N.B. It has been improved since this question was asked).
All HTTP clients have to assume that a GET-method is likely to be available for the majority of resources. They do this because support for GET and HEAD are the minimum requirements for an HTTP/1.1 server. Without this assumption the web would not function. If a client can assume GET is available, then why not make other assumptions about common methods such as DELETE, or POST?
REST and HTTP aim to leverage the power of making assumptions about a basic set of methods in order to reduce the overall volume of requests on a network; if a request succeeds there's no need for further communication; but if a request fails with status '405 Method Not Allowed', then the client is immediately in receipt of the requests that could succeed via the Allow-header:
> ANNIHILATE /posts/1/comments/1 HTTP/1.1
> Content-Type: application/json
>
< HTTP/1.1 405 Method Not Allowed
< Allow: HEAD, GET, DELETE
< Content-Type: application/json
<
If the basic set of HTTP/1.1 methods aren't enough then you are free to define your own. However, it would be RESTful to solve problems using the available features of HTTP before defining new methods or putting metadata into the message-body.
A fully discoverable JSON API that doesn't require any out-of-band knowledge as you put it so succinctly:
"That I can also DELETE a comment with the same URL is something the client knows through out-of-band information (the documentation) and is not discovered and driven by the response from the server."
...is completely possible. It just requires a simple standard and a client that understands the standard. Check out hm-json and the hm-json Browser project:
https://bitbucket.org/ratfactor/hm-json-browser/
As you can see in the demo, absolutely no out-of-band documentation is needed - only one entry point URI from which all other resources and their HTTP methods can be discovered by browsing.
By the way, HAL as mentioned in suing's answer is very, very close to your hypothetical requirements for HATEOAS. It's a great standard and it has a lot of cool ideas like embedded resources, but it has no way of informing the client about all available HTTP methods such as DELETE for a given resource.
Another solid (and new as of May 2013) attempt at resolving HATEOAS for JSON can be found here:
JSON API: http://jsonapi.org/
The premise of your question contains an often misunderstood aspect of REST – that the API response body entity be responsible for not only communicating the representational state of the requested resource but for also communicating the over-all state of the application the resource belongs to. These two things - resource state and application state are not the same thing.
The response entity body by definition provides you the state of the resource at a point in time. But a single resource is only one of many that comprises an application. Application state is the combined states of all in scope related resources – at any point in time – from the perspective of the application consumer - human or machine. To deliver this 'application state' a level 3 REST API make possible HATEOAS.
Since Hypertext is what most people mean when referring to the 'Hyper'media in HATEOAS, the special power of hypertext is it's ability to link to other media. Further, since most experience hypertext via HTTP/HTML this tends to lead many to think hyperlinks are only possible via an anchor tag or link tag within the body of a response entity - but this is not so.
If the transport protocol is HTTP then application state can and should be communicated via headers. Specifically, one or more 'Link' HEADERS with a 'rel' attribute to provide semantics. The Link HEADER along with the ALLOW header are the HTTP mechanisms for communicating what the next possible state transitions are and how to go about accessing them.
If you decide to not use these built-in mechanisms than your options are to try and communicate the application state by 'piggy-backing' on your resource state communication channel i.e. the response body, which leads to trying to devise some form of additional specification into the design of the resource itself.
When this is done - 'piggy-backing'- many run into content-type issues because the response body has to be specified by a MIME/Content-type like XML or JSON which means figuring out how to implement the HATEOAS mechanisms via some custom content-type specific format like custom XML tags or key:value pairs of nested object. You can do this, many do - e.g. see json-api suggestion above, but again HTTP already provides mechanisms for this.
I think it goes to us as humans always thinking we have to see or be able to click on these links as in the normal web use-case but we are talking about APIs that I can only assume are being built not for human consumption but for machine consumption - right? The fact that headers - which are there by the way as part of the response - are not visible in most human interfaces to HTTP i.e. browsers is not an issue with REST but rather an implementation limitation of the HTTP Agents on the market.
Hope this helps. BTW if you want a good human browser for APIs google 'Paw API Browser'

Using POST as a workaround for the URL character limit

If you have an API and support the POST operation only because of URL length limitations and the passing of complex parameters in the request, can you still say that you have a RESTful architecture?
What the above basically implies is that for this particular (read-only) API, there is no semantic difference between a GET and a POST, so what can be done with a GET can also be done with a POST (but not vice versa due to the limitations).
Would this still make the style of the architecture a RESTful one?
Technically you are not violating any constraints. However you are severely reducing the self-descriptiveness of requests. This will result in the loss of the ability to cache responses. Being able to cache responses is an essential feature that is needed to build effective REST systems.
You will definitely lose functionality HTTP provides for GET requests. Proxies for instance make certain assumptions about GET requests (idempotence, cachability).
There's nothing wrong with POST perse, but maybe the REPORT method is more appropriate.
So the question here is about restful architecture not for restful web services.If we go by the information given on Wiki-RestfulArch-Constraints , Yes it is.
The term Representational State Transfer was introduced and defined in 2000 by Roy Fielding in his doctoral dissertation. Section 6.3 explains how to apply REST to HTTP: http://www.ics.uci.edu/~fielding/pubs/dissertation/evaluation.htm#sec_6_3
Fielding does not claim that the use of POST is forbidden.
Wikipedia also mentions POST as a legal HTTP operation for RESTful web services:
http://en.wikipedia.org/wiki/Representational_State_Transfer#RESTful_web_services
Why don't you simply switch to including a body in the GET instead of using the query string?
Update
The RFC says the following:
A server SHOULD
read and forward a message-body on any request; if the request method
does not include defined semantics for an entity-body, then the
message-body SHOULD be ignored when handling the request
Theres nothing in the specification that says that a body cannot be included in any of the methods. And all proxies, servers etc are obliged to include the body. It's up to the handler (you) to ignore the body or not.
As for the GET method, nothing states that it can not include a body.
This means that you can use a GET body as long as your web server supports it.