Skip to content
HTTP content negotiation as Plack Middleware
Branch: master
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Type Name Latest commit message Commit time
Failed to load latest commit information.


Plack::Middleware::Negotiate - Apply HTTP content negotiation as Plack middleware

Build Status Coverage Status Kwalitee Score


builder {
    enable 'Negotiate',
        formats => {
            xml  => { 
                type    => 'application/xml',
                charset => 'utf-8',
            html => { type => 'text/html', language => 'en' },
            _    => { size => 0 }  # default values for all formats           
        parameter => 'format', # e.g.
        extension => 'strip';  # e.g.


Plack::Middleware::Negotiate applies HTTP content negotiation to a PSGI request. In addition to normal content negotiation from a list of defined formats one may enable explicit format selection with a path extension or query parameter. In summary, the following methods are tried in this order to negotiate a known format:

  • HTTP GET/POST format parameter (if enabled with option parameter)

    e.g. format is set to xml for if format xml has been defined.

  • URL path extension (if enabled with option extension)

    e.g. format is set to xml for if format xml has been defined.

  • HTTP Accept Header (unless disabled with option explicit)

    e.g. format is set to xml if format xml has been defined with content type application/xml for Accept header value "application/xml".

The PSGI environment key negotiate.format is set to the chosen format name after negotiation. The PSGI response is enriched with corresponding HTTP headers Content-Type and Content-Language unless these headers already exist.

If used as pure application, this middleware returns a HTTP status code 406 if no format could be negotiated.


new( formats => { ... } [, %options ] )

Creates a new negotiation middleware with a given set of formats.

negotiate( $env )

Chooses a format based on a PSGI request. The request is first checked for explicit format selection via parameter and extension (if configured) and then passed to HTTP::Negotiate. On success the method returns a format name. The method may modify the PSGI request environment keys PATH_INFO and SCRIPT_NAME if format was selected by extension set to strip, and strips the format HTTP GET query parameter from QUERY_STRING if parameter is set to a format. If format was selected by HTTP POST body parameter, the parameter it is not stripped from the request.

known( $format )

Tells whether a format name is known. By default this is the case if the format name exists in the list of formats.

about( $format )

If the format was specified, this method returns a hash with quality, type, encoding, charset, and language. Missing values are set to the default.


Returns a list of content variants to be used in HTTP::Negotiate. The return value is an array reference of array references, each with seven elements: format name, source quality, type, encoding, charset, language, and size. The size is always zero.

add_headers( \@headers, $format )

Add apropriate HTTP response headers for a format unless the headers are already given.


  • formats

    A list of formats to choose among. Each format can be defined with type, quality (defaults to 1), encoding, charset, and language. The special format name _ (underscore) is reserved to define default values for all formats.

    Formats can also be used to directly route the request to a PSGI application:

      my $app = Plack::Middleware::Negotiate->new(
          formats => {
              json => { 
                  type => 'application/json',
                  app  => $json_app,
              html => {
                  type => 'text/html',
                  app  => $html_app,
  • parameter

    Enables explicit format selection with a query paramater, for instance format. Both HTTP GET and HTTP POST body parameters are supported.

  • extension

    Enables explicit format selection with a virtual file extension. The value strip strips a known format name from the request path. The value keep keeps the format name extension after format selection.

    The middleware takes care for rewriting and restoring PATH_INFO if it is configured to detect and strip a format extension.

  • explicit

    Disables content negotiation based on HTTP headers.


Plack::Middleware::Negotiate uses Log::Contextual to emit a logging message during content negotiation on logging level trace. Just set:



The Content-Encoding HTTP response header is not automatically set on a response and content negotiation based on size is not supported. Feel free to comment on whether and how this middleware should support both.


Jakob Voß, Christopher A. Kirke


Copyright 2014- Jakob Voß

This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.


Content negotiation in this module is based on HTTP::Negotiate. See HTTP::Headers::ActionPack::ContentNegotiation for an alternative approach. This module has some overlap with Plack::Middleware::SetAccept.

You can’t perform that action at this time.