This guest post comes from Mark Massé, Senior Director of Engineering at ESPN. Mark has fourteen years of engineering, management, and architecture experience with The Walt Disney Company and received a “Disney Inventor Award” in 2008.
This architecture is attractive to organizations for a number of reasons, such as:
In order to support the increasing complexity of web applications being built with this architecture, the design and development practices applied to REST APIs must continue to mature.
One area of REST API design that warrants our attention is the use of “Media Types”, which are also known as either MIME Types or Content Types. Media types have the following syntax:
type "/" subtype *( ";" parameter )
REST APIs typically work with media types that fall under the “application” type. Note that parameters may follow the type/subtype in the form of attribute=value pairs that are separated by a leading semi-colon (;) character. HTTP/1.1 uses media types in the values of the Accept and Content-Type headers. As shown in the example below, client applications can convey their preference for a response body’s media type using HTTP/1.1’s Accept request header.
In the Content-Type header of an HTTP/1.1 request or response, a media type reference indicates the “type” associated with the message body’s byte sequence. The example below demonstrate a Content-Type header value that references a media type with a “charset” parameter:
Content-type: text/html; charset=ISO-8859-4
REST APIs commonly use either the “application/json” or the “application/xml” media type in the Content-Type header of an HTTP/1.1 request or response. This anti-pattern is a form of tunneling, that we might call “type tunneling” because it masks the content’s actual “type” and reveals only its format. While it is correct that the body is formatted using languages such as JSON or XML, its content usually has semantics that require special processing beyond simply parsing the language’s syntax. Clients will expect a specific set of “fields” and hypermedia “links” to be present in a response message body’s formatted content.
A “Web Resource Model” begins with the hierarchical organization of data and functions that results from the design of a REST API’s URI paths. While its true that REST requires URIs be treated as opaque, the design of URIs matters a lot to folks that enjoy logical data models. Web resource schemas can add another dimension to the resource model by providing data structure type definitions to describe the representational forms that are traded back and forth between client and server.
As an example, consider a REST API URI such as http://api.soccer.restapi.org/players/2113 that responds to GET requests with a representation of a Player resource that is formatted using JSON. If the Content-Type header field value declares that the response’s media type is application/json, it has accurately conveyed the content’s syntax but has disregarded the schema of the Player representation. This response’s Content-Type header simply tells a client that it should expect some JSON-formatted text. Instead, it should communicate that the body contains a representation of a Player document that is formatted with JSON.
Most modern REST APIs communicate thier schema, via human-readable documentation hosted on a developer facing portal or wiki. This approach leads to a more static type system as the REST API owners are encouraging client developers to hard-code (and easily typo) the details of their API’s types. Once hard-coded by clients, the REST API must employ and maintain a versioning system in order to significantly evolve the schemas. Machine-readable schema defintions are preferred since they can be loaded dynamically at client development-time and runtime to up the level of robustness, introspection, and developer productivity.
Some modern REST APIs use frameworks like XML Schema Definition (XSD) and JSONSchema to communicate their schemas in a machine-readable format. These solutions have two design concerns that make them unfavorable. First, they require content (the application’s data) in an HTTP/1.1 message’s body to include references to the type definition, instead of conveying this type link where it belongs, in the Content-Type header. Second, formats are fashionable – they are cosmetic and they go in and out of style. Formats should be pluggable. Swapping one format in for another should not require an overhaul of your web resource type system. The schema of our web resources should be de-coupled from the format du jour. Schemas are constant reflections of our data structures. Formats offer a variety of serialization flavors.
To support and separate these design concerns, the “application/wrml” media type can be used to communicate both the “Format” and “Schema” of the data exchanged between a REST API and its clients.
application/wrml; schema=URI; format=URI
This media type may appear excessive when compared to simpler ones like application/json. However, this is a worthwhile trade-off since this media type communicates, directly to clients, distinct and complementary bits of information regarding the content of a message. The Web Resource Modeling Language (WRML, www.wrml.org) provides this “pluggable” media type to give rich web applications direct access to structural information and format serialization code. The media type’s self-descriptive and pluggable design reduces the need for information to be communicated out-of-band and then hard-coded by client developers.
The example below shows WRML’s media type used to describe a Player form that is formatted using JSON.
The application/wrml media type’s required schema parameter’s value identifies a separate document that details the Player resource type’s form, which is independent of the media type’s format parameter’s value. The media type’s required format parameter’s value identifies a document resource that describes the JSON format itself.