line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Mojo::Server::Daemon; |
2
|
53
|
|
|
53
|
|
4769
|
use Mojo::Base 'Mojo::Server'; |
|
53
|
|
|
|
|
121
|
|
|
53
|
|
|
|
|
350
|
|
3
|
|
|
|
|
|
|
|
4
|
53
|
|
|
53
|
|
367
|
use Carp qw(croak); |
|
53
|
|
|
|
|
130
|
|
|
53
|
|
|
|
|
2685
|
|
5
|
53
|
|
|
53
|
|
834
|
use Mojo::IOLoop; |
|
53
|
|
|
|
|
133
|
|
|
53
|
|
|
|
|
368
|
|
6
|
53
|
|
|
53
|
|
25176
|
use Mojo::Transaction::WebSocket; |
|
53
|
|
|
|
|
183
|
|
|
53
|
|
|
|
|
612
|
|
7
|
53
|
|
|
53
|
|
376
|
use Mojo::URL; |
|
53
|
|
|
|
|
133
|
|
|
53
|
|
|
|
|
297
|
|
8
|
53
|
|
|
53
|
|
286
|
use Mojo::Util qw(term_escape); |
|
53
|
|
|
|
|
132
|
|
|
53
|
|
|
|
|
2531
|
|
9
|
53
|
|
|
53
|
|
312
|
use Mojo::WebSocket qw(server_handshake); |
|
53
|
|
|
|
|
119
|
|
|
53
|
|
|
|
|
2202
|
|
10
|
53
|
|
|
53
|
|
358
|
use Scalar::Util qw(weaken); |
|
53
|
|
|
|
|
135
|
|
|
53
|
|
|
|
|
3296
|
|
11
|
|
|
|
|
|
|
|
12
|
53
|
|
50
|
53
|
|
388
|
use constant DEBUG => $ENV{MOJO_SERVER_DEBUG} || 0; |
|
53
|
|
|
|
|
133
|
|
|
53
|
|
|
|
|
176905
|
|
13
|
|
|
|
|
|
|
|
14
|
|
|
|
|
|
|
has acceptors => sub { [] }; |
15
|
|
|
|
|
|
|
has [qw(backlog max_clients silent)]; |
16
|
|
|
|
|
|
|
has inactivity_timeout => sub { $ENV{MOJO_INACTIVITY_TIMEOUT} // 30 }; |
17
|
|
|
|
|
|
|
has ioloop => sub { Mojo::IOLoop->singleton }; |
18
|
|
|
|
|
|
|
has keep_alive_timeout => sub { $ENV{MOJO_KEEP_ALIVE_TIMEOUT} // 5 }; |
19
|
|
|
|
|
|
|
has listen => sub { [split /,/, $ENV{MOJO_LISTEN} || 'http://*:3000'] }; |
20
|
|
|
|
|
|
|
has max_requests => 100; |
21
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
sub DESTROY { |
23
|
130
|
|
|
130
|
|
11129
|
my $self = shift; |
24
|
130
|
50
|
|
|
|
537
|
return if ${^GLOBAL_PHASE} eq 'DESTRUCT'; |
25
|
130
|
|
|
|
|
4000
|
my $loop = $self->ioloop; |
26
|
130
|
|
100
|
|
|
284
|
$loop->remove($_) for keys %{$self->{connections} // {}}, @{$self->acceptors}; |
|
130
|
|
|
|
|
867
|
|
|
130
|
|
|
|
|
434
|
|
27
|
|
|
|
|
|
|
} |
28
|
|
|
|
|
|
|
|
29
|
132
|
|
|
132
|
1
|
330
|
sub ports { [map { $_[0]->ioloop->acceptor($_)->port } @{$_[0]->acceptors}] } |
|
132
|
|
|
|
|
454
|
|
|
132
|
|
|
|
|
412
|
|
30
|
|
|
|
|
|
|
|
31
|
|
|
|
|
|
|
sub run { |
32
|
0
|
|
|
0
|
1
|
0
|
my $self = shift; |
33
|
|
|
|
|
|
|
|
34
|
|
|
|
|
|
|
# Make sure the event loop can be stopped in regular intervals |
35
|
0
|
|
|
|
|
0
|
my $loop = $self->ioloop; |
36
|
0
|
|
|
0
|
|
0
|
my $int = $loop->recurring(1 => sub { }); |
37
|
0
|
|
|
0
|
|
0
|
local $SIG{INT} = local $SIG{TERM} = sub { $loop->stop }; |
|
0
|
|
|
|
|
0
|
|
38
|
0
|
|
|
|
|
0
|
$self->start->ioloop->start; |
39
|
0
|
|
|
|
|
0
|
$loop->remove($int); |
40
|
|
|
|
|
|
|
} |
41
|
|
|
|
|
|
|
|
42
|
|
|
|
|
|
|
sub start { |
43
|
138
|
|
|
138
|
1
|
321
|
my $self = shift; |
44
|
|
|
|
|
|
|
|
45
|
138
|
|
|
|
|
448
|
my $loop = $self->ioloop; |
46
|
138
|
100
|
|
|
|
585
|
if (my $max = $self->max_clients) { $loop->max_connections($max) } |
|
4
|
|
|
|
|
12
|
|
47
|
|
|
|
|
|
|
|
48
|
|
|
|
|
|
|
# Resume accepting connections |
49
|
138
|
100
|
|
|
|
479
|
if (my $servers = $self->{servers}) { |
|
|
100
|
|
|
|
|
|
50
|
1
|
|
|
|
|
7
|
push @{$self->acceptors}, $loop->acceptor(delete $servers->{$_}) for keys %$servers; |
|
1
|
|
|
|
|
4
|
|
51
|
|
|
|
|
|
|
} |
52
|
|
|
|
|
|
|
|
53
|
|
|
|
|
|
|
# Start listening |
54
|
137
|
|
|
|
|
489
|
elsif (!@{$self->acceptors}) { |
55
|
136
|
|
|
|
|
422
|
$self->app->server($self); |
56
|
136
|
|
|
|
|
253
|
$self->_listen($_) for @{$self->listen}; |
|
136
|
|
|
|
|
508
|
|
57
|
|
|
|
|
|
|
} |
58
|
|
|
|
|
|
|
|
59
|
136
|
|
|
|
|
674
|
return $self; |
60
|
|
|
|
|
|
|
} |
61
|
|
|
|
|
|
|
|
62
|
|
|
|
|
|
|
sub stop { |
63
|
1
|
|
|
1
|
1
|
3
|
my $self = shift; |
64
|
|
|
|
|
|
|
|
65
|
|
|
|
|
|
|
# Suspend accepting connections but keep listen sockets open |
66
|
1
|
|
|
|
|
4
|
my $loop = $self->ioloop; |
67
|
1
|
|
|
|
|
4
|
while (my $id = shift @{$self->acceptors}) { |
|
2
|
|
|
|
|
8
|
|
68
|
1
|
|
|
|
|
5
|
my $server = $self->{servers}{$id} = $loop->acceptor($id); |
69
|
1
|
|
|
|
|
4
|
$loop->remove($id); |
70
|
1
|
|
|
|
|
4
|
$server->stop; |
71
|
|
|
|
|
|
|
} |
72
|
|
|
|
|
|
|
|
73
|
1
|
|
|
|
|
7
|
return $self; |
74
|
|
|
|
|
|
|
} |
75
|
|
|
|
|
|
|
|
76
|
|
|
|
|
|
|
sub _build_tx { |
77
|
936
|
|
|
936
|
|
2242
|
my ($self, $id, $c) = @_; |
78
|
|
|
|
|
|
|
|
79
|
936
|
|
|
|
|
3614
|
my $tx = $self->build_tx->connection($id); |
80
|
936
|
|
|
|
|
2994
|
$tx->res->headers->server('Mojolicious (Perl)'); |
81
|
936
|
|
|
|
|
3140
|
my $handle = $self->ioloop->stream($id)->timeout($self->inactivity_timeout)->handle; |
82
|
936
|
50
|
|
|
|
5822
|
unless ($handle->isa('IO::Socket::UNIX')) { |
83
|
936
|
|
|
|
|
3169
|
$tx->local_address($handle->sockhost)->local_port($handle->sockport); |
84
|
936
|
|
|
|
|
3872
|
$tx->remote_address($handle->peerhost)->remote_port($handle->peerport); |
85
|
|
|
|
|
|
|
} |
86
|
936
|
50
|
|
|
|
3610
|
$tx->req->url->base->scheme('https') if $c->{tls}; |
87
|
|
|
|
|
|
|
|
88
|
936
|
|
|
|
|
3346
|
weaken $self; |
89
|
|
|
|
|
|
|
$tx->on( |
90
|
|
|
|
|
|
|
request => sub { |
91
|
936
|
|
|
936
|
|
1718
|
my $tx = shift; |
92
|
|
|
|
|
|
|
|
93
|
936
|
|
|
|
|
2548
|
my $req = $tx->req; |
94
|
936
|
100
|
|
|
|
2649
|
if (my $error = $req->error) { $self->_trace($id, $error->{message}) } |
|
1
|
|
|
|
|
6
|
|
95
|
|
|
|
|
|
|
|
96
|
|
|
|
|
|
|
# WebSocket |
97
|
936
|
100
|
|
|
|
2681
|
if ($req->is_handshake) { |
98
|
72
|
|
|
|
|
461
|
my $ws = $self->{connections}{$id}{next} = Mojo::Transaction::WebSocket->new(handshake => $tx); |
99
|
72
|
|
|
|
|
327
|
$self->emit(request => server_handshake $ws); |
100
|
|
|
|
|
|
|
} |
101
|
|
|
|
|
|
|
|
102
|
|
|
|
|
|
|
# HTTP |
103
|
864
|
|
|
|
|
3053
|
else { $self->emit(request => $tx) } |
104
|
|
|
|
|
|
|
|
105
|
|
|
|
|
|
|
# Last keep-alive request or corrupted connection |
106
|
936
|
|
|
|
|
2803
|
my $c = $self->{connections}{$id}; |
107
|
936
|
100
|
100
|
|
|
4467
|
$tx->res->headers->connection('close') if ($c->{requests} || 1) >= $self->max_requests || $req->error; |
|
|
|
100
|
|
|
|
|
108
|
|
|
|
|
|
|
|
109
|
936
|
|
|
|
|
6098
|
$tx->on(resume => sub { $self->_write($id) }); |
|
94
|
|
|
|
|
372
|
|
110
|
936
|
|
|
|
|
3320
|
$self->_write($id); |
111
|
|
|
|
|
|
|
} |
112
|
936
|
|
|
|
|
7405
|
); |
113
|
|
|
|
|
|
|
|
114
|
|
|
|
|
|
|
# Kept alive if we have more than one request on the connection |
115
|
936
|
100
|
|
|
|
4642
|
return ++$c->{requests} > 1 ? $tx->kept_alive(1) : $tx; |
116
|
|
|
|
|
|
|
} |
117
|
|
|
|
|
|
|
|
118
|
|
|
|
|
|
|
sub _close { |
119
|
237
|
|
|
237
|
|
611
|
my ($self, $id) = @_; |
120
|
237
|
100
|
|
|
|
895
|
if (my $tx = $self->{connections}{$id}{tx}) { $tx->closed } |
|
68
|
|
|
|
|
219
|
|
121
|
237
|
|
|
|
|
4742
|
delete $self->{connections}{$id}; |
122
|
|
|
|
|
|
|
} |
123
|
|
|
|
|
|
|
|
124
|
4
|
100
|
|
4
|
|
47
|
sub _trace { $_[0]->app->log->trace($_[2]) if $_[0]{connections}{$_[1]}{tx} } |
125
|
|
|
|
|
|
|
|
126
|
|
|
|
|
|
|
sub _finish { |
127
|
1030
|
|
|
1030
|
|
2450
|
my ($self, $id) = @_; |
128
|
|
|
|
|
|
|
|
129
|
|
|
|
|
|
|
# Always remove connection for WebSockets |
130
|
1030
|
|
|
|
|
2382
|
my $c = $self->{connections}{$id}; |
131
|
1030
|
100
|
|
|
|
3072
|
return unless my $tx = $c->{tx}; |
132
|
974
|
100
|
|
|
|
3376
|
return $self->_remove($id) if $tx->is_websocket; |
133
|
|
|
|
|
|
|
|
134
|
|
|
|
|
|
|
# Finish transaction |
135
|
928
|
|
|
|
|
3576
|
delete($c->{tx})->closed; |
136
|
|
|
|
|
|
|
|
137
|
|
|
|
|
|
|
# Upgrade connection to WebSocket |
138
|
928
|
100
|
|
|
|
2957
|
if (my $ws = delete $c->{next}) { |
139
|
|
|
|
|
|
|
|
140
|
|
|
|
|
|
|
# Successful upgrade |
141
|
72
|
100
|
|
|
|
240
|
if ($ws->handshake->res->code == 101) { |
142
|
62
|
|
|
|
|
254
|
$c->{tx} = $ws->established(1); |
143
|
62
|
|
|
|
|
314
|
weaken $self; |
144
|
62
|
|
|
245
|
|
400
|
$ws->on(resume => sub { $self->_write($id) }); |
|
245
|
|
|
|
|
742
|
|
145
|
62
|
|
|
|
|
239
|
$self->_write($id); |
146
|
|
|
|
|
|
|
} |
147
|
|
|
|
|
|
|
|
148
|
|
|
|
|
|
|
# Failed upgrade |
149
|
10
|
|
|
|
|
37
|
else { $ws->closed } |
150
|
|
|
|
|
|
|
} |
151
|
|
|
|
|
|
|
|
152
|
|
|
|
|
|
|
# Close connection if necessary |
153
|
928
|
100
|
100
|
|
|
2583
|
return $self->_remove($id) if $tx->error || !$tx->keep_alive; |
154
|
|
|
|
|
|
|
|
155
|
|
|
|
|
|
|
# Build new transaction for leftovers |
156
|
901
|
100
|
|
|
|
2521
|
if (length(my $leftovers = $tx->req->content->leftovers)) { |
157
|
1
|
|
|
|
|
4
|
$tx = $c->{tx} = $self->_build_tx($id, $c); |
158
|
1
|
|
|
|
|
5
|
$tx->server_read($leftovers); |
159
|
|
|
|
|
|
|
} |
160
|
|
|
|
|
|
|
|
161
|
|
|
|
|
|
|
# Keep-alive connection |
162
|
901
|
100
|
|
|
|
3793
|
$self->ioloop->stream($id)->timeout($self->keep_alive_timeout) unless $c->{tx}; |
163
|
|
|
|
|
|
|
} |
164
|
|
|
|
|
|
|
|
165
|
|
|
|
|
|
|
sub _listen { |
166
|
136
|
|
|
136
|
|
403
|
my ($self, $listen) = @_; |
167
|
|
|
|
|
|
|
|
168
|
136
|
|
|
|
|
697
|
my $url = Mojo::URL->new($listen); |
169
|
136
|
|
|
|
|
498
|
my $proto = $url->protocol; |
170
|
136
|
100
|
100
|
|
|
897
|
croak qq{Invalid listen location "$listen"} unless $proto eq 'http' || $proto eq 'https' || $proto eq 'http+unix'; |
|
|
|
66
|
|
|
|
|
171
|
|
|
|
|
|
|
|
172
|
135
|
|
|
|
|
555
|
my $query = $url->query; |
173
|
135
|
|
|
|
|
616
|
my $options = {backlog => $self->backlog}; |
174
|
135
|
|
|
|
|
619
|
$options->{$_} = $query->param($_) for qw(fd single_accept reuse); |
175
|
135
|
50
|
|
|
|
442
|
if ($proto eq 'http+unix') { $options->{path} = $url->host } |
|
0
|
|
|
|
|
0
|
|
176
|
|
|
|
|
|
|
else { |
177
|
135
|
50
|
|
|
|
477
|
if ((my $host = $url->host) ne '*') { $options->{address} = $host } |
|
135
|
|
|
|
|
401
|
|
178
|
135
|
50
|
|
|
|
444
|
if (my $port = $url->port) { $options->{port} = $port } |
|
0
|
|
|
|
|
0
|
|
179
|
|
|
|
|
|
|
} |
180
|
|
|
|
|
|
|
|
181
|
135
|
|
|
|
|
404
|
$options->{tls_ca} = $query->param('ca'); |
182
|
135
|
|
33
|
|
|
307
|
/^(.*)_(cert|key)$/ and $options->{"tls_$2"}{$1} = $query->param($_) for @{$query->names}; |
|
135
|
|
|
|
|
504
|
|
183
|
135
|
50
|
|
|
|
440
|
if (my $cert = $query->param('cert')) { $options->{tls_cert}{''} = $cert } |
|
0
|
|
|
|
|
0
|
|
184
|
135
|
50
|
|
|
|
448
|
if (my $key = $query->param('key')) { $options->{tls_key}{''} = $key } |
|
0
|
|
|
|
|
0
|
|
185
|
135
|
|
|
|
|
432
|
my ($ciphers, $verify, $version) = ($query->param('ciphers'), $query->param('verify'), $query->param('version')); |
186
|
135
|
50
|
|
|
|
489
|
$options->{tls_options}{SSL_cipher_list} = $ciphers if defined $ciphers; |
187
|
135
|
50
|
|
|
|
394
|
$options->{tls_options}{SSL_verify_mode} = hex $verify if defined $verify; |
188
|
135
|
50
|
|
|
|
381
|
$options->{tls_options}{SSL_version} = $version if defined $version; |
189
|
135
|
|
|
|
|
488
|
my $tls = $options->{tls} = $proto eq 'https'; |
190
|
|
|
|
|
|
|
|
191
|
135
|
|
|
|
|
550
|
weaken $self; |
192
|
135
|
|
|
|
|
423
|
push @{$self->acceptors}, $self->ioloop->server( |
193
|
|
|
|
|
|
|
$options => sub { |
194
|
180
|
|
|
180
|
|
548
|
my ($loop, $stream, $id) = @_; |
195
|
|
|
|
|
|
|
|
196
|
180
|
|
|
|
|
929
|
$self->{connections}{$id} = {tls => $tls}; |
197
|
180
|
|
|
|
|
353
|
warn "-- Accept $id (@{[_peer($stream->handle)]})\n" if DEBUG; |
198
|
180
|
|
|
|
|
761
|
$stream->timeout($self->inactivity_timeout); |
199
|
|
|
|
|
|
|
|
200
|
180
|
50
|
|
|
|
1385
|
$stream->on(close => sub { $self && $self->_close($id) }); |
|
164
|
|
|
|
|
828
|
|
201
|
180
|
0
|
0
|
|
|
1152
|
$stream->on(error => sub { $self && $self->app->log->error(pop) && $self->_close($id) }); |
|
0
|
|
|
|
|
0
|
|
202
|
180
|
|
|
|
|
998
|
$stream->on(read => sub { $self->_read($id => pop) }); |
|
1153
|
|
|
|
|
4189
|
|
203
|
180
|
|
|
|
|
989
|
$stream->on(timeout => sub { $self->_trace($id, 'Inactivity timeout') }); |
|
3
|
|
|
|
|
23
|
|
204
|
|
|
|
|
|
|
} |
205
|
135
|
|
|
|
|
237
|
); |
206
|
|
|
|
|
|
|
|
207
|
134
|
50
|
|
|
|
578
|
return if $self->silent; |
208
|
0
|
|
|
|
|
0
|
$self->app->log->info(qq{Listening at "$url"}); |
209
|
0
|
|
|
|
|
0
|
$query->pairs([]); |
210
|
0
|
0
|
|
|
|
0
|
$url->host('127.0.0.1') if $url->host eq '*'; |
211
|
0
|
0
|
0
|
|
|
0
|
$url->port($self->ports->[-1]) if !$options->{path} && !$url->port; |
212
|
0
|
|
0
|
|
|
0
|
say 'Web application available at ', $options->{path} // $url; |
213
|
|
|
|
|
|
|
} |
214
|
|
|
|
|
|
|
|
215
|
0
|
0
|
|
0
|
|
0
|
sub _peer { $_[0]->isa('IO::Socket::UNIX') ? $_[0]->peerpath : $_[0]->peerhost } |
216
|
|
|
|
|
|
|
|
217
|
|
|
|
|
|
|
sub _read { |
218
|
1153
|
|
|
1153
|
|
3152
|
my ($self, $id, $chunk) = @_; |
219
|
|
|
|
|
|
|
|
220
|
|
|
|
|
|
|
# Make sure we have a transaction |
221
|
1153
|
|
|
|
|
2551
|
my $c = $self->{connections}{$id}; |
222
|
1153
|
|
66
|
|
|
5435
|
my $tx = $c->{tx} ||= $self->_build_tx($id, $c); |
223
|
1153
|
|
|
|
|
1871
|
warn term_escape "-- Server <<< Client (@{[_url($tx)]})\n$chunk\n" if DEBUG; |
224
|
1153
|
|
|
|
|
3978
|
$tx->server_read($chunk); |
225
|
|
|
|
|
|
|
} |
226
|
|
|
|
|
|
|
|
227
|
|
|
|
|
|
|
sub _remove { |
228
|
73
|
|
|
73
|
|
202
|
my ($self, $id) = @_; |
229
|
73
|
|
|
|
|
218
|
$self->ioloop->remove($id); |
230
|
73
|
|
|
|
|
295
|
$self->_close($id); |
231
|
|
|
|
|
|
|
} |
232
|
|
|
|
|
|
|
|
233
|
0
|
|
|
0
|
|
0
|
sub _url { shift->req->url->to_abs } |
234
|
|
|
|
|
|
|
|
235
|
|
|
|
|
|
|
sub _write { |
236
|
2315
|
|
|
2315
|
|
5313
|
my ($self, $id) = @_; |
237
|
|
|
|
|
|
|
|
238
|
|
|
|
|
|
|
# Protect from resume event recursion |
239
|
2315
|
|
|
|
|
5306
|
my $c = $self->{connections}{$id}; |
240
|
2315
|
100
|
100
|
|
|
10758
|
return if !(my $tx = $c->{tx}) || $c->{writing}; |
241
|
2273
|
|
|
|
|
5498
|
local $c->{writing} = 1; |
242
|
2273
|
|
|
|
|
6946
|
my $chunk = $tx->server_write; |
243
|
2273
|
|
|
|
|
3587
|
warn term_escape "-- Server >>> Client (@{[_url($tx)]})\n$chunk\n" if DEBUG; |
244
|
2273
|
100
|
|
|
|
6659
|
my $next = $tx->is_finished ? '_finish' : length $chunk ? '_write' : undef; |
|
|
100
|
|
|
|
|
|
245
|
2273
|
100
|
|
|
|
5414
|
return $self->ioloop->stream($id)->write($chunk) unless $next; |
246
|
2034
|
|
|
|
|
6776
|
weaken $self; |
247
|
2034
|
|
|
2008
|
|
5360
|
$self->ioloop->stream($id)->write($chunk => sub { $self->$next($id) }); |
|
2008
|
|
|
|
|
7722
|
|
248
|
|
|
|
|
|
|
} |
249
|
|
|
|
|
|
|
|
250
|
|
|
|
|
|
|
1; |
251
|
|
|
|
|
|
|
|
252
|
|
|
|
|
|
|
=encoding utf8 |
253
|
|
|
|
|
|
|
|
254
|
|
|
|
|
|
|
=head1 NAME |
255
|
|
|
|
|
|
|
|
256
|
|
|
|
|
|
|
Mojo::Server::Daemon - Non-blocking I/O HTTP and WebSocket server |
257
|
|
|
|
|
|
|
|
258
|
|
|
|
|
|
|
=head1 SYNOPSIS |
259
|
|
|
|
|
|
|
|
260
|
|
|
|
|
|
|
use Mojo::Server::Daemon; |
261
|
|
|
|
|
|
|
|
262
|
|
|
|
|
|
|
my $daemon = Mojo::Server::Daemon->new(listen => ['http://*:8080']); |
263
|
|
|
|
|
|
|
$daemon->unsubscribe('request')->on(request => sub ($daemon, $tx) { |
264
|
|
|
|
|
|
|
|
265
|
|
|
|
|
|
|
# Request |
266
|
|
|
|
|
|
|
my $method = $tx->req->method; |
267
|
|
|
|
|
|
|
my $path = $tx->req->url->path; |
268
|
|
|
|
|
|
|
|
269
|
|
|
|
|
|
|
# Response |
270
|
|
|
|
|
|
|
$tx->res->code(200); |
271
|
|
|
|
|
|
|
$tx->res->headers->content_type('text/plain'); |
272
|
|
|
|
|
|
|
$tx->res->body("$method request for $path!"); |
273
|
|
|
|
|
|
|
|
274
|
|
|
|
|
|
|
# Resume transaction |
275
|
|
|
|
|
|
|
$tx->resume; |
276
|
|
|
|
|
|
|
}); |
277
|
|
|
|
|
|
|
$daemon->run; |
278
|
|
|
|
|
|
|
|
279
|
|
|
|
|
|
|
=head1 DESCRIPTION |
280
|
|
|
|
|
|
|
|
281
|
|
|
|
|
|
|
L is a full featured, highly portable non-blocking I/O HTTP and WebSocket server, with IPv6, TLS, |
282
|
|
|
|
|
|
|
SNI, Comet (long polling), keep-alive and multiple event loop support. |
283
|
|
|
|
|
|
|
|
284
|
|
|
|
|
|
|
For better scalability (epoll, kqueue) and to provide non-blocking name resolution, SOCKS5 as well as TLS support, the |
285
|
|
|
|
|
|
|
optional modules L (4.32+), L (0.15+), L (0.64+) and L |
286
|
|
|
|
|
|
|
(2.009+) will be used automatically if possible. Individual features can also be disabled with the C, |
287
|
|
|
|
|
|
|
C and C environment variables. |
288
|
|
|
|
|
|
|
|
289
|
|
|
|
|
|
|
See L for more. |
290
|
|
|
|
|
|
|
|
291
|
|
|
|
|
|
|
=head1 SIGNALS |
292
|
|
|
|
|
|
|
|
293
|
|
|
|
|
|
|
The L process can be controlled at runtime with the following signals. |
294
|
|
|
|
|
|
|
|
295
|
|
|
|
|
|
|
=head2 INT, TERM |
296
|
|
|
|
|
|
|
|
297
|
|
|
|
|
|
|
Shut down server immediately. |
298
|
|
|
|
|
|
|
|
299
|
|
|
|
|
|
|
=head1 EVENTS |
300
|
|
|
|
|
|
|
|
301
|
|
|
|
|
|
|
L inherits all events from L. |
302
|
|
|
|
|
|
|
|
303
|
|
|
|
|
|
|
=head1 ATTRIBUTES |
304
|
|
|
|
|
|
|
|
305
|
|
|
|
|
|
|
L inherits all attributes from L and implements the following new ones. |
306
|
|
|
|
|
|
|
|
307
|
|
|
|
|
|
|
=head2 acceptors |
308
|
|
|
|
|
|
|
|
309
|
|
|
|
|
|
|
my $acceptors = $daemon->acceptors; |
310
|
|
|
|
|
|
|
$daemon = $daemon->acceptors(['6be0c140ef00a389c5d039536b56d139']); |
311
|
|
|
|
|
|
|
|
312
|
|
|
|
|
|
|
Active acceptor ids. |
313
|
|
|
|
|
|
|
|
314
|
|
|
|
|
|
|
# Check port |
315
|
|
|
|
|
|
|
mu $port = $daemon->ioloop->acceptor($daemon->acceptors->[0])->port; |
316
|
|
|
|
|
|
|
|
317
|
|
|
|
|
|
|
=head2 backlog |
318
|
|
|
|
|
|
|
|
319
|
|
|
|
|
|
|
my $backlog = $daemon->backlog; |
320
|
|
|
|
|
|
|
$daemon = $daemon->backlog(128); |
321
|
|
|
|
|
|
|
|
322
|
|
|
|
|
|
|
Listen backlog size, defaults to C. |
323
|
|
|
|
|
|
|
|
324
|
|
|
|
|
|
|
=head2 inactivity_timeout |
325
|
|
|
|
|
|
|
|
326
|
|
|
|
|
|
|
my $timeout = $daemon->inactivity_timeout; |
327
|
|
|
|
|
|
|
$daemon = $daemon->inactivity_timeout(5); |
328
|
|
|
|
|
|
|
|
329
|
|
|
|
|
|
|
Maximum amount of time in seconds a connection with an active request can be inactive before getting closed, defaults |
330
|
|
|
|
|
|
|
to the value of the C environment variable or C<30>. Setting the value to C<0> will allow |
331
|
|
|
|
|
|
|
connections to be inactive indefinitely. |
332
|
|
|
|
|
|
|
|
333
|
|
|
|
|
|
|
=head2 ioloop |
334
|
|
|
|
|
|
|
|
335
|
|
|
|
|
|
|
my $loop = $daemon->ioloop; |
336
|
|
|
|
|
|
|
$daemon = $daemon->ioloop(Mojo::IOLoop->new); |
337
|
|
|
|
|
|
|
|
338
|
|
|
|
|
|
|
Event loop object to use for I/O operations, defaults to the global L singleton. |
339
|
|
|
|
|
|
|
|
340
|
|
|
|
|
|
|
=head2 keep_alive_timeout |
341
|
|
|
|
|
|
|
|
342
|
|
|
|
|
|
|
my $timeout = $daemon->keep_alive_timeout; |
343
|
|
|
|
|
|
|
$daemon = $daemon->keep_alive_timeout(10); |
344
|
|
|
|
|
|
|
|
345
|
|
|
|
|
|
|
Maximum amount of time in seconds a connection without an active request can be inactive before getting closed, |
346
|
|
|
|
|
|
|
defaults to the value of the C environment variable or C<5>. Setting the value to C<0> will |
347
|
|
|
|
|
|
|
allow connections to be inactive indefinitely. |
348
|
|
|
|
|
|
|
|
349
|
|
|
|
|
|
|
=head2 listen |
350
|
|
|
|
|
|
|
|
351
|
|
|
|
|
|
|
my $listen = $daemon->listen; |
352
|
|
|
|
|
|
|
$daemon = $daemon->listen(['https://127.0.0.1:8080']); |
353
|
|
|
|
|
|
|
|
354
|
|
|
|
|
|
|
Array reference with one or more locations to listen on, defaults to the value of the C environment |
355
|
|
|
|
|
|
|
variable or C (shortcut for C). |
356
|
|
|
|
|
|
|
|
357
|
|
|
|
|
|
|
# Listen on all IPv4 interfaces |
358
|
|
|
|
|
|
|
$daemon->listen(['http://*:3000']); |
359
|
|
|
|
|
|
|
|
360
|
|
|
|
|
|
|
# Listen on all IPv4 and IPv6 interfaces |
361
|
|
|
|
|
|
|
$daemon->listen(['http://[::]:3000']); |
362
|
|
|
|
|
|
|
|
363
|
|
|
|
|
|
|
# Listen on IPv6 interface |
364
|
|
|
|
|
|
|
$daemon->listen(['http://[::1]:4000']); |
365
|
|
|
|
|
|
|
|
366
|
|
|
|
|
|
|
# Listen on IPv4 and IPv6 interfaces |
367
|
|
|
|
|
|
|
$daemon->listen(['http://127.0.0.1:3000', 'http://[::1]:3000']); |
368
|
|
|
|
|
|
|
|
369
|
|
|
|
|
|
|
# Listen on UNIX domain socket "/tmp/myapp.sock" (percent encoded slash) |
370
|
|
|
|
|
|
|
$daemon->listen(['http+unix://%2Ftmp%2Fmyapp.sock']); |
371
|
|
|
|
|
|
|
|
372
|
|
|
|
|
|
|
# File descriptor, as used by systemd |
373
|
|
|
|
|
|
|
$daemon->listen(['http://127.0.0.1?fd=3']); |
374
|
|
|
|
|
|
|
|
375
|
|
|
|
|
|
|
# Allow multiple servers to use the same port (SO_REUSEPORT) |
376
|
|
|
|
|
|
|
$daemon->listen(['http://*:8080?reuse=1']); |
377
|
|
|
|
|
|
|
|
378
|
|
|
|
|
|
|
# Listen on two ports with HTTP and HTTPS at the same time |
379
|
|
|
|
|
|
|
$daemon->listen(['http://*:3000', 'https://*:4000']); |
380
|
|
|
|
|
|
|
|
381
|
|
|
|
|
|
|
# Use a custom certificate and key |
382
|
|
|
|
|
|
|
$daemon->listen(['https://*:3000?cert=/x/server.crt&key=/y/server.key']); |
383
|
|
|
|
|
|
|
|
384
|
|
|
|
|
|
|
# Domain specific certificates and keys (SNI) |
385
|
|
|
|
|
|
|
$daemon->listen( |
386
|
|
|
|
|
|
|
['https://*:3000?example.com_cert=/x/my.crt&example.com_key=/y/my.key']); |
387
|
|
|
|
|
|
|
|
388
|
|
|
|
|
|
|
# Or even a custom certificate authority |
389
|
|
|
|
|
|
|
$daemon->listen( |
390
|
|
|
|
|
|
|
['https://*:3000?cert=/x/server.crt&key=/y/server.key&ca=/z/ca.crt']); |
391
|
|
|
|
|
|
|
|
392
|
|
|
|
|
|
|
These parameters are currently available: |
393
|
|
|
|
|
|
|
|
394
|
|
|
|
|
|
|
=over 2 |
395
|
|
|
|
|
|
|
|
396
|
|
|
|
|
|
|
=item ca |
397
|
|
|
|
|
|
|
|
398
|
|
|
|
|
|
|
ca=/etc/tls/ca.crt |
399
|
|
|
|
|
|
|
|
400
|
|
|
|
|
|
|
Path to TLS certificate authority file used to verify the peer certificate. |
401
|
|
|
|
|
|
|
|
402
|
|
|
|
|
|
|
=item cert |
403
|
|
|
|
|
|
|
|
404
|
|
|
|
|
|
|
cert=/etc/tls/server.crt |
405
|
|
|
|
|
|
|
mojolicious.org_cert=/etc/tls/mojo.crt |
406
|
|
|
|
|
|
|
|
407
|
|
|
|
|
|
|
Path to the TLS cert file, defaults to a built-in test certificate. |
408
|
|
|
|
|
|
|
|
409
|
|
|
|
|
|
|
=item ciphers |
410
|
|
|
|
|
|
|
|
411
|
|
|
|
|
|
|
ciphers=AES128-GCM-SHA256:RC4:HIGH:!MD5:!aNULL:!EDH |
412
|
|
|
|
|
|
|
|
413
|
|
|
|
|
|
|
TLS cipher specification string. For more information about the format see |
414
|
|
|
|
|
|
|
L. |
415
|
|
|
|
|
|
|
|
416
|
|
|
|
|
|
|
=item fd |
417
|
|
|
|
|
|
|
|
418
|
|
|
|
|
|
|
fd=3 |
419
|
|
|
|
|
|
|
|
420
|
|
|
|
|
|
|
File descriptor with an already prepared listen socket. |
421
|
|
|
|
|
|
|
|
422
|
|
|
|
|
|
|
=item key |
423
|
|
|
|
|
|
|
|
424
|
|
|
|
|
|
|
key=/etc/tls/server.key |
425
|
|
|
|
|
|
|
mojolicious.org_key=/etc/tls/mojo.key |
426
|
|
|
|
|
|
|
|
427
|
|
|
|
|
|
|
Path to the TLS key file, defaults to a built-in test key. |
428
|
|
|
|
|
|
|
|
429
|
|
|
|
|
|
|
=item reuse |
430
|
|
|
|
|
|
|
|
431
|
|
|
|
|
|
|
reuse=1 |
432
|
|
|
|
|
|
|
|
433
|
|
|
|
|
|
|
Allow multiple servers to use the same port with the C socket option. |
434
|
|
|
|
|
|
|
|
435
|
|
|
|
|
|
|
=item single_accept |
436
|
|
|
|
|
|
|
|
437
|
|
|
|
|
|
|
single_accept=1 |
438
|
|
|
|
|
|
|
|
439
|
|
|
|
|
|
|
Only accept one connection at a time. |
440
|
|
|
|
|
|
|
|
441
|
|
|
|
|
|
|
=item verify |
442
|
|
|
|
|
|
|
|
443
|
|
|
|
|
|
|
verify=0x00 |
444
|
|
|
|
|
|
|
|
445
|
|
|
|
|
|
|
TLS verification mode. |
446
|
|
|
|
|
|
|
|
447
|
|
|
|
|
|
|
=item version |
448
|
|
|
|
|
|
|
|
449
|
|
|
|
|
|
|
version=TLSv1_2 |
450
|
|
|
|
|
|
|
|
451
|
|
|
|
|
|
|
TLS protocol version. |
452
|
|
|
|
|
|
|
|
453
|
|
|
|
|
|
|
=back |
454
|
|
|
|
|
|
|
|
455
|
|
|
|
|
|
|
=head2 max_clients |
456
|
|
|
|
|
|
|
|
457
|
|
|
|
|
|
|
my $max = $daemon->max_clients; |
458
|
|
|
|
|
|
|
$daemon = $daemon->max_clients(100); |
459
|
|
|
|
|
|
|
|
460
|
|
|
|
|
|
|
Maximum number of accepted connections this server is allowed to handle concurrently, before stopping to accept new |
461
|
|
|
|
|
|
|
incoming connections, passed along to L. |
462
|
|
|
|
|
|
|
|
463
|
|
|
|
|
|
|
=head2 max_requests |
464
|
|
|
|
|
|
|
|
465
|
|
|
|
|
|
|
my $max = $daemon->max_requests; |
466
|
|
|
|
|
|
|
$daemon = $daemon->max_requests(250); |
467
|
|
|
|
|
|
|
|
468
|
|
|
|
|
|
|
Maximum number of keep-alive requests per connection, defaults to C<100>. |
469
|
|
|
|
|
|
|
|
470
|
|
|
|
|
|
|
=head2 silent |
471
|
|
|
|
|
|
|
|
472
|
|
|
|
|
|
|
my $bool = $daemon->silent; |
473
|
|
|
|
|
|
|
$daemon = $daemon->silent($bool); |
474
|
|
|
|
|
|
|
|
475
|
|
|
|
|
|
|
Disable console messages. |
476
|
|
|
|
|
|
|
|
477
|
|
|
|
|
|
|
=head1 METHODS |
478
|
|
|
|
|
|
|
|
479
|
|
|
|
|
|
|
L inherits all methods from L and implements the following new ones. |
480
|
|
|
|
|
|
|
|
481
|
|
|
|
|
|
|
=head2 ports |
482
|
|
|
|
|
|
|
|
483
|
|
|
|
|
|
|
my $ports = $daemon->ports; |
484
|
|
|
|
|
|
|
|
485
|
|
|
|
|
|
|
Get all ports this server is currently listening on. |
486
|
|
|
|
|
|
|
|
487
|
|
|
|
|
|
|
# All ports |
488
|
|
|
|
|
|
|
say for @{$daemon->ports}; |
489
|
|
|
|
|
|
|
|
490
|
|
|
|
|
|
|
=head2 run |
491
|
|
|
|
|
|
|
|
492
|
|
|
|
|
|
|
$daemon->run; |
493
|
|
|
|
|
|
|
|
494
|
|
|
|
|
|
|
Run server and wait for L"SIGNALS">. |
495
|
|
|
|
|
|
|
|
496
|
|
|
|
|
|
|
=head2 start |
497
|
|
|
|
|
|
|
|
498
|
|
|
|
|
|
|
$daemon = $daemon->start; |
499
|
|
|
|
|
|
|
|
500
|
|
|
|
|
|
|
Start or resume accepting connections through L"ioloop">. |
501
|
|
|
|
|
|
|
|
502
|
|
|
|
|
|
|
# Listen on random port |
503
|
|
|
|
|
|
|
my $port = $daemon->listen(['http://127.0.0.1'])->start->ports->[0]; |
504
|
|
|
|
|
|
|
|
505
|
|
|
|
|
|
|
# Run multiple web servers concurrently |
506
|
|
|
|
|
|
|
my $daemon1 = Mojo::Server::Daemon->new(listen => ['http://*:3000'])->start; |
507
|
|
|
|
|
|
|
my $daemon2 = Mojo::Server::Daemon->new(listen => ['http://*:4000'])->start; |
508
|
|
|
|
|
|
|
Mojo::IOLoop->start unless Mojo::IOLoop->is_running; |
509
|
|
|
|
|
|
|
|
510
|
|
|
|
|
|
|
=head2 stop |
511
|
|
|
|
|
|
|
|
512
|
|
|
|
|
|
|
$daemon = $daemon->stop; |
513
|
|
|
|
|
|
|
|
514
|
|
|
|
|
|
|
Stop accepting connections through L"ioloop">. |
515
|
|
|
|
|
|
|
|
516
|
|
|
|
|
|
|
=head1 DEBUGGING |
517
|
|
|
|
|
|
|
|
518
|
|
|
|
|
|
|
You can set the C environment variable to get some advanced diagnostics information printed to |
519
|
|
|
|
|
|
|
C. |
520
|
|
|
|
|
|
|
|
521
|
|
|
|
|
|
|
MOJO_SERVER_DEBUG=1 |
522
|
|
|
|
|
|
|
|
523
|
|
|
|
|
|
|
=head1 SEE ALSO |
524
|
|
|
|
|
|
|
|
525
|
|
|
|
|
|
|
L, L, L. |
526
|
|
|
|
|
|
|
|
527
|
|
|
|
|
|
|
=cut |