Skip to content

Response

MVC::Keayl::Response is a mutable builder for a single outgoing HTTP response. Controllers and middleware set the status, headers, and body on it; the server adapter then calls finish to obtain the (status, headers, body) tuple it hands back to the connection.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
use MVC::Keayl::Response;

my $response = MVC::Keayl::Response.new;

$response.status = 201;
$response.content-type('application/json');
$response.location('/users/1');
$response.write('{"id":1}');

my ($status, $headers, $body) = $response.finish;

Construction

Named argument Meaning
:status HTTP status code. Defaults to 200.
:headers A hash of header names to initial values.
:body The initial body content.

Status

status is a writable accessor:

1
2
$response.status;        # 200
$response.status = 404;

Headers

Header names are matched case-insensitively, and the display casing you set is preserved on output.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
$response.set-header('Content-Type', 'text/plain');   # set / replace
$response.add-header('Set-Cookie', 'a=1');            # append another value
$response.add-header('Set-Cookie', 'b=2');

$response.header('content-type');   # 'text/plain'
$response.header('set-cookie');     # 'a=1, b=2'  (values joined for reading)

$response.has-header('Content-Type');   # True
$response.delete-header('Content-Type');

$response.headers;   # { 'Set-Cookie' => 'a=1, b=2' }  (display names, joined values)

Convenience accessors

content-type and location are getter/setter shortcuts for their headers, and content-length reports the body's UTF-8 byte count:

1
2
3
4
5
6
7
$response.content-type('application/json');
$response.content-type;     # 'application/json'

$response.location('/users/1');
$response.location;         # '/users/1'

$response.content-length;   # byte count of the current body

Body buffering

The body accumulates across write calls; the body getter returns the joined buffer, and the body setter replaces it:

1
2
3
4
5
$response.write('Hello, ');
$response.write('world');
$response.body;             # 'Hello, world'

$response.body('replaced'); # discards the buffer

Finalization

finish commits the response and returns the adapter tuple: a (status, headers, body) list where headers is an itemized list of name => value pairs (one pair per value, so multi-value headers like Set-Cookie stay separate) and body is a UTF-8 Blob:

1
2
3
4
5
my ($status, $headers, $body) = $response.finish;

$status;          # 201
$headers.list;    # (Content-Type => ..., Content-Length => ..., ...)
$body;            # Blob

On finalization the response supplies a default Content-Type of text/html; charset=utf-8 when none was set, and always sets Content-Length to the body's byte count.