/usr/share/perl5/UR/Service/UrlRouter.pm is in libur-perl 0.430-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 | package UR::Service::UrlRouter;
use strict;
use warnings;
use UR;
use Sub::Install;
use overload '&{}' => \&__call__, # To support being called as a code ref
'bool' => sub { 1 }; # Required due to an unless() test in UR::Context
class UR::Service::UrlRouter {
has_optional => [
verbose => { is => 'Boolean' },
]
};
foreach my $method ( qw( GET POST PUT DELETE ) ) {
my $code = sub {
my($self, $path, $sub) = @_;
my $list = $self->{$method} ||= [];
push @$list, [ $path, $sub ];
};
Sub::Install::install_sub({
as => $method,
code => $code,
});
}
sub _log {
my $self = shift;
return unless $self->verbose;
print STDERR join("\t", @_),"\n";
}
sub __call__ {
my $self = shift;
return sub {
my $env = shift;
my $req_method = $env->{REQUEST_METHOD};
my $matchlist = $self->{$req_method} || [];
foreach my $route ( @$matchlist ) {
my($path,$cb) = @$route;
my $call = sub { my $rv = $cb->($env, @_);
$self->_log(200, $req_method, $env->{PATH_INFO}, $path);
return ref($rv) ? $rv : [ 200, [], [$rv] ];
};
if (my $ref = ref($path)) {
if ($ref eq 'Regexp' and (my @matches = $env->{PATH_INFO} =~ $path)) {
return $call->(@matches);
} elsif ($ref eq 'CODE' and $path->($env)) {
return $call->();
}
} elsif ($env->{PATH_INFO} eq $path) {
return $call->();
}
}
$self->_log(404, $req_method, $env->{PATH_INFO});
return [ 404, [ 'Content-Type' => 'text/plain' ], [ 'Not Found' ] ];
}
}
1;
=pod
=head1 NAME
UR::Service::UrlRouter - PSGI-aware router for incoming requests
=head1 SYNOPSIS
my $r = UR::Service::UrlRouter->create();
$r->GET('/index.html', \&handle_index);
$r->POST(qr(update/(.*?).html, \&handle_update);
my $s = UR::Service::WebServer->create();
$s->run( $r );
=head1 DESCRIPTION
This class acts as a middleman, routing requests from a PSGI server to the
appropriate function to handle the requests.
=head2 Properties
=over 4
=item verbose
If verbose is true, the object will print details about the handled requests
to STDOUT.
=back
=head2 Methods
=over 4
=item $r->GET($URLish, $handler)
=item $r->POST($URLish, $handler)
=item $r->PUT($URLish, $handler)
=item $r->DELETE($URLisn, $handler)
These four methods register a handler for the given request method + URL pair.
The first argument specifies the URL to match against, It can be specified
in one of the following ways
=over 4
=item $string
A simple string matches the incoming request if the request's path is eq to
the $string
=item qr(some regex (with) captures)
A regex matches the incoming request if the path matches the regex. If the
regex contains captures, these are passed as additional arguments to the
$handler.
=item $coderef
A coderef matches the incoming request if $coderef returns true. $coderef
is given one acgument: the PSGI env hashref.
$handler is a CODE ref. When called, the first argument is the standard PSGI
env hashref.
=back
=item $r->__call__
__call__ is not intended to be called directly.
This class overloads the function dereference (call) operator so that the
object may be used as a callable object (ie. $obj->(arg, arg)). As overload
expects, __call__ returns a code ref that handles the PSGI request by finding
an appropriate match with the incoming request and a previously registered
handler. If no matching handler is found, it returns a 404 error code.
If multiple handlers match the incoming request, then only the earliest
registered handler will be called.
=back
=head1 SEE ALSO
L<UR::Service::WebServer>, L<HTTP::Server::PSGI>, L<Plack>
=cut
|