Plack::Middleware::Negotiate - Apply HTTP content negotiation as Plack middleware
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. http://example.org/foo?format=xml
extension => 'strip'; # e.g. http://example.org/foo.xml
$app;
};
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 http://example.org/foo?format=xml if format xml has been defined.
-
URL path extension (if enabled with option
extension
)e.g. format is set to xml for http://example.org/foo.xml 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.
Creates a new negotiation middleware with a given set of formats.
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.
Tells whether a format name is known. By default this is the case if the format name exists in the list of formats.
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 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
, andlanguage
. 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 valuekeep
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:
$ENV{PLACK_MIDDLEWARE_NEGOTIATE_TRACE} = 1;
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.