REST is an architectural style which, if followed stringent, allows clients to decouple themselfs from APIs/services. This allows the latter one to evolve freely without breaking clients which as a result make them more failure-robust. This properties are, however, only obtainable if you follow certain constraints like
- Adhere to the underlying transport protocol (HTTP) to increase likelihood of cross-domain interoperability
- HATEOAS (focus on meaningful link relation names and support of URIs provided by the API/server)
- focus on media-types (contract of the exchanged media-type syntax and semantic)
fully. Just following it partially wont yield all the benefits it has to offer, unfortunately.
According to RFC 7231 PUT
The PUT method requests that the state of the target resource be created or replaced with the state defined by the representation enclosed in the request message payload.
Loosly speaking, PUT
demands that the former representation of a certain resource is being replaced with the payload received of a PUT
request if it didn't violate any semantical restrictions. The server, however, is free to add or modify the request to its need, i.e. add links and other data if needed.
Hypertext as the engine of application state (HATEOAS) is one of the few constraint REST puts on the table. It demands that APIs/servers feed clients with URIs clients can use. Similar to the Web we use every day, links can be annotated with meaningful description about the content or the intent of the URI and if interested gets clicked by us humans. This concept should be translated to REST applications as well. The descriptive text accompanying the URI is called link relation name and clients should use it to determine whether to invoke the URI or not or help the client to determine when to invoke which URI. It should be as meaningful to clients as possible and may be specified either in certain media-types, common standards or domain knowledge. I.e. a pageable collection might use link relation like next
, prev
, first
and last
to give a client the possiblility to page through the different elements of a collection without the client needing to know the exact URI. It will just invoke the URI based on the link relation name. This technique helps clients to be robust in cases when the server changes its URI structure. It is rather obvious that clients that parse URIs to determine the intent will break easily if a server ever changes its URI structure, clients making use of link relations don't actually care about the concrete URI spelling used as the URI is just used to invoke the API again.
According to one of Fielding's blog post, APIs should support clients with all the information they need to proceed their task. This includes providing all necessary links a client can invoke from the current state on. This takes away the burden of clients from parsing and interpreting URIs and generating them later on to perform the request. A response from the server might contain links like the one below:
{
"name": "bob",
...
"_links": [
"self": {
"href": "http://.../users/1"
},
"identifier": {
"href": "http://.../users/U00001V002"
},
"friends": [
"tim": {
"href": "http://.../users/2"
},
"sam": {
"href": "http://.../users/3"
},
...
],
...
]
}
What links or information to return is completly domain specific. Restricting to just JSON i.e. is a bad choice here either as JSON lacks support for links and furthermore can't describe the semantics of the actual content.
The above representation might lead to clients preassuming that certain resources have a certain type and then just create a marshaller for that specific type. Such systems might easily break if new fields are added or old ones omitted or renamed. Instead of clients using typed resources meaningful to them APIs should be designed arround media types. Fielding even states that
REST APIs should spend almost all of its descriptive effort in defining the media type(s) used for representing resources and driving application state, or in defining extended relation names and/or hypertext-enabled mark-up for existing standard media types
Media types are the coupling part between clients and servers in a REST architecture. Instead of a client directly coupling to a respective API (and therefore needing update whenever the API changes), both, server and clients, couple to plenty of media types and negotiate about which ones they understand. Similar to browsers, applications might add support for new media types on the fly through plugins later on without even requiring a restart.
The focus on well-defined media-types further help clients and servers to avoid breaking changes later on. I.e. instead of versioning a certain API, the media type can be versioned as it defines the syntax and semantics of the headers and payload exchanged. HTML i.e. decided to stay backwards compatible to avoid breaking older clients that can't update to newer versions of the spec.
Certain media-types like application/atom+xml
or application/hal+json
provide certain benefits in terms of HATEOAS support. They, however, might probably be too generic for most applications. application/collection+json
i.e. is also only useful for collections returned. According to Fielding media types should be generic enough to be reusable accross domains but specific enough to be usable in certain domains. I.e. to exchange user information one might use text/vcard
or one of the other variants (i.e.: XML, JSON) instead of creating a new user-centric media type. A list of already defined media types can be found here
As you might hopefully see, each and every step involved in a REST architecture focuses on the decoupling of clients from APIs and to keep interoperability of different peers in that architecture as high as possible.
With that being said, as already mentioned, while an URI has to identify exactly one resource, the content of a resource might be exposed via multiple URIs. You can therefore, as proposed, just send multiple links a client can simply invoke including meaningful link-relation names as response to the client. A more proper REST way would include to switch over to media-type support in the long run and describe the syntax and semantics a client or server may expect though.