line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package Plack::Middleware::Proxy::Connect; |
2
|
1
|
|
|
1
|
|
141372
|
use strict; |
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
34
|
|
3
|
1
|
|
|
1
|
|
6
|
use warnings; |
|
1
|
|
|
|
|
3
|
|
|
1
|
|
|
|
|
27
|
|
4
|
1
|
|
|
1
|
|
5
|
use parent 'Plack::Middleware'; |
|
1
|
|
|
|
|
2
|
|
|
1
|
|
|
|
|
6
|
|
5
|
|
|
|
|
|
|
|
6
|
1
|
|
|
1
|
|
5011
|
use AnyEvent::Socket; |
|
1
|
|
|
|
|
49427
|
|
|
1
|
|
|
|
|
138
|
|
7
|
1
|
|
|
1
|
|
1272
|
use AnyEvent::Handle; |
|
1
|
|
|
|
|
7855
|
|
|
1
|
|
|
|
|
543
|
|
8
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
our $VERSION = '0.01'; |
10
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
sub call { |
12
|
0
|
|
|
0
|
1
|
|
my($self, $env) = @_; |
13
|
0
|
0
|
|
|
|
|
return $self->app->( $env ) unless $env->{ REQUEST_METHOD } eq 'CONNECT'; |
14
|
|
|
|
|
|
|
|
15
|
0
|
0
|
|
|
|
|
my $client_fh = $env->{'psgix.io'} |
16
|
|
|
|
|
|
|
or return [ 501, [], ['Not implemented CONNECT method']]; |
17
|
0
|
|
|
|
|
|
my ( $host, $port ) = |
18
|
|
|
|
|
|
|
( $env->{REQUEST_URI} =~ m{^(?:.+\@)?(.+?)(?::(\d+))?$} ); |
19
|
|
|
|
|
|
|
|
20
|
|
|
|
|
|
|
sub { |
21
|
0
|
|
|
0
|
|
|
my $respond = shift; |
22
|
|
|
|
|
|
|
|
23
|
|
|
|
|
|
|
# Run the loop by myself when psgi.nonblocking is turend off. |
24
|
0
|
0
|
|
|
|
|
my $cv = $env->{'psgi.nonblocking'} ? undef : AE::cv; |
25
|
|
|
|
|
|
|
|
26
|
|
|
|
|
|
|
tcp_connect $host, $port, sub { |
27
|
0
|
|
|
|
|
|
my ( $origin_fh ) = @_; |
28
|
0
|
0
|
|
|
|
|
unless( $origin_fh ){ |
29
|
0
|
|
|
|
|
|
$respond->( [ 502, [], ['Bad Gateway'] ] ); |
30
|
0
|
0
|
|
|
|
|
$cv->send if $cv; |
31
|
0
|
|
|
|
|
|
return; |
32
|
|
|
|
|
|
|
} |
33
|
|
|
|
|
|
|
|
34
|
0
|
|
|
|
|
|
my $writer = $respond->( [ 200, [] ] ); |
35
|
|
|
|
|
|
|
|
36
|
0
|
|
|
|
|
|
my $client_hdl = AnyEvent::Handle->new( fh => $client_fh ); |
37
|
0
|
|
|
|
|
|
my $origin_hdl = AnyEvent::Handle->new( fh => $origin_fh ); |
38
|
|
|
|
|
|
|
|
39
|
|
|
|
|
|
|
# Join 2 handles by a tunnel |
40
|
|
|
|
|
|
|
$client_hdl->on_read(sub { |
41
|
0
|
|
|
|
|
|
my $hdl = shift; |
42
|
0
|
|
|
|
|
|
my $rbuf = delete $hdl->{rbuf}; |
43
|
0
|
|
|
|
|
|
$origin_hdl->push_write( $rbuf ); |
44
|
0
|
|
|
|
|
|
} ); |
45
|
|
|
|
|
|
|
$client_hdl->on_error( sub { |
46
|
0
|
|
|
|
|
|
my ( $hdl, $fatal, $message ) = @_; |
47
|
0
|
0
|
|
|
|
|
$! and warn "error($fatal): $message\n"; |
48
|
0
|
|
|
|
|
|
$origin_hdl->push_shutdown; |
49
|
|
|
|
|
|
|
# Finish this request. |
50
|
0
|
|
|
|
|
|
$writer->close; |
51
|
0
|
0
|
|
|
|
|
$cv->send if $cv; |
52
|
|
|
|
|
|
|
# Use $client_hdl to keep the handle by a cyclical reference. |
53
|
0
|
|
|
|
|
|
$client_hdl->destroy; |
54
|
0
|
|
|
|
|
|
} ); |
55
|
|
|
|
|
|
|
|
56
|
|
|
|
|
|
|
$origin_hdl->on_read(sub { |
57
|
0
|
|
|
|
|
|
my $hdl = shift; |
58
|
0
|
|
|
|
|
|
my $rbuf = delete $hdl->{rbuf}; |
59
|
0
|
|
|
|
|
|
$client_hdl->push_write( $rbuf ); |
60
|
0
|
|
|
|
|
|
} ); |
61
|
|
|
|
|
|
|
$origin_hdl->on_error( sub { |
62
|
0
|
|
|
|
|
|
my ( $hdl, $fatal, $message ) = @_; |
63
|
0
|
0
|
|
|
|
|
$! and warn "error($fatal): $message\n"; |
64
|
0
|
|
|
|
|
|
$client_hdl->push_shutdown; |
65
|
|
|
|
|
|
|
# Use $origin_hdl to keep the handle by a cyclical reference. |
66
|
0
|
|
|
|
|
|
$origin_hdl->destroy; |
67
|
0
|
|
|
|
|
|
} ); |
68
|
0
|
|
|
|
|
|
}; |
69
|
|
|
|
|
|
|
|
70
|
0
|
0
|
|
|
|
|
$cv->recv if $cv; |
71
|
0
|
|
|
|
|
|
}; |
72
|
|
|
|
|
|
|
} |
73
|
|
|
|
|
|
|
|
74
|
|
|
|
|
|
|
1; |
75
|
|
|
|
|
|
|
|
76
|
|
|
|
|
|
|
__END__ |