NAME

Kelp::Response - Format an HTTP response

SYNOPSIS

Examples of how to use this module make a lot more sense when shown inside route definitions. Note that in the below examples $self->res is an instance of Kelp::Response:

# Render simple text
sub text {
    my $self = shift;
    $self->res->text->render("It works!");
}

# Render advanced HTML
sub html {
    my $self = shift;
    $self->res->html->render("<h1>It works!</h1>");
}

# Render a mysterious JSON structure
sub json {
    my $self = shift;
    $self->res->json->render({ why => 'no' });
}

# Render the stock 404
sub missing {
    my $self = shift;
    $self->res->render_404;
}

# Render a template
sub view {
    my $self = shift;
    $self->res->template('view.tt', { name => 'Rick James' } );
}

DESCRIPTION

The PSGI specification requires that each route returns an array with status code, headers and body. Plack::Response already provides many useful methods that deal with that. This module extends Plack::Response to add the tools we need to write graceful PSGI compliant responses. Some methods return $self, which makes them easy to chain.

ATTRIBUTES

rendered

Tells if the response has been rendered. This attribute is used internally and unless you know what you're doing, we recommend that you do not use it.

partial

Sets partial response. If this attribute is set to a true value, it will cause finalize to return the HTTP status code and headers, but not the body. This is convenient if you intend to stream your content. In the following example, we set partial to 1 and use finalize to get a writer object for streaming.

sub stream {
    my $self = shift;
    return sub {
        my $responder = shift;

        # Stream JSON
        $self->res->set_code(200)->json->partial(1);

        # finalize will now return only the status code and headers
        my $writer = $responder->( $self->res->finalize );

        # Stream JSON body using the writer object
        for ( 1 .. 30 ) {
            $writer->write(qq|{"id":$_}\n|);
            sleep 1;
        }

        # Close the writer
        $writer->close;
    };
}

For more information on how to stream, see the "Delayed-Response-and-Streaming-Body" in PSGI docs.

METHODS

render

This method tries to act smart, without being a control freak. It will fill out the blanks, unless they were previously filled out by someone else. Here is what is does:

  • If the response code was not previously set, this method will set it to 200.

  • If no content-type is previously set, render will set is based on the type of the data rendered. If it's a reference, then the content-type will be set to application/json, otherwise it will be set to text/html.

    # Will set the content-type to json
    $res->render( { numbers => [ 1, 2, 3 ] } );
  • Last, the data will be encoded with the charset specified by the app.

set_content_type

Sets the content type of the response and returns $self.

# Inside a route definition
$self->res->set_content_type('image/png');

text, html, json, xml

These methods are shortcuts for set_content_type with the corresponding type. All of them set the content-type header and return $self so they can be chained.

$self->res->text->render("word");
$self->res->html->render("<p>word</p>");
$self->res->json->render({ word => \1 });

set_header

Sets response headers. This is a wrapper around "header" in Plack::Response, which returns $self to allow for chaining.

$self->res->set_header('X-Something' => 'Value')->text->render("Hello");

no_cache

A convenience method that sets several response headers instructing most browsers to not cache the response.

$self->res->no_cache->json->render({ epoch => time });

The above response will contain headers that disable caching.

set_code

Set the response code.

$self->res->set_code(401)->render("Access denied");

render_404

A convenience method that sets code 404 and returns "File Not Found".

sub some_route {
    if ( not $self->req->param('ok') ) {
        return $self->res->render_404;
    }
}

If your application's tone is overly friendly or humorous, you will want to create a custom 404 page. The best way to do this is to subclass this module into your own class, for example MyApp::Response. Then override the render_404 method.

package MyApp::Response;
use parent 'Kelp::Response';

sub render_404 {
    my $self = shift;
    $self->set_code(404)->template('errors/404.tt');
}

You'll have to override the "response" in Kelp method in your main module too, in order to instruct it to use your new class:

package MyApp;
use parent 'Kelp';

sub response {
    my $self = shift;
    return MyApp::Response->new( app => $self );
}

render_500

Renders the stock "500 - Server Error" message. See "render_404" for examples on how to customize it.

template

This method renders a template. The template should be previously configured by you and included via a module. See Kelp::Module::Template for a template module.

sub some_route {
    my $self = shift;
    $self->res->template('home.tt', { login => 'user' });
}