The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.

NAME

Kelp::Request - Request class for a Kelp application

SYNOPSIS

    my $request = Kelp::Request( app => $app, env => $env );

DESCRIPTION

This module provides a convenience layer on top of Plack::Request. It extends it to add several convenience methods and support for application encoding.

ENCODING

Starting with version 2.10, Kelp::Request simplifies input handling and improves correctness by automatically decoding path, query parameters and content.

Headers (so cookies as well) are unaffected, as they aren't consistently supported outside of ASCII range. JSON now decodes request data into the proper charset instead of flat utf8 regardless of configuration. Sessions are configured separately in middlewares, so they must themselves do the proper decoding.

Following methods will return values decoded with charset either from Content-Type header or the one specified in the app's configuration ("request_charset" in Kelp):

  • param

  • cgi_param

  • body_param

  • json_param

  • parameters

  • body_parameters

  • content

  • json_content

Following methods will always decode to "request_charset" in Kelp because they are not the part of message's content (URIs should always be in ASCII-compilant encoding, UTF-8 is preferable):

  • path

  • param (from query)

  • cgi_param (from query)

  • parameters (from query)

  • query_parameters

If you wish to get input in the original request encoding, use these instead (note: there is no raw_param):

  • raw_path

  • raw_parameters

  • raw_query_parameters

  • raw_body_parameters

  • raw_body (instead of content)

Following methods will return decoded values if the other parts of the system are configured to decode them:

  • session - depends on session middleware

Some caveats about the automatic decoding and "request_charset" in Kelp configuration parameter:

As always, UTF-8 (the default) works best - don't change to avoid issues. Other ASCII-compilant encodings should work well. "content" will always be decoded properly, but application/x-www-form-urlencoded and multipart/form-data will have issues with non-ASCII-compilant encodings. Especially the latter, because the information about Content-Type of a single part is lost on Plack level and it is not properly decoded using that encoding. In such corner cases, you should probably get the full undecoded body using "raw_body" and parse it yourself.

If you wish to disable automatic decoding, you can set "request_charset" in Kelp to undef - it will then ignore any charset which came with the message and let you do your own decoding.

ATTRIBUTES

app

A reference to the Kelp application. This will always be the real application, not the reblessed controller.

stash

Returns a hashref, which represents the stash of the current the request

An all use, utility hash to use to pass information between routes. The stash is a concept originally conceived by the developers of Catalyst. It's a hash that you can use to pass data from one route to another.

    # put value into stash
    $self->req->stash->{username} = app->authenticate();
    # more convenient way
    $self->stash->{username} = app->authenticate();

    # get value from stash
    return "Hello " . $self->req->stash->{username};
    # more convenient way
    return "Hello " . $self->stash('username');

named

This hash is initialized with the named placeholders of the path that the current route is processing.

route_name

Contains a string name of the route matched for this request. Contains route pattern if the route was not named.

charset

Returns the charset from the Content-Type HTTP header or undef if there is none. Will ignore the charset unless Content-Type is text/* or application/*. Readonly.

METHODS

param

Shortcut for returning the HTTP parameters of the request with heavy amount of dwimmery. It has two modes of operation and behaves differently for JSON and non-JSON requests.

  • If passed with a parameter, returns the value value of a parameter with that name from either request body or query (body is preferred). This always returns a scalar value.

  • If passed without parameters, returns the list containing the names of available parameters. This always returns a list.

The behavior is changed when the content type of the request is application/json and a JSON module is loaded. In that case, it will decode the JSON body and return values from it instead. If the root contents of the JSON document is not an HASH (after decoding), then it will be wrapped into a hash with its reftype as a key, for example:

    { ARRAY => [...] } # when JSON contains an array as root element
    { '' => [...] }    # when JSON contains something that's not a reference

    my $array_ref = $kelp->param('ARRAY');

There also exists a special, deprecated behavior of param returning the entire contents of json when called without arguments in scalar context. This will be later removed, so that param will work exactly the same regardless of whether the request was json. Use "json_content" for that instead.

Since this method behaves differently based on the form of input, you're encouraged to use other, more specific methods listed below.

query_param

Same as "param", but always returns parameters from query string.

body_param

Same as "param", but always returns parameters from body form.

json_param

Same as "param", but always returns parameters from JSON body.

cgi_param

CGI.pm compatible implementation of param (but does not set parameters). It is not recommended to use this method, unless for some reason you have to maintain CGI.pm compatibility. Misusing this method can lead to bugs and security vulnerabilities.

parameters

Same as "parameters" in Plack::Request, but the keys and values in the hash are decoded.

raw_parameters

Same as "parameters" in Plack::Request. The hash keys and values are not decoded.

query_parameters

Same as "query_parameters" in Plack::Request, but the keys and values in the hash are decoded.

raw_query_parameters

Same as "query_parameters" in Plack::Request, The hash keys and values are not decoded.

body_parameters

Same as "body_parameters" in Plack::Request, but the keys and values in the hash are decoded.

raw_body_parameters

Same as "body_parameters" in Plack::Request, The hash keys and values are not decoded.

content

Same as "content" in Plack::Request, but the result is decoded.

This is the go-to method for getting the request body for string manipulation character by character. It can be useful when you, for example, want to run a regex on the body. Use this instead of "raw_body".

raw_body

Same as "raw_body" in Plack::Request. The result is not decoded.

This is the go-to method for getting the request body for string manipulation byte by byte. An example would be deserializing the body with a custom serializer. Use this instead of "content".

json_content

Returns the json-decoded body of the request or undef if the request is not json, there is no json decoder or an error occured.

path

Same as "path" in Plack::Request, but the result is decoded.

raw_path

Same as "path" in Plack::Request. The result is not decoded.

address, remote_host, user

These are shortcuts to the REMOTE_ADDR, REMOTE_HOST and REMOTE_USER environment variables.

    if ( $self->req->address eq '127.0.0.1' ) {
        ...
    }

Note: See "Deploying" in Kelp::Cookbook for configuration required for these fields when using a proxy.

session

Returns the Plack session hash or croaks if no Session middleware was included.

    sub get_session_value {
        my $self = shift;
        $self->session->{user} = 45;
    }

If called with a single argument, returns that value from the session hash:

    sub set_session_value {
        my $self = shift;
        my $user = $self->req->session('user');
        # Same as $self->req->session->{'user'};
    }

Set values in the session using key-value pairs:

    sub set_session_hash {
        my $self = shift;
        $self->req->session(
            name  => 'Jill Andrews',
            age   => 24,
            email => 'jill@perlkelp.com'
        );
    }

Replace all values with a hash:

    sub set_session_hashref {
        my $self = shift;
        $self->req->session( { bar => 'foo' } );
    }

Clear the session:

    sub clear_session {
        my $self = shift;
        $self->req->session( {} );
    }

Delete session value:

    delete $self->req->session->{'useless'};

is_ajax

Returns true if the request was called with XMLHttpRequest.

content_type_is

Returns true if request has a Content-Type header starting with a passed string.

is_text

Returns true if the request's content type was text/plain.

is_html

Returns true if the request's content type was text/html.

is_json

Returns true if the request's content type was application/json.

is_xml

Returns true if the request's content type was application/xml.

charset_decode

Shortcut method, which decodes a string using "charset" or "request_charset" in Kelp. A second optional parameter can be passed, and if true will cause the method to ignore charset passed in the Content-Type header.

It does noting if "request_charset" in Kelp is undef or false.