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

AnyEvent::HTTPD::Router - Adding Routes to AnyEvent::HTTPD

DESCRIPTION

AnyEvent::HTTPD::Router is an extension to the AnyEvent::HTTPD module, from which it is inheriting. It adds the reg_routes() method to it.

This module aims to add as little as possible overhead to it while still being flexible and extendable. It requires the same little dependencies that AnyEvent::HTTPD uses.

The dispatching for the routes happens first. If no route could be found, or you do not stop further dispatching with stop_request() the registered callbacks will be executed as well; as if you would use AnyEvent::HTTPD. In other words, if you plan to use routes in your project you can use this module and upgrade from callbacks to routes step by step.

Routes support http methods, but custom methods https://cloud.google.com/apis/design/custom_methods can also be used. You don't need to, of course ;-)

SYNOPSIS

use AnyEvent::HTTPD::Router;

my $httpd       = AnyEvent::HTTPD::Router->new( port => 1337 );
my $all_methods = [qw/GET DELETE HEAD POST PUT PATCH/];

$httpd->reg_routes(
    GET => '/index.txt' => sub {
        my ( $httpd, $req ) = @_;
        $httpd->stop_request;
        $req->respond([
            200, 'ok', { 'Content-Type' => 'text/plain', }, "test!" ]);
    },
    $all_methods => '/my-method' => sub {
        my ( $httpd, $req ) = @_;
        $httpd->stop_request;
        $req->respond([
            200, 'ok', { 'X-Your-Method' => $req->method }, '' ]);
    },
    GET => '/calendar/:year/:month/:day' => sub {
        my ( $httpd, $req, $param ) = @_;
        my $calendar_entries = get_cal_entries(
            $param->{year}, $param->{month}, $param->{day}
        );

        $httpd->stop_request;
        $reg->respond([
            200, 'ok', { 'Content-Type' => 'application/json'},
            to_json($calendar_entries)
        ]);
    },
    GET => '/static-files/*' => sub {
        my ( $httpd, $req, $param ) = @_;
        my $requeted_file = $param->{'*'};
        my ($content, $content_type) = black_magic($requested_file);

        $httpd->stop_request;
        $req->respond([
            200, 'ok', { 'Content-Type' => $content_type }, $content ]);
    }
);

$httpd->run();

METHODS

  • new()

    Creates a new AnyEvent::HTTPD::Router server. The constructor handles the following parameters. All further parameters are passed to AnyEvent::HTTPD.

    • dispatcher

      You can pass your own implementation of your router dispatcher into this module. This expects the dispatcher to be an instance not a class name.

    • dispatcher_class

      You can pass your own implementation of your router dispatcher into this module. This expects the dispatcher to be a class name.

    • routes

      You can add the routes at the constructor. This is an ArrayRef.

    • known_methods

      Whenever you register a new route this modules checks if the method is either customer method prefixed with ':' or a $known_method. You would need to change this, if you would like to implement WebDAV, for example. This is an ArrayRef.

    • auto_respond_404

      If the value for this parameter is set to true a a simple 404 responder will be installed that responds if not route matches. You can implement your own handler see EVENTS.

  • reg_routes( [$method, $path, $callback]* )

    You can add further routes with this method. Multiple routes can be added at once. To add a route you need do add 3 parameters: <method>, <path>, <callback>.

  • *

    AnyEvent::HTTPD::Router subclasses AnyEvent::HTTPD so you can use all methods the parent class.

EVENTS

  • no_route_found => $request

    When the dispatcher can not find a route that matches on your request, the event no_route_found will be emitted.

    In the case that routes and callbacks (reg_cb()) for paths as used with AnyEvent::HTTPD are mixed, keep in mind that that no_route_found will happen before the other path callbacks are executed. So for a 404 not found handler you could do

    $httpd->reg_cb('' => sub {
        my ( $httpd, $req ) = @_;
        $req->respond( [ 404, 'not found', {}, '' ] );
    });

    If you just use reg_routes() and don't mix with reg_cb() for paths you could implement the 404 not found handler like this:

    $httpd->reg_cb('no_route_found' => sub {
        my ( $httpd, $req ) = @_;
        $req->respond( [ 404, 'not found', {}, '' ] );
    });

    This is exactly what you get if you specify auto_respond_404 at the constructor.

  • See "EVENTS" in AnyEvent::HTTPD

WRITING YOUR OWN ROUTE DISPATCHER

If you want to change the implementation of the dispatching you specify the dispatcher or dispatcher_class. You need to implement the match() method.

In the case you specify the request_class for AnyEvent::HTTPD you might need to make adaptions to the match() method as well.

SEE ALSO

There are a lot of HTTP Router modules in CPAN:

BUILDING AND RELEASING THIS MODULE

This module uses https://metacpan.org/pod/Minilla.

LICENSE

Copyright (C) Martin Barth.

This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself.

CONTRIBUTORS

Paul Koschinski

AUTHOR

Martin Barth (ufobat)