NAME
Plack::Middleware::PeriAHS::ParseRequest - Parse Riap request from HTTP request
VERSION
version 0.13
SYNOPSIS
# in your app.psgi
use Plack::Builder;
builder {
enable "PeriAHS::ParseRequest",
match_uri => m!^/api(?<uri>/[^?]*)!;
};
DESCRIPTION
This middleware's task is to parse Riap request from HTTP request (PSGI environment) and should normally be the first middleware put in the stack.
Parsing result
The result of parsing will be put in $env-
{"riap.request"}> hashref.
Aside from that, this middleware also sets these for convenience of later middlewares:
$env->{'periahs.default_fmt'} => STR
Default output format, will be used for response if
fmt
is not specified in Rinci request. Determined using some simple heuristics, i.e. graphical browser like Firefox or Chrome will get 'HTML', command-line browser like Wget or Curl will get 'Text', others will get 'json'.$env->{'periahs.jsonp_callback'} => STR
From form variable
callback
.$env->{'periahs.riap_client'} => OBJ
Store the Riap client (instance of Perinci::Access).
Parsing process
From HTTP header and request body. First parsing is done as per Riap::HTTP specification's requirement. All X-Riap-*
request headers are parsed for Riap request key. When an unknown header is found, HTTP 400 error is returned. Then, request body is read for args
. application/json
document type is accepted, and also text/yaml
(if accept_yaml
configuration is enabled).
Additionally, the following are also done:
From URI. Request URI is checked against match_uri configuration. If URI doesn't match this regex, a 404 error response is returned. It is a convenient way to check for valid URLs as well as set Riap request keys, like:
qr!^/api/(?<fmt>json|yaml)/!;
The default match_uri
is qr/(?<uri>[^?]*)/.
From form variables. If parse_form
is enabled, args
request key will be set (or added) from GET/POST request variables, for example: http://host/api/foo/bar?a=1&b:j=[2] will set arguments a
and b
(":j" suffix means value is JSON-encoded; ":y" and ":p" are also accepted if the accept_yaml
configurations are enabled). In addition, request variables -riap-*
are also accepted for setting other Riap request keys. Unknown Riap request key or encoding suffix will result in 400 error.
If request format is JSON and form variable callback
is defined, then it is assumed to specify callback for JSONP instead part of args
. "callback(json)" will be returned instead of just "json".
From URI (2, path info)
. If parse_path_info
configuration is enabled, and uri
Riap request key has been set (so metadata can be retrieved), args
will be set (or added) from URI path info. See "parse_path_info" in the configuration documentation.
http://host/api/v1/Module::Sub/func/a1/a2/a3
will result in ['a1', 'a2', 'a3'] being fed into Perinci::Sub::GetArgs::Array. An unsuccessful parsing will result in HTTP 400 error.
CONFIGURATIONS
match_uri => REGEX or [REGEX, CODE] (default qr/.?/)
This provides an easy way to extract Riap request keys (typically
uri
) from HTTP request's URI. Put named captures inside the regex and it will set the corresponding Riap request keys, e.g.:qr!^/api(?<uri>/[^?]*)!
If you need to do some processing, you can also specify a 2-element array containing regex and code. When supplied this, the middleware will NOT automatically set Riap request keys with the named captures; instead, your code should do it. Code will be supplied ($env, \%match) and should set $env->{'riap.request'} as needed. An example:
match_uri => [ qr!^/api (?: /(?<module>[\w.]+)? (?: /(?<func>[\w+]+) )? )?!x, sub { my ($env, $match) = @_; if (defined $match->{module}) { $match->{module} =~ s!\.!/!g; $env->{'riap.request'}{uri} = "/$match->{module}/" . ($match->{func} // ""); } }];
Given URI
/api/Foo.Bar/baz
,uri
Riap request key will be set to/Foo/Bar/baz
.accept_yaml => BOOL (default 0)
Whether to accept YAML-encoded data in HTTP request body and form for
args
Riap request key. If you only want to deal with JSON, keep this off.parse_form => BOOL (default 1)
Whether to parse
args
keys and Riap request keys from form (GET/POST) variable of the name-x-riap-*
(notice the prefix dash). If an argument is already defined (e.g. from request body) or request key is already defined (e.g. fromX-Riap-*
HTTP request header), it will be skipped.parse_path_info => BOOL (default 0)
Whether to parse arguments from $env->{PATH_INFO}. Note that this will require a Riap
meta
request to the backend, to get the specification for function arguments. You'll also most of the time need to prepare the PATH_INFO first. Example:parse_path_info => 1, match_uri => [ qr!^/ga/(?<mod>[^?/]+)(?: /?(?: (?<func>[^?/]+)?: (<pi>/?[^?]*) ) )!x, sub { my ($env, $m) = @_; $m->{mod} =~ s!::!/!g; $m->{func} //= ""; $env->{'riap.request'}{uri} = "/$m->{mod}/$m->{func}"; $env->{PATH_INFO} = $m->{pi}; }, ]
riap_client => OBJ
By default, a Perinci::Access object will be instantiated (and later put into
$env-
{'periahs.riap_client'}> for the next middlewares) to perform Riap requests. You can supply a custom object here.
SEE ALSO
AUTHOR
Steven Haryanto <stevenharyanto@gmail.com>
COPYRIGHT AND LICENSE
This software is copyright (c) 2012 by Steven Haryanto.
This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.