The Sun Cloud API at http://kenai.com/projects/suncloudapis/pages/Home is a good example to follow for a RESTful API. True to RESTful principles, when you GET a resource you get no more nor less than a representation of that resource.
The Content-Type header in the response tells you exactly what the type of that resource is, for example application/vnd.com.sun.cloud.Snapshot+json. Sun has registered these mimetypes with the IANA.
How practical is this in general currently? Most API's I have seen have used the Content-Type of "application/json". This tells you that the response is JSON but nothing more about it. You have to have something in the JSON object, like a "type" property, to know what it is.
I'm designing a RESTful API (which will not be made public, therefore I wouldn't be registering mimetypes). I have been using RESTEasy and I find that even if I specify a complete mimetype, the Content-Type in the response header will be exactly what the Accept request header specified. If the request asks for "application/*+json" by default the response header will have "application/*+json". I can probably fix this by changing the header before the response goes out, but should I try to do that? Or should the response have a wildcard just like the request did?
Or should I just serve up "application/json" like most APIs seem to do?
Additional thoughts added later:
Another way of stating the question is: Should I use HTTP as the protocol, or should I use HTTP only as a transport mechanism to wrap my own protocol?
To use HTTP as the protocol, the entity body of the response contains the representation of the object requested (or the representation of an error message object), the "Content-Type" header contains the exact type of the object, and the "Status" header contains a success or error code.
To use HTTP as merely a transport mechanism, the "Status" header is always set to 200 OK, the "Content-Type" is something generic like "application/json", and the entity body contains something that itself has an object, an object type, an error code and whatever else you want. If your own protocol is RESTful, then the whole scheme is RESTful. (HTTP is a RESTful protocol but not the only possible one.)
Your own protocol will be opaque to all the transport layers. If you use HTTP as the protocol, all the transport layers will understand it and may do things you don't want; for instance a browser will intercept a "401 Unauthorized" response and put up a login dialog, even if you want to handle it yourself.
I use my own vnd.mycompany.mymediatype+xml media types for many of my representations. On the client I dispatch to the appropriate controller class based on the media type of the returned representation. This really allows the server to control the behavior of my client application in response to the user following a link.
Personally, I believe that using application/xml and application/json are one of the worst choices you can make if you hoping to support REST clients. The only exception to this is when the client only uses downloaded code (like Javascript) to interpret the data.
Or should I just serve up "application/json" like most APIs seem to do?
I don't think so.
A media type is the only point of coupling between your RESTful web application and the clients that use it. The documentation of your media types is the documentation of your API. Your media types are the contract between your clients and your application. Eliminate the specific media type and you eliminate an important element that makes REST workable.
Sun has registered these mimetypes with the IANA.
Couldn't find any mention of that here. AFAIK, there is no requirement to actually register your custom media type with the IANA. The convention seems to be to use the inverted domain notation of application/vnd.com.example.app.foo+json, which prevents namespace conflicts. If and when your media type becomes stable and public, it might be a good idea, but there's no requirement. Could be wrong on this, though.
Will you get any value by specifying a complete mimetype? Would you do anything with the complete mimetype different than you would if the mimetype was application/json?
My 2 cents- If the API is not going to be made public, then I see no reason for a complete mimetype. A mimetype of application/json should be more than enough. You already know the type of json that the response is returning. If the API eventually becomes public, then worry about a complete mimetype... or just let people figure it out.
Related
I've set up an API in Spring where the client can specify the ids of the objects they want to receive. It returns a JSON list (using the #ResponseBody annotation) of the objects.
But, since the request can be a long list, I've set it up as a POST, where it's received as an object named ProductRequest (using the #RequestBody annotation). This seemingly isn't conformant to the official REST API standard, since posts are official to create new objects, but it seems better to implement it this way since you're not cluttering up the URL with a bunch of ids. Also, I can specify additional parameters customizing the output.
So my question is, can this be considered a valid RESTful design? Post isn't being used to create an object, so it's not strictly conformant to restful. Thoughts?
It is a simple GET request.
#GetMapping(path = "/your-url")
public List<Object> method(#RequestParam(name="ids") List<Long> objectIds) {
}
You can receive your list just as a simple java list.
/api?ids=1,2,3
You can very well do an http POST to "get" the resource(s). There are some very valid examples of doing so,
GraphQL -- All we are doing is sending (POSTing) some Queries in requestbody to "GET" some data in the format that we prefer
Assume that you have to authenticate with a username and password to get a specific data, you will either send it in Header in GET request or you will do a POST to 'GET' a data.
Couldn't that overflow the max allowable for the URL string?
Actually, there is no limitation on the length of a URI. However, practically, you can encounter some.
According to RFC7230 (emphasis mine),
HTTP does not place a predefined limit on the length of a request-line, as described in Section 2.5. A server that receives a method longer than any that it implements SHOULD respond with a 501 (Not Implemented) status code. A server that receives a request-target longer than any URI it wishes to parse MUST respond with a 414 (URI Too Long) status code.
Various ad-hoc limitations on request-line length are found in practice. It is RECOMMENDED that all HTTP senders and recipients support, at a minimum, request-line lengths of 8000 octets.
It clearly suggests that we can't rely on a request-line while we are dealing with your issue.
Can this be considered a valid RESTful design?
Due to the limitation mentioned above, using POST is a valid workaround.
As stated by this Wikipedia article,
The common workaround for these problems is to use POST instead of GET and store the parameters in the request body. The length limits on request bodies are typically much higher than those on URL length.
To completely free you from hesitation, there is a common non-standard header X-Http-Method-Override. It requests a web application to override the method specified in the request with the method given in the header:
X-Http-Method-Override: GET
I am not sure whether Spring handles the header. Though, it has the HiddenHttpMethodFilter filter which seems to do similar work.
I'm building a web service that use JSON everywhere.
Now I need an HTTP method to retrieve properties of a resource (e.g. attribute like read-only, write, ACL, on so on). It looks like there is only one HTTP method for this purpose: PROPFIND.
However the spec clearly instructs to use XML.
Is that insane to use that verb with a JSON interface anyway?
I'm also concerned that PROPFIND is part of the WebDAV extension.
If that's a no-go, what is the recommended verb or the recommended way to retrieve properties for a resource in a JSON-oriented web service?
In a "representational state transfer" architecture, the idea is:
to use a very limited set of input/output verbs whose formal properties can be universally defined (e.g. GET and HEAD are safe, PUT and DELETE are idempotent),
to circumvent this small number of verbs with an unlimited number of resources.
Therefore using other verbs than those that are defined in HTTP is a bad idea. As a matter of fact, every WebDAV verb could have been done with HTTP verbs (and the appropriate headers and resources).
In a RESTful world, you have several options:
to define a new kind of resource for metadata,
to mix data and metadata in the representation of the same resource,
to manage metadata as HTTP headers (note that you can use the HEAD verb if you need to get metadata without the data).
REST is protocol independent but it's frequently implemented over the HTTP protocol. WebDAV is an extension of the HTTP protocol. So, in theory you could use WebDAV methods too (it doesn't mean you should).
From the chapter 6 of Fielding's dissertation:
6.3.1.2 Extensible Protocol Elements
[...] HTTP request semantics are signified by the request method name. Method extension is allowed whenever a standardizable set of semantics can be shared between client, server, and any intermediaries that may be between them. [...]
Keep things simple and stick to the standard HTTP methods: they are well-known and they are supported by a huge amount of clients and proxies.
See below a couple of approaches you can use to get metadata from your resources using HTTP verbs:
Using a sub-resource
You could have a metadata sub-resource for the resources you want to request some metadata. For example, to get the metadata of a user resource, it would be as simple as:
GET /api/users/johndoe/metadata HTTP/1.1
Host: example.com
Accept: application/json
Using a custom media type
Another approach you could consider is a custom media type such as application/vnd.company.metadata+json for representing the metadata of your resources. So, you would have something as following:
GET /api/users/johndoe HTTP/1.1
Host: example.com
Accept: application/vnd.company.metadata+json
With this approach, the same endpoint could support other media types such as application/json and/or application/vnd.company+json to return the data itself:
GET /api/users/johndoe HTTP/1.1
Host: example.com
Accept: application/json
GET /api/users/johndoe HTTP/1.1
Host: example.com
Accept: application/vnd.company+json
If you need, another media type such as application/vnd.company.full+json could be used to request both data and metadata of a resource:
GET /api/users/johndoe HTTP/1.1
Host: example.com
Accept: application/vnd.company.full+json`
A similar approach is used by the GitHub API.
When you trying to make HTTP web services surely there is also some method which you can use in HTTP headers.
but also there is also many property attribute which contains the info regarding request/response
like
"status", "Content-Type" etc.
you can also set these property in your web services.
like
"Content-Type": "application/json";
Here, when you set this attribute in any "Request/Response" that means you allow only that specific MIME type data in "Request/Response".
I have the basic understanding of HTTP Request/Response I hope this info will help you Please check and make sure you provided content related settings with appropriate MIME Type.
otherwise you can follow this link www.webdev.org
I'm a newbie both in SOAP and REST programming.
In SOAP the structure and the fields of the entities being exchanged
are always well and unambiguously documented in the WSDL.
I think the same does not happen in REST.
How is the developer of the REST API supposed to
document the structure and all the fields of the JSON objects, representing the entities being exchanged?
REST and SOAP can't be compared directly, as they are very different things. You can implement REST over SOAP if you want, but not the opposite. I recommend reading this answer.
In RESTful APIs you are supposed to document your media-types properly and let the interaction be driven by the underlying protocol, but don't look for that in most of the HTTP APIs that call themselves REST. They are using the term as a buzzword and often do the opposite of that, documenting the protocol instead of the media-types.
For instance, if you have an User resource, you are supposed to have a proper media-type for it in a format like JSON or XML that looks like application/vnd.mycompany.user.v1+json, and your documentation should describe what this JSON document looks like so the client knows what to expect. This doesn't have to be as strict as a WSDL. In fact, it can be a human readable documentation like you would do for documenting a class API or something like that.
The client can say what media-types he is prepared to accept with the Accept header. For instance, if a client wants the v1 representation in JSON, he can use something like:
GET /users/xyz
Accept: application/vnd.mycompany.user.v1+json
If he wants the v2 representation in XML, he can use something like:
GET /users/xyz
Accept: application/vnd.mycompany.user.v2+xml
And if he simply wants JSON and will let the server decide what to do, he can use a generic media-type and figure out what the server threw at him by checking the Content-Type response header.
GET /users/xyz
Accept: application/json
However, keep in mind that most of the so called REST APIs you'll find don't use custom media-types like this. Instead, they use the same generic media-types like application/json and application/xml everywhere. That means the clients have to identify resources through URI semantics and relations, and that's not REST at all. I'm not saying it's wrong, it's simple and works for many problems, but it's not REST and it doesn't solve the same kind of problems REST really intends to solve.
REST does not establish or recommend a way for you to structure your data. It's only meant to make it easy for anyone to figure out which methods and entities your API supports. You don't even necessarily need to output JSON in your REST API.
We're having a bit of a discussion on the subject of posting data to a REST endpoint. Since the objects are quite complex, the easiest solution is to simply serialize them as JSON and send this in the request body.
Now the question is this: Is this kosher? Or should the JSON be set as a form parameter like data=[JSON]? Or is sending of JSON in the request body just frowned upon for forcing the clients using the application, to send their data via JavaScript instead of letting the browser package it up as application/x-www-form-urlencoded?
I know all three options work. But which are OK? Or at least recommended?
I'd say that both methods will work well
it's important that you stay consistent across your APIs. The option I would personally choose is simply sending the content as application/json.
POST doesn't force you to use application/x-www-form-urlencoded - it's simply something that's used a lot because it's what webbrowsers use.
There is nothing wrong about sending it directly as serialized JSON, for example google does this by default in it's volley library (which obviously is their recommended REST library for android).
If fact, there are plenty of questions on SO about how not to use JSON, but rather perform "normal" POST requests with volley. Which is a bit counter intuitive for beginners, having to overwrite it's base class' getParams() method.
But google having it's own REST library doing this by default, would be my indicator that it is OK.
You can use JSON as part of the request data as the OP had stated all three options work.
The OP needs to support JSON input as it had to support contain complex structural content. However, think of it this way... are you making a request to do something or are you just sending what is basically document data and you just happen to use the POST operation as the equivalent of create new entry.
That being the case, what you have is basically a resource endpoint with CRUDL semantics. Following up on that you're actually not limited to application/json but any type that the resource endpoint is supposed to handle.
For non-resource endpoints
I find that (specifically for JAX-RS) the application/x-www-urlencoded one is better.
Consistency with OAuth 2.0 and OpenID Connect, they use application/x-www-urlencoded.
Easier to annotate the individual fields using Swagger Annotations
Swagger provides more defaults.
Postman generates a nice form for you to fill out and makes things easier to test.
Examples of non-resource endpoints:
Authentication
Authorization
Simple Search (though I would use GET on this one)
Non-simple search where there are many criteria
Sending a message/document (though I would also consider multipart/form-data so I can pass meta data along with the content, but JAX-RS does not have a standard for this one Jersey and RestEasy have their own implementations)
How to structure an API where the same data may request in different format, in a RESTful format. For example.
GET /person/<id> //get the details of resource <id>
Now depending on the client (browser) requirement, the data may send as html (say normal rendering) or Json (say ajax call). So my doubts are
Can I keep the same url for both requests, or should keep them seperate?
How to detect whether the request is for html/Json at the server. The request type is same (GET). So which parameter should I consider.
How to detect the difference in data type at client (html/Json)\
thanks,
bsr.
Similar question: REST Content-Type: Should it be based on extension or Accept header?
The accepted answers has great points.
Can I keep the same url for both requests, or should keep them seperate?
Yes, keep them the same. Its the same resource, you're just asking for different representations of it.
How to detect whether the request is for html/Json at the server. The request type is same (GET). So which parameter should I consider.
You can use the Accept header to specify the return content-type.
How to detect the difference in data type at client (html/Json)\
You would look at the "Content-Type" header.
What about adding a variable for output type?