Last active
December 26, 2015 04:09
-
-
Save brianmed/7091198 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package Mojo::UserAgent::Proxy; | |
| use Mojo::Base -base; | |
| has [qw(http https no)]; | |
| sub detect { | |
| my $self = shift; | |
| $self->http($ENV{HTTP_PROXY} || $ENV{http_proxy}); | |
| $self->https($ENV{HTTPS_PROXY} || $ENV{https_proxy}); | |
| return $self->no([split /,/, $ENV{NO_PROXY} || $ENV{no_proxy} || '']); | |
| } | |
| # sub _start { | |
| # ... | |
| # $self->proxy->inject($tx); | |
| # ... | |
| # } | |
| sub inject { | |
| my ($self, $tx) = @_; | |
| $self->detect if $ENV{MOJO_PROXY}; | |
| my $proto = $url->protocol; | |
| if ($self->need_proxy($url->host)) { | |
| # HTTP proxy | |
| my $http = $self->http_proxy; | |
| $req->proxy($http) if $http && !defined $req->proxy && $proto eq 'http'; | |
| # HTTPS proxy | |
| my $https = $self->https_proxy; | |
| $req->proxy($https) if $https && !defined $req->proxy && $proto eq 'https'; | |
| } | |
| } | |
| sub is_needed { | |
| !first { $_[1] =~ /\Q$_\E$/ } @{$_[0]->no_proxy || []}; | |
| } | |
| # $self->proxy->config($tx) | |
| # sub _connect_proxy { | |
| # my ($self, $old, $cb) = @_; | |
| # | |
| # # Start CONNECT request | |
| # return undef unless my $new = $self->proxy->connect($old); | |
| # return $self->_start($new => $self->proxy->start); | |
| # } | |
| sub connect { | |
| my ($self, $old) = @_; | |
| # Already a CONNECT request | |
| my $req = $old->req; | |
| return undef if uc $req->method eq 'CONNECT'; | |
| # No proxy | |
| return undef unless my $proxy = $req->proxy; | |
| # WebSocket and/or HTTPS | |
| my $url = $req->url; | |
| my $upgrade = lc($req->headers->upgrade // ''); | |
| return undef unless $upgrade eq 'websocket' || $url->protocol eq 'https'; | |
| # CONNECT request | |
| my $new = $self->tx(CONNECT => $url->clone->userinfo(undef)); | |
| $new->req->proxy($proxy); | |
| return $new; | |
| } | |
| sub start { | |
| my ($self, $tx) = @_; | |
| # CONNECT failed (connection needs to be kept alive) | |
| unless ($tx->keep_alive && $tx->res->is_status_class(200)) { | |
| $old->req->error('Proxy connection failed'); | |
| return $self->$cb($old); | |
| } | |
| # Prevent proxy reassignment and start real transaction | |
| $old->req->proxy(0); | |
| my $id = $tx->connection; | |
| return $self->_start($old->connection($id), $cb) | |
| unless $tx->req->url->protocol eq 'https'; | |
| # TLS upgrade | |
| my $loop = $self->_loop; | |
| my $handle = $loop->stream($id)->steal_handle; | |
| my $c = delete $self->{connections}{$id}; | |
| $loop->remove($id); | |
| weaken $self; | |
| $id = $self->_connect($self->transactor->endpoint($old), | |
| $handle, sub { $self->_start($old->connection($id), $cb) }); | |
| $self->{connections}{$id} = $c; | |
| } | |
| 1; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment