Skip to content

Content Negotiation

Jon Freer edited this page Oct 20, 2018 · 4 revisions

Proactive

Proactive (server-driven) negotiation involves deferring resource representation selection to the origin server. The client or "agent" specifies a set of criteria using explicit proactive negotiation headers, referred to as the Accept* headers (Accept, Accept-Language, Accept-Encoding, Accept-Charset) that the origin server can use to select an available and compatible representation.

Downsides

  • The values specified within the Accept* headers lead to fingerprinting and decreased client privacy (although Noti does not capture any data about it's clients).
  • The origin server must implement a potentially complex algorithm (or suite of algorithms) to choose a representation based on the information specified by the client.
  • Since the Accept* headers outline a specific set of conditions that should be satisfied when serving a response, this form of negotiation inherently reduces the reusability of a response from a caching perspective.
  • It's technically impossible for the origin server to choose the "best" representation for any given user, because that would imply that the needs of each client could be holistically expressed via HTTP and that the origin server could serve those needs.
  • Specifying the Accept* headers can be burdensome and inefficient for clients.

Support

Noti has been implemented to support proactive negotiation. Issuing requests using the Accept* headers will result in Noti determining the resource representation that "best" satisfies the criteria specified based on an internal algorithm.

Algorithm

Although RFC7231 is comprehensive from defining the syntax and semantics of the various components of content negotiation, it does not proceed to describe a formal algorithm for origin servers to use when selecting representations based on the Accept* headers. Due to this, the algorithms are specific to each origin server leading to varying implementations such the Apache 2.2 algorithm. Noti defers to the algorithm implemented within the Request#selectVariant method.

Reactive

Reactive (agent-driven) negotiation is the opposite of proactive negotiation, since the client or "agent" holds the power of choosing the representation. Using reactive negotiation, the origin server replies to the client's request for a resource representation with a 300 (Multiple Choices) response that lists the various representations supported for the resource in the form of URIs and additional helpful metadata. The client can then choose to issue a subsequent request to one of the provided URIs using the metadata to retrieve a representation it desires.

Downsides

  • Results in an extra request when retrieving resource representations, since the origin server must first present a list of available representations for the client or "agent" to choose from.
    • It is technically possible that a client could choose to only interact with one of the results provided within the response received from the initial request. However, thought should be given towards the possibility that an origin server may no longer choose to support the representation initially provided as an option.

Support

At this time, Noti does not support reactive (agent-driven) negotiation. However, since there are various well-known drawbacks of proactive (server-driven) negotiation, implementing support is imminent.

Algorithm

Even though reactive negotiation is not currently supported, the following is the high-level algorithm that could be used to implement it in the future:

  1. Ensure the request is either a GET or HEAD request.
    1. Although proactive negotiation headers (Accept*) can be specified in requests other than GET or HEAD (such as PUT, POST, etc.) the complexity of the algorithm rises.
  2. Ensure no proactive negotiation headers (Accept*) are specified in the request.
  3. Send back a response using a hypermedia media type (such as application/vnd.siren+json) that lists the various links along with metadata such as language, encoding, charset, etc. of each resource that are available.

Media Types

Supported

Noti is currently equipped to serve representations in the following media type formats:

  • application/json (JSON)
  • application/xml (XML)
  • application/vnd.siren+json (Siren)
  • application/yaml (YAML)
  • application/x-yaml (YAML)
  • text/yaml (YAML)
  • text/x-yaml (YAML)
  • text/vnd.yaml (YAML)

To Be Supported

The following media type formats are in the works, so check back for support:

  • application/hal+json (HAL)
  • application/hal+xml (HAL)
  • application/protobuf (Protobuf)
  • application/x-protobuf (Protobuf)

Encodings

Supported

Noti is currently equipped to provide representations encoded with the following coding schemes:

  • gzip

Clone this wiki locally