File Coverage

blib/lib/Router/XS.pm
Criterion Covered Total %
statement 12 16 75.0
branch 0 2 0.0
condition n/a
subroutine 10 11 90.9
pod 9 10 90.0
total 31 39 79.4


line stmt bran cond sub pod time code
1             package Router::XS;
2 1     1   16367 use Exporter 'import';
  1         2  
  1         364  
3              
4             my @STD = qw(check_route add_route);
5             my @REST = qw(get post put patch del head conn options any);
6             our @EXPORT_OK = (@STD, @REST);
7             our %EXPORT_TAGS = (std => \@STD, rest => \@REST, all => [@STD, @REST]);
8              
9             our $VERSION = 0.01;
10              
11             require XSLoader;
12             XSLoader::load();
13              
14             sub get ($&) {
15 1     1 1 5989 add_route("GET/$_[0]", $_[1]);
16             }
17              
18             sub post ($&) {
19 1     1 1 390 add_route("POST/$_[0]", $_[1]);
20             }
21              
22             sub put ($&) {
23 1     1 1 386 add_route("PUT/$_[0]", $_[1]);
24             }
25              
26             sub patch ($&) {
27 1     1 1 415 add_route("PATCH/$_[0]", $_[1]);
28             }
29              
30             sub del ($&) {
31 1     1 1 378 add_route("DELETE/$_[0]", $_[1]);
32             }
33              
34             sub head ($&) {
35 1     1 1 374 add_route("HEAD/$_[0]", $_[1]);
36             }
37              
38             sub conn ($&) {
39 1     1 1 407 add_route("CONNECT/$_[0]", $_[1]);
40             }
41              
42             sub options ($&) {
43 1     1 1 380 add_route("OPTIONS/$_[0]", $_[1]);
44             }
45              
46             sub any ($&) {
47 1     1 1 371 add_route("*/$_[0]", $_[1]);
48             }
49              
50             sub route ($) {
51 0     0 0   my ($sub, @args) = check_route(join '/', $_[0]->request->path, $_[0]->request->method);
52 0 0         if ($sub) {
53 0           return $sub->($_[0], @args);
54             }
55 0           return undef;
56             }
57              
58             1;
59              
60             =encoding utf8
61              
62             =head1 NAME
63              
64             Router::XS - Fast URI path to value lookup
65              
66             =head1 SYNOPSIS
67              
68             use Router::XS ':all';
69              
70             my $user_home_page = sub { ... };
71              
72             add_route('/user/*', $user_home_page);
73             my ($sub, @captures) = check_route('/user/foobar');
74              
75             # or use HTTP method verbs to add routes
76             get '/user/*' => sub { ... };
77              
78             my ($sub, @captures) = check_route('GET/user/foobar');
79              
80             =head1 FUNCTIONS
81              
82             =head2 add_route ($path, $sub)
83              
84             Adds a new route associated with a subroutine to the router. Will C if a
85             matching route has already been added. Accepts asterisks (C<*>) as wildcards
86             for captures. C<$path> may be prepended with an HTTP method:
87              
88             add_route('POST/some/path', $sub);
89              
90             =head2 check_route ($path)
91              
92             Checks a URI path against the added routes and returns C if no match is
93             found, otherwise returning the associated subroutine reference and any captures
94             from wildcards:
95              
96             =head2 get/post/put/patch/del/head/conn/options/any
97              
98             Sugar for C: adds a route using C<$path> for the associated HTTP
99             method:
100              
101             put '/product/*' => sub { ... };
102              
103             The C function accepts any HTTP method. When an incoming request is
104             received, C must still be called.
105              
106             See the test file included in this distribution for further examples.
107              
108             =head1 THREAD SAFETY
109              
110             Router::XS is not thread safe: however if you add all routes at the startup of
111             an application under a single thread, and do not call C thereafter,
112             it should be thread safe.
113              
114             =head1 BENCHMARKS
115              
116             On my machine Router::XS performs well against other fast Routers. The test
117             conditions add 200 routes, and then check how fast the router can match the
118             path '/interstitial/track':
119              
120             Rate Router::Boom Router::R3 Router::XS
121             Router::Boom 344536/s -- -85% -93%
122             Router::R3 2235343/s 549% -- -54%
123             Router::XS 4860641/s 1311% 117% --
124              
125             =head2 DEPENDENCIES
126              
127             This module uses C to build a
128             n-ary tree of paths. C is a single C header file, included in this
129             distribution. uthash is copyright (c) 2003-2017, Troy D. Hanson.
130              
131             =head1 INSTALLATION
132              
133             perl Makefile.PL
134             make
135             make test
136             make install
137              
138             =head1 AUTHOR
139              
140             E 2017 David Farrell
141              
142             =head1 LICENSE
143              
144             The (two-clause) FreeBSD License
145              
146             =head1 ACKNOWLEDGEMENTS
147              
148             Thanks to L for letting their employees contribute to Open Source.
149              
150             =head1 SEE ALSO
151              
152             There are many routers on L including:
153              
154             =over 4
155              
156             =item * L
157              
158             =item * L
159              
160             =item * L
161              
162             =item * L
163              
164             =back
165              
166             =cut