NAME

YATT::Lite::WebMVC0::Connection - output buffer with request properties

SYNOPSIS

# Inside actions (*.ydo, <!yatt:action>, .htyattrc.pl), you will get
# a connection object as $CON (or $con). In templates, entity calls
# like &yatt:site_path(); implicitly use it.

# Read request parameters.
my $q = $CON->param('q');

# Build app-internal urls (mount-prefix aware).
my $path = $CON->site_path("/auth/login", [nx => $CON->current_path]);
my $url  = $CON->site_url("/confirm", [token => $token]); # for emails

# Redirect (never returns).
$CON->raise_redirect($CON->site_path("/"));

# Connection is just a blessed glob handle. You can print to it.
print {$CON} "foo", "bar";

# Per-request stash.
$CON->stash->{foo} = 3;

# Raise an error page.
$CON->error("Found error in %s!", $path);

#========================================
# Under the hood, a connection is created like this
# (usually via $siteapp->make_connection($parent_fh, @config)):

# If $env is like followings:
# $env->{PATH_INFO}       = '/mysite/user/hkoba'
# $env->{PATH_TRANSLATED} = '/var/www/webapps/mysite/html/user.yatt/hkoba'

my $con = YATT::Lite::WebMVC0::Connection->create(
             $parent_fh,
             env => $env,

             site_prefix => "/mysite",

             dir         => "/var/www/webapps/mysite/html",
             location    => "/",
             file        => "user.yatt",
             request_file => "user",  # file name part as requested
             subpath     => "/hkoba",

             # cgi => Plack::Request->new($env),
             # no_nested_query => 1
          );

DESCRIPTION

A connection object represents one HTTP request/response cycle. It is a blessed GLOB which buffers output printed to it, and also carries request properties (PSGI env, query parameters, the location quad: dir, location, file, subpath, and "request_file").

Most methods below are also exposed to templates as same-named entity functions (e.g. $CON->site_path(...) as &yatt:site_path(...);). See YATT::Lite::WebMVC0::SiteApp.

URL BUILDING METHODS

