Content negotiation is an important aspect of RESTful APIs to make it possible for diverse systems to work seamlessly together. It’s based on enabling clients and servers to agree on the format and language of data they exchange.

What is the purpose of Content Negotiation?

RESTful resources can support multiple representations. Each team of developers implements one of more ways (e.g. data formats) to receive requests and return responses on the server side. Efficient communication between client and server can only be guaranteed if the both sides agree on how the exchange takes place. This is especially valid if the request and response support multiple formats. The act of agreeing on a way to represent the exchanged data format is content negotiation.

Content negotiation ensures the following:

  • Support for diverse clients is useful when the requested representation differs.
    • e.g. Accept: application/json or Accept: application/xml.
  • Data format flexibility can come into play when a client prefers a smaller response.
    • e.g. Instead of Accept: application/json, use Accept: application/msgpack which is a binary serialization, making the response smaller and easier to transfer.
  • Language localization will respond with content translated into the client’s preferred language
    • e.g. Accept-Language: en-US.

Who decides the data format?

There are two sides to the exchange:

  • The client
  • The server

Technically, either side can decide on how the data is transferred between the two.

For server-side negotiation the server must decide based on various factors what the most appropriate format should be. This incurs assumptions that can be erroneous and the server-side implementation can also be more complex. This forces the client to adhere to the rules set up on the server-side.

For client-side negotiation the client lets the server know what format it prefers. This approach is more versatile and thus makes more sense.

There are two ways to communicate the data format:

  • HTTP request headers
  • or resource URI patterns.

HTTP Request Headers

The HTTP request headers Content-Type and Accept are used to determine the data format that will be sent in the request and the response. There are several types to choose from. Here are some examples:

  • text/plain
  • text/html
  • application/json
  • application/zip
  • image/gif
  • image/jpeg

Below is an example of what the keys look like in the content package. Note the Accept type

Content-Type: application/json, text/plain
Accept: application/json

If the Accept header is not present, the server gets to decide the format of the response.

Content Negotiation using URL Patterns

Below are a couple of ways to communicate a preferred data format.

Via the extension on the URL:

https://www.example-api.com/record/47.xml
https://www.example-api.com/record/47.json

or via an extra parameter:

https://www.example-api.com/record/47?format=xml
https://www.example-api.com/record/47?format=json

Defining preferences via a quality factor

The Accept header may hold multiple values with an added value that defines preference or priority.

In this example, the client declares it accpets both json and xml formats, with json being preferred over xml, as defined by the numeric value in q which can be between 0 and 1. If the server can only satisfy the xml format, it will respond with that. The final alternative is if the server can’t respond with either json, or xml, so it responds with what it can.

Accept: application/json,application/xml;q=0.9,*/*;q=0.8

How does Dotkernel API handle Content Negotiation?

Out of the box, Dotkernel API uses HTTP request headers Content-Type and Accept to handle client-side content negotiation. It has both application/json, application/hal+json included. Of course, you can change these as development progresses for your project. There is also support for per-route content negotiation, if you should need it.

The configuration is done is its own configuration file. The validation is automatic and several explicit errors are handled, based on what format is supported.

Check out the relevant links below for exact details on the Dotkernel implementation of content negotiation.

Relevant Links

Content Negotiation in Dotkernel API

Content types on iana.org


Looking for PHP, Laminas or Mezzio Support?

As part of the Laminas Commercial Vendor Program, Apidemia offers expert technical support and services for:

  • Modernising Legacy Applications
  • Migration from any version of Zend Framework to Laminas
  • Migration from legacy Laminas API Tools (formerly Apigility) to Dotkernel API
  • Mezzio and Laminas Consulting and Technical Audit
  • Leave a Reply

    Your email address will not be published. Required fields are marked *

    You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>