Should the WebDAV PROPFIND method be used with JSON in REST APIs? - json

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

Related

What is "application/x-amz-json" and how is it different from "application/json"?

I've run into "application/x-amz-json-1.1" in making requests to AWS resources. Most recently, it became a problem that an API Gateway I was communicating with didn't like handling it (for whatever reason). This got me wondering what the benefit to using application/x-amz-json-1.1 instead of application/json for my requests is. And to my disappointment, AWS doesn't seem to have any documentation on this odd content type.
So I turn to SO: what is "application/x-amz-json" and how is it different from "application/json"?
Amazon does not specifically document what application/x-amz-json Content-Type is for, however there are protocol documentations on Smithy (an open source language for defining services and SDKs published by AWS):
AWS JSON 1.1 protocol
AWS JSON 1.0 protocol
Considering the question relates to the difference when used as Content-Type1 header to make requests, I think we can tell the difference is:
application/json is to request/receive JSON data without anything more specific
application/x-amz-json-1.1 (or other version) is also to request/receive JSON data and expect additional behaviors described in the docs above. (i.e. tell the server/client this is JSON plus additional elements)
I think application/x-amz-json can be thought as a sort of extension or a more specific way of doing application/json requests.
it became a problem that an API Gateway I was communicating with didn't like handling it (for whatever reason)
In the specific case of making PATCH, PUT and POST requests to AWS Amazon API Gateway, specifying Content-Type header application/x-amz-json-1.1 or other version seems to be required. As per related docs:
Content-Type (Conditional)
Specifies JSON and the version, for example, Content-Type: application/x-amz-json-1.0.
Condition: Required for PATCH, PUT and POST requests.
Maybe the server understands application/json as basic JSON but requires application/x-amz-json-1.1 to perform specific requests.
1 Content-Tye header being used to tell the server/client how to process our request

HTTP header for indicating required stylistic property for the response body

What HTTP header should I use for specifying stylistic properties of an HTTP response, specifically the case of keys in a JSON object? A note: I am developing a REST API where I would like clients to provide an expected case, for example camelCase or snake_case.
When camelCase is specified a response would look like:
{
"peopleUrl": "…",
"postsUrl": "…"
}
When snake_case is specified a response would look like:
{
"people_url": "…",
"posts_url": "…"
}
The headers I’ve been looking at are Expect and Prefer. Expect is described as mandatory configurations a server must comply with or error, and Prefer is described as optional configurations. The specific syntax I was looking at is:
Expect: case=camel
or:
Prefer: case=camel
Currently, I’m feeling like Expect is the best because it requires the configuration. However, while in RFC 2616 an extension mechanism for Expect is provided, however in RFC 7231 this extension mechanism was removed and only the 100-continue field is allowed (scroll to the next page to see the note providing the warrant). The Prefer header was specified in RFC 7240 and does appear to have an extension mechanism.
Which header is best for this configuration option? Am I looking in the wrong direction with Expect and Prefer?
As some of the comments indicate, there probably isn't an existing HTTP header name, defined in the HTTP RFCs, which would cover/handle your use case. Using Expect or Prefer, with well-defined semantics that don't quite cover your needs, may lead to more pain/frustration than you'd like; those headers might be handled specially by existing clients, servers, and proxies in ways that you do not want/expect.
That said, there is nothing preventing you from using your own custom X- header for requests and responses, e.g. X-JSON-KeyStyle:
GET /path/to/resource HTTP/1.1
Host: ...
X-JSON-KeyStyle: camel
...
And then your response would indicate the style used in the returned data:
HTTP1/1 200 OK
...
X-JSON-KeyStyle: camel
...
By specification, any header names prefaced with X- are deliberately not handled/covered, and are for uses such as this. With this approach, then, you would only need document your custom HTTP header, for use by clients of your REST API.
Hope this helps!

REST JSON specification

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.

Why is the HTTP location header only set for POST requests/201 (Created) responses?

Ignoring 3xx responses for a moment, I wonder why the HTTP location header is only used in conjunction with POST requests/201 (Created) responses.
From the RFC 2616 spec:
For 201 (Created) responses, the Location is that of the new resource which was created by the request.
This is a widely supported behavior, but why shouldn't it be used with other HTTP methods? Take the JSON API spec as an example:
It defines a self referencing link for the current resource inside the JSON payload (not uncommon for RESTful APIs). This link is included in every payload. The spec says that you MUST include an HTTP location header, if you create a new document via POST and that the value is the same as the self referencing link in the payload, but this is ONLY needed for POST. Why bother with a custom format for a self referencing link, if you could just use the HTTP location header?
Note: This isn't specific to JSON API. It's the same for HAL, JSON Hyper-Schema or other standards.
Note 2: It isn't even specific to the HTTP location header as it is the same with the HTTP link header. As you can see the JSON API, HAL and JSON Hyper-Schema not only define conventions for self referencing links, but also to express information about related resources or possible actions for a resource. But it seems that they all could just use the HTTP link header. (They could even put the self referencing link into the HTTP link header, if they don't want to use the HTTP location header.)
I don't want to rant, it just seems to be some sort of "reinventing the wheel". It also seems to be very limiting: if you would just use HTTP location/link header, it doesn't matter if you ask for JSON, XML or whatever in your HTTP accept header and you would get useful meta-information about your resource on a HEAD request, which wouldn't contain the links if you would use JSON API, HAL or JSON Hyper-Schema.
The semantics of the Location header isn't that of a self-referencing link, but of a link the user-agent should follow in order to complete the request. That makes sense in redirects, and when you create a new resource that will be in a new location you should go to. If your request is already completed, meaning you already have a full representation of the resource you wanted, it doesn't make sense to return a Location.
The Link header may be considered semantically equivalent to an hypertext Link, but it should be used to reference metadata related to the given resource when the media-type is not hypermedia-aware, so it doesn't replace the functionality of a link to related resources in a RESTful API.
The need for a custom link format in the resource representation is inherent to the need to decouple the resource from the underlying implementation and protocol. REST is not coupled to HTTP, and any protocol for which there's a valid URI scheme can be used. If you decided to use the Link header for all links, you're coupling to HTTP.
Let's say you present an FTP link for clients to follow. Where would be the Link in that case?
The semantic of the Location header depends on the status code. For 201, it links to the newly created resource, but in 3xx requests it can have multiple (although similiar) meanings. I think that is why it is generally avoided for other usages.
The alternative is the Content-Location header, which always has a consistent meaning. It tells the client the canonical URL the resource it requested. It is purely informative (in contrast to the Location, which is expected to be processed by the client).
So, the Content-Location header seems to closer resemble a self-referencing link. However, the Content-Location also has no defined behavior for PUT and POST. It also seems to be quite rarely used.
This blogs post Location vs Content-Location is a nice comparison. Here is a quote:
Finally, neither header is meant for general-purpose linking.
In sum, requiring a standardized, self link in the body seems to be good idea. It avoids a lot of confusion on the client side.

Mimetypes for a RESTful API

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.