These four methods are the recommended way to build app-internal urls. The naming follows the widespread convention: *_path returns a path (no scheme://host), *_url returns an absolute url. All of them respect the mount point of the site ("site_prefix"), so they keep working when the app is deployed under a sub-path (e.g. behind Alias, Action or a reverse proxy).

$query is optional. It must be a HASH ref, an ARRAY ref of key-value pairs, or a query object (including $CON itself). Plain scalars and flattened key => value lists are rejected with an error (to prevent silent mistakes; see mkurl).

Note: for a link to a sibling page with a known depth, plain relative links (href="other", href="../login") are also fine and need no helper.

site_path($path, $query)

Returns site_prefix . $path . query_string. $path must start with / (it means site root, not server root). If $path is omitted, returns the site root (= "site_location").

$CON->site_path;                        # => /myapp/
$CON->site_path("/admin/");             # => /myapp/admin/
$CON->site_path("/list", {page => 2});  # => /myapp/list?page=2

site_url($path, $query)

Absolute url version of site_path. Use this when you need scheme://host - typically for urls put into emails. The scheme respects X-Forwarded-Proto (see mkprefix).

$CON->site_url("/confirm", [token => $token]);
# => https://example.com/myapp/confirm?token=...

current_path($query)

Returns the path of the current request (query string replaced by $query, dropped if omitted). Since $CON->mkquery accepts $CON itself as a query object, $CON->current_path($CON) reproduces the current url with its current parameters - useful to build nx (come-back url) parameters.

# Requested url: /myapp/item?page=2
$CON->current_path;               # => /myapp/item
$CON->current_path([page => 3]);  # => /myapp/item?page=3
$CON->current_path($CON);         # => /myapp/item?page=2

current_url($query)

Absolute url version of current_path.

REDIRECT

raise_redirect($url)

redirect($url)

Sends a 302 Found redirect and never returns - it is implemented with die and unwinds the stack, like other raise_* family members ("raise_response" in YATT::Lite::Util). Do not write code after it expecting it to run. raise_redirect is an alias of redirect, preferred because the name tells this never-return behavior.

$CON->raise_redirect($CON->site_path("/login", [nx => $nx]));

Open redirect protection is built in: if $url is a plain string pointing to a foreign host (//host/... or scheme://host/...), it is rejected with 400 Bad Request. To intentionally redirect to an external site, pass a SCALAR REF:

$CON->raise_redirect(\ $external_url);

Output printed so far is discarded, and the session (if any) is flushed before the redirect.

REQUEST PARAMETER METHODS

param($name)

Returns the query/body parameter. Without arguments, returns the list of parameter names. With $CON->param($name, $value), sets the value.

Note: unless "no_nested_query" in YATT::Lite::WebMVC0::SiteApp is on, parameters like foo[0], foo[bar] are restructured into ARRAY/HASH refs (nested query) and param returns them as-is.

multi_param($name)

List context aware variant, following modern CGI convention.

param_type($name, $type, $diag, $opts)

Type-checked parameter access. $type is either a Regexp or a name of re_* patterns in YATT::Lite::RegexpNames (e.g. integer, digit, name, nonempty, any). If the value does not match, dies with 400 Bad Request (or $diag message if given). Handy for input validation:

my $id = $CON->param_type(id => 'integer');

delete_param($name)

remove_param($name)

Deletes the parameter. (Two names for the same method.)

param_exists($name)

as_hash

queryobj

as_hash returns all parameters as a plain HASH. queryobj returns the underlying parameter container (nested query HASH, Hash::MultiValue or CGI-ish object).

LOCATION INSPECTION METHODS

These methods tell where the current request is. They return values, not links - to build links, use "URL BUILDING METHODS".

Suppose the site is mounted at /myapp (SCRIPT_NAME=/myapp) and https://example.com/myapp/auth/test?q=1 is served by auth/test.yatt. Then:

site_prefix    /myapp
site_location  /myapp/
location       /auth/
dir_location   /myapp/auth/
file_location  /myapp/auth/test
page_location  /myapp/auth/test
request_file   test
mapped_path    /myapp/auth/test
request_path   /myapp/auth/test
request_uri    /myapp/auth/test?q=1

(If the request were /myapp/auth/test.yatt?q=1 instead, request_file would be test.yatt, and file_location / mapped_path would be /myapp/auth/test.yatt - they reproduce how the request spelled the file name. page_location stays canonical (/myapp/auth/test) regardless. Others are not affected.)

site_prefix

The mount point of the whole site (without trailing /). Comes from "site_prefix" in YATT::Lite::WebMVC0::SiteApp config, or falls back to $env->{'yatt.script_name'} (normalized SCRIPT_NAME, set by SiteApp).

site_location

site_loc

site_prefix . '/'. The url path of the site root.

location

The location of current DirApp (directory), without site_prefix. Guaranteed to end with /.

dir_location

Like "location", but with the mount prefix prepended.

file_location

The url path of the current page: "dir_location" + "request_file". Like "mapped_path", this follows how the request spelled the file name (Apache content-negotiation model: the requested name is the base name and negotiation just appends extensions to it). The file name part is empty for index requests.

page_location

Canonical url path of the current page, based on the physical file name: "dir_location" + file name without the last extension (file name part is omitted for index pages). Unlike "file_location", this is not affected by how the request spelled the url. Use this for canonical links.

request_file

The file name part as it appeared in the request: extension-less when the request omitted it, extension-ful when the request spelled it, and empty when the file name was totally omitted (index requests). In other words, file - request_file = the extension supplemented by the dispatcher.

mapped_path

Reconstruction of the url path of the current request from the mapping result: site_prefix + location + request_file + subpath. Usually this equals "request_path"; they differ when REQUEST_URI does not represent the logical location (e.g. url rewriting). In list context, returns ($prefix_location_file, $subpath).

request_path

request_uri

request_uri is $env->{REQUEST_URI} (query string included). request_path is the same with query string stripped.

is_current_file($path)

True when $path addresses the current page. $path is a site-rooted literal - the same form as the argument of site_path, so a nav link and its current-page test can share one literal:

<yatt:if "&yatt:is_current_file(/auth/login);">
  <b>login</b>
<:yatt:else/>
  <a href="&yatt:site_path(/auth/login);">login</a>
</yatt:if>

Accepted forms: canonical (/auth/login), physical (/auth/login.yatt), and directory form for index pages (/auth/). Mount prefix and how the request spelled the url do not affect the result. Subpath is ignored.

is_current_page($file, $page)

Compares the page name (directory-independent) and subpage (subpath) against the current request.

LOW LEVEL URL METHODS

Building blocks of the above. Usually you won't need them directly - prefer site_path and its friends for new code.

mkurl($file, $param, %opts)

The oldest url builder. Returns an absolute url by default (note: this default is opposite to site_path family).

$file selects the base path:

undef or ''

The current request path.

'.'

The directory part of the current request path.

'name' (relative)

Sibling file in the same directory.

/abs (starts with /)

site_prefix . $file.

$param is passed to mkquery. %opts are:

local => 1

Omit scheme://host part (return path only).

mapped_path => 1

Use "mapped_path" (reconstruction of the requested url path from the mapping result) as the base, instead of REQUEST_URI. Useful when REQUEST_URI does not represent the logical location (e.g. url rewriting).

separator => $sep

Query separator. Default is &.

Caveat: %opts comes after the positional $param. mkurl("/admin/", local => 1) is a common mistake - "local" is taken as $param. Write mkurl("/admin/", undef, local => 1), or just use site_path("/admin/").

mkpath($file, $use_mapped_path)

The path building part of mkurl.

mkquery($param, $separator)

Builds a query string from $param: a HASH ref (keys sorted), an ARRAY ref of key-value pairs (order preserved), an object with keys/get_all (like Hash::MultiValue) or param (like CGI), or a connection itself (meaning its current parameters). In scalar context, returns ?key=value&... (? included) or an empty string. In list context, returns encoded key=value pairs.

mkprefix(@extras)

Returns scheme://host[:port] + @extras. The scheme respects $env->{HTTP_X_FORWARDED_PROTO} (reverse proxy) over $env->{'psgi.url_scheme'}.

mkhost($scheme)

Returns HTTP_HOST if set, otherwise SERVER_NAME with non-default :port.

PSGI/CGI ENV METHODS

Following methods return raw request env values. Each takes an optional $default:

referer, remote_addr, request_method, script_name, path_info, query_string, server_name, server_port, server_protocol, content_length, content_type.

Caveat about script_name: $CON->script_name is the raw $env->{SCRIPT_NAME}, which may contain handler artifacts like /cgi-bin/dispatch.cgi under Apache Action mapping. On the other hand, the entity &yatt:script_name(); returns the normalized $env->{'yatt.script_name'}. For url building, use "site_prefix" (or the entity).

Also:

raw_body, uploads, upload

Delegated to Plack::Request. PSGI mode only.

file, subpath, parameters, request_file

Read-only accessors of connection properties.

SESSION METHODS

Session support is delegated to the system (SiteApp). See YATT::Lite::WebMVC0::Partial::Session2 for the actual implementation of session_* hooks.

get_session

Returns the session object if the request has (or lazily resumes) one.

start_session(@init)

Starts a new session.

delete_session

flush_session

OTHER METHODS

current_user

current_user($method, @args)

Returns the user object loaded via $system->load_current_user. With arguments, invokes $user->$method(@args) (dies if no user is loaded).

accept_language(%opts)

Parses Accept-Language header and returns preferred language(s). Options: filter => \@langs (or Regexp/HASH/CODE), long => 1 (en_US style), detail => 1 (with quality values).

my $lang = $CON->accept_language(filter => [qw/en ja/]) || 'en';

Inherited basics

From YATT::Lite::Connection (parent class): buffer (current output), flush, stash (per-request HASH for your app), set_header, list_header, cget, configure, error($fmt, @args), raise($type, $fmt, @args), error_with_status($code, $fmt, @args), logbacktrace, logdump.

SEE ALSO

YATT::Lite::WebMVC0::SiteApp (entity functions), YATT::Lite