File Coverage

blib/lib/Mojo/Server.pm
Criterion Covered Total %
statement 53 59 89.8
branch 13 20 65.0
condition 3 6 50.0
subroutine 13 14 92.8
pod 6 6 100.0
total 88 105 83.8


line stmt bran cond sub pod time code
1             package Mojo::Server;
2 54     54   418 use Mojo::Base 'Mojo::EventEmitter';
  54         114  
  54         376  
3              
4 54     54   398 use Carp qw(croak);
  54         146  
  54         2741  
5 54     54   906 use Mojo::File qw(path);
  54         126  
  54         3475  
6 54     54   1799 use Mojo::Loader qw(load_class);
  54         110  
  54         2870  
7 54     54   405 use Mojo::Util qw(md5_sum);
  54         161  
  54         2476  
8 54     54   9127 use POSIX ();
  54         111323  
  54         1536  
9 54     54   319 use Scalar::Util qw(blessed);
  54         123  
  54         57981  
10              
11             has app => sub { shift->build_app('Mojo::HelloWorld') };
12             has reverse_proxy => sub { $ENV{MOJO_REVERSE_PROXY} || !!@{shift->trusted_proxies} };
13             has trusted_proxies => sub { [split /\s*,\s*/, ($ENV{MOJO_TRUSTED_PROXIES} // '')] };
14              
15             our @ARGS_OVERRIDE;
16              
17             sub build_app {
18 38     38 1 133 my ($self, $app) = (shift, shift);
19 38         165 local $ENV{MOJO_EXE};
20 38 100       181 return $self->app($app->new(@_))->app unless my $e = load_class $app;
21 1 50       19 die ref $e ? $e : qq{Can't find application class "$app" in \@INC. (@INC)\n};
22             }
23              
24             sub build_tx {
25 965     965 1 1718 my $self = shift;
26 965         3053 my $tx = $self->app->build_tx;
27 965         1592 push @{$tx->req->trusted_proxies}, @{$self->trusted_proxies};
  965         2725  
  965         3162  
28 965 100       2956 $tx->req->reverse_proxy(1) if $self->reverse_proxy;
29 965         3546 return $tx;
30             }
31              
32             sub daemonize {
33              
34             # Fork and kill parent
35 0 0   0 1 0 die "Can't fork: $!" unless defined(my $pid = fork);
36 0 0       0 exit 0 if $pid;
37 0 0       0 POSIX::setsid == -1 and die "Can't start a new session: $!";
38              
39             # Close filehandles
40 0         0 open STDIN, '<', '/dev/null';
41 0         0 open STDOUT, '>', '/dev/null';
42 0         0 open STDERR, '>&', STDOUT;
43             }
44              
45             sub load_app {
46 17 100   17 1 90 my ($self, $path, @args) = (shift, shift, ref $_[0] ? %{shift()} : @_);
  1         8  
47              
48             # Clean environment (reset FindBin defensively)
49             {
50 17         31 local $0 = $path = path($path)->to_abs->to_string;
  17         65  
51 17         2350 require FindBin;
52 17         5055 FindBin->again;
53 17         3409 local @ENV{qw(MOJO_APP_LOADER MOJO_EXE)} = (1, undef);
54 17         69 local @ARGS_OVERRIDE = @args;
55              
56             # Try to load application from script into sandbox
57 17         39 my $app = eval "package Mojo::Server::Sandbox::@{[md5_sum $path]}; do \$path";
  17         1714  
58 17 100 33     197 my $err = $app ? undef : $@ || $! || "$path did not return a true value";
59 17 100       70 die qq{Can't load application from file "$path": $err} if $err;
60 16 100 66     337 die qq{File "$path" did not return an application object.\n} unless blessed $app && $app->can('handler');
61 15         71 $self->app($app);
62             };
63 15         131 FindBin->again;
64              
65 15         2897 return $self->app;
66             }
67              
68             sub new {
69 235     235 1 27595 my $self = shift->SUPER::new(@_);
70 235     965   2018 $self->on(request => sub { shift->app->handler(shift) });
  965         3057  
71 235         1197 return $self;
72             }
73              
74 1     1 1 982 sub run { croak 'Method "run" not implemented by subclass' }
75              
76             1;
77              
78             =encoding utf8
79              
80             =head1 NAME
81              
82             Mojo::Server - HTTP/WebSocket server base class
83              
84             =head1 SYNOPSIS
85              
86             package Mojo::Server::MyServer;
87             use Mojo::Base 'Mojo::Server', -signatures;
88              
89             sub run ($self) {
90              
91             # Get a transaction
92             my $tx = $self->build_tx;
93              
94             # Emit "request" event
95             $self->emit(request => $tx);
96             }
97              
98             =head1 DESCRIPTION
99              
100             L is an abstract base class for HTTP/WebSocket servers and server interfaces, like L,
101             L, L, L, L and
102             L.
103              
104             =head1 EVENTS
105              
106             L inherits all events from L and can emit the following new ones.
107              
108             =head2 request
109              
110             $server->on(request => sub ($server, $tx) {...});
111              
112             Emitted when a request is ready and needs to be handled.
113              
114             $server->on(request => sub ($server, $tx) {
115             $tx->res->code(200);
116             $tx->res->headers->content_type('text/plain');
117             $tx->res->body('Hello World!');
118             $tx->resume;
119             });
120              
121             =head1 ATTRIBUTES
122              
123             L implements the following attributes.
124              
125             =head2 app
126              
127             my $app = $server->app;
128             $server = $server->app(MojoSubclass->new);
129              
130             Application this server handles, defaults to a L object.
131              
132             =head2 reverse_proxy
133              
134             my $bool = $server->reverse_proxy;
135             $server = $server->reverse_proxy($bool);
136              
137             This server operates behind a reverse proxy, defaults to the value of the C environment variable
138             or true if L is not empty.
139              
140             =head2 trusted_proxies
141              
142             my $proxies = $server->trusted_proxies;
143             $server = $server->trusted_proxies(['10.0.0.0/8', '127.0.0.1', '172.16.0.0/12', '192.168.0.0/16', 'fc00::/7']);
144              
145             This server expects requests from trusted reverse proxies, defaults to the value of the C
146             environment variable split on commas with optional whitespace. These proxies should be addresses or networks in CIDR
147             form.
148              
149             =head1 METHODS
150              
151             L inherits all methods from L and implements the following new ones.
152              
153             =head2 build_app
154              
155             my $app = $server->build_app('MyApp');
156             my $app = $server->build_app('MyApp', log => Mojo::Log->new);
157             my $app = $server->build_app('MyApp', {log => Mojo::Log->new});
158              
159             Build application from class and assign it to L.
160              
161             =head2 build_tx
162              
163             my $tx = $server->build_tx;
164              
165             Let application build a transaction.
166              
167             =head2 daemonize
168              
169             $server->daemonize;
170              
171             Daemonize server process.
172              
173             =head2 load_app
174              
175             my $app = $server->load_app('/home/sri/myapp.pl');
176             my $app = $server->load_app('/home/sri/myapp.pl', log => Mojo::Log->new);
177             my $app = $server->load_app('/home/sri/myapp.pl', {log => Mojo::Log->new});
178              
179             Load application from script and assign it to L.
180              
181             say Mojo::Server->new->load_app('./myapp.pl')->home;
182              
183             =head2 new
184              
185             my $server = Mojo::Server->new;
186             my $server = Mojo::Server->new(reverse_proxy => 1);
187             my $server = Mojo::Server->new({reverse_proxy => 1});
188              
189             Construct a new L object and subscribe to L event with default request handling.
190              
191             =head2 run
192              
193             $server->run;
194              
195             Run server. Meant to be overloaded in a subclass.
196              
197             =head1 SEE ALSO
198              
199             L, L, L.
200              
201             =cut