Skip to content

Commit

Permalink
added protocol method to Mojo::URL
Browse files Browse the repository at this point in the history
  • Loading branch information
kraih committed Nov 24, 2012
1 parent 724025e commit b473b78
Show file tree
Hide file tree
Showing 10 changed files with 86 additions and 59 deletions.
2 changes: 2 additions & 0 deletions Changes
@@ -1,10 +1,12 @@

3.61 2012-11-25
- Added protocol method to Mojo::URL.
- Added charset attribute to Mojo::Path.
- Improved support for relative redirects in Mojo::UserAgent::Transactor.
- Improved documentation.
- Improved tests.
- Fixed clone bug in Mojo::Parameters.
- Fixed case sensitivity bugs in Mojo::UserAgent::Transactor.

3.60 2012-11-22
- Added unexpected event to Mojo::Transaction::HTTP.
Expand Down
8 changes: 4 additions & 4 deletions lib/Mojo/Message/Request.pm
Expand Up @@ -113,16 +113,16 @@ sub get_start_line_chunk {
# CONNECT
my $method = uc $self->method;
if ($method eq 'CONNECT') {
my $port = $url->port || ($url->scheme eq 'https' ? '443' : '80');
my $port = $url->port || ($url->protocol eq 'https' ? '443' : '80');
$path = $url->host . ":$port";
}

# Proxy
elsif ($self->proxy) {
my $clone = $url = $url->clone->userinfo(undef);
my $upgrade = lc($self->headers->upgrade || '');
my $scheme = $url->scheme || '';
$path = $clone unless $upgrade eq 'websocket' || $scheme eq 'https';
$path = $clone
unless $upgrade eq 'websocket' || $url->protocol eq 'https';
}

$self->{start_buffer} = "$method $path HTTP/@{[$self->version]}\x0d\x0a";
Expand All @@ -137,7 +137,7 @@ sub get_start_line_chunk {

sub is_secure {
my $url = shift->url;
return ($url->scheme || $url->base->scheme // '') eq 'https';
return ($url->protocol || $url->base->protocol) eq 'https';
}

sub is_xhr {
Expand Down
2 changes: 1 addition & 1 deletion lib/Mojo/Server/Daemon.pm
Expand Up @@ -163,7 +163,7 @@ sub _listen {
my $verify = $query->param('verify');
$options->{tls_verify} = hex $verify if defined $verify;
delete $options->{address} if $options->{address} eq '*';
my $tls = $options->{tls} = $url->scheme eq 'https' ? 1 : undef;
my $tls = $options->{tls} = $url->protocol eq 'https' ? 1 : undef;

# Listen
weaken $self;
Expand Down
11 changes: 11 additions & 0 deletions lib/Mojo/URL.pm
Expand Up @@ -103,6 +103,8 @@ sub path {
return $self;
}

sub protocol { lc(shift->scheme // '') }

sub query {
my $self = shift;

Expand Down Expand Up @@ -299,6 +301,15 @@ Host part of this URL.
Port part of this URL.
=head2 C<protocol>
my $proto = $url->protocol;
Normalized version of C<scheme>.
# "http"
Mojo::URL->new('HtTp://mojolicio.us')->protocol;
=head2 C<scheme>
my $scheme = $url->scheme;
Expand Down
39 changes: 19 additions & 20 deletions lib/Mojo/UserAgent.pm
Expand Up @@ -59,7 +59,7 @@ sub app {
sub app_url {
my $self = shift;
$self->_server(@_);
return Mojo::URL->new("$self->{scheme}://localhost:$self->{port}/");
return Mojo::URL->new("$self->{proto}://localhost:$self->{port}/");
}

sub build_form_tx { shift->transactor->form(@_) }
Expand Down Expand Up @@ -177,7 +177,7 @@ sub _cleanup {
}

sub _connect {
my ($self, $scheme, $host, $port, $handle, $cb) = @_;
my ($self, $proto, $host, $port, $handle, $cb) = @_;

# Open connection
weaken $self;
Expand All @@ -188,7 +188,7 @@ sub _connect {
local_address => $self->local_address,
port => $port,
timeout => $self->connect_timeout,
tls => $scheme eq 'https' ? 1 : 0,
tls => $proto eq 'https' ? 1 : 0,
tls_ca => $self->ca,
tls_cert => $self->cert,
tls_key => $self->key,
Expand Down Expand Up @@ -229,7 +229,7 @@ sub _connect_proxy {

# Start real transaction
return $self->_start($old->connection($tx->connection), $cb)
unless $tx->req->url->scheme eq 'https';
unless $tx->req->url->protocol eq 'https';

# TLS upgrade
return unless my $id = $tx->connection;
Expand Down Expand Up @@ -268,10 +268,10 @@ sub _connection {

# Reuse connection
my $id = $tx->connection;
my ($scheme, $host, $port) = $self->transactor->endpoint($tx);
$id ||= $self->_cache("$scheme:$host:$port");
my ($proto, $host, $port) = $self->transactor->endpoint($tx);
$id ||= $self->_cache("$proto:$host:$port");
if ($id && !ref $id) {
warn "-- Reusing connection ($scheme:$host:$port)\n" if DEBUG;
warn "-- Reusing connection ($proto:$host:$port)\n" if DEBUG;
$self->{connections}{$id} = {cb => $cb, tx => $tx};
$tx->kept_alive(1) unless $tx->connection;
$self->_connected($id);
Expand All @@ -283,11 +283,11 @@ sub _connection {
if $tx->req->method ne 'CONNECT' && $self->_connect_proxy($tx, $cb);

# Connect
warn "-- Connect ($scheme:$host:$port)\n" if DEBUG;
($scheme, $host, $port) = $self->transactor->peer($tx);
warn "-- Connect ($proto:$host:$port)\n" if DEBUG;
($proto, $host, $port) = $self->transactor->peer($tx);
weaken $self;
$id = $self->_connect(
($scheme, $host, $port, $id) => sub { $self->_connected($id) });
($proto, $host, $port, $id) => sub { $self->_connected($id) });
$self->{connections}{$id} = {cb => $cb, tx => $tx};

return $id;
Expand Down Expand Up @@ -411,20 +411,20 @@ sub _redirect {
}

sub _server {
my ($self, $scheme) = @_;
my ($self, $proto) = @_;

# Reuse server
return $self->{server} if $self->{server} && !$scheme;
return $self->{server} if $self->{server} && !$proto;

# Start test server
my $loop = $self->_loop;
my $server = $self->{server}
= Mojo::Server::Daemon->new(ioloop => $loop, silent => 1);
my $port = $self->{port} ||= $loop->generate_port;
die "Couldn't find a free TCP port for testing.\n" unless $port;
$self->{scheme} = $scheme ||= 'http';
$server->listen(["$scheme://127.0.0.1:$port"])->start;
warn "-- Test server started ($scheme://127.0.0.1:$port)\n" if DEBUG;
$self->{proto} = $proto ||= 'http';
$server->listen(["$proto://127.0.0.1:$port"])->start;
warn "-- Test server started ($proto://127.0.0.1:$port)\n" if DEBUG;
return $server;
}

Expand All @@ -441,18 +441,17 @@ sub _start {

# Proxy
$self->detect_proxy if $ENV{MOJO_PROXY};
my $url = $req->url;
my $scheme = $url->scheme || '';
my $url = $req->url;
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 && $scheme eq 'http';
$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 && $scheme eq 'https';
$req->proxy($https) if $https && !defined $req->proxy && $proto eq 'https';
}

# We identify ourselves and accept gzip compression
Expand Down
2 changes: 1 addition & 1 deletion lib/Mojo/UserAgent/CookieJar.pm
Expand Up @@ -67,7 +67,7 @@ sub find {
push @$new, $cookie;

# Taste cookie
next if $cookie->secure && $url->scheme ne 'https';
next if $cookie->secure && $url->protocol ne 'https';
next unless $path =~ /^\Q@{[$cookie->path]}/;
my $name = $cookie->name;
my $value = $cookie->value;
Expand Down
45 changes: 22 additions & 23 deletions lib/Mojo/UserAgent/Transactor.pm
Expand Up @@ -17,17 +17,17 @@ sub endpoint {
my ($self, $tx) = @_;

# Basic endpoint
my $req = $tx->req;
my $url = $req->url;
my $scheme = $url->scheme || 'http';
my $host = $url->ihost;
my $port = $url->port || ($scheme eq 'https' ? 443 : 80);
my $req = $tx->req;
my $url = $req->url;
my $proto = $url->protocol || 'http';
my $host = $url->ihost;
my $port = $url->port || ($proto eq 'https' ? 443 : 80);

# Proxy for normal HTTP requests
return $self->_proxy($tx, $scheme, $host, $port)
if $scheme eq 'http' && lc($req->headers->upgrade || '') ne 'websocket';
return $self->_proxy($tx, $proto, $host, $port)
if $proto eq 'http' && lc($req->headers->upgrade || '') ne 'websocket';

return $scheme, $host, $port;
return $proto, $host, $port;
}

sub form {
Expand Down Expand Up @@ -116,10 +116,9 @@ sub proxy_connect {
return undef unless my $proxy = $req->proxy;

# WebSocket and/or HTTPS
my $url = $req->url;
my $url = $req->url;
my $upgrade = lc($req->headers->upgrade || '');
my $scheme = $url->scheme;
return undef unless $upgrade eq 'websocket' || $scheme eq 'https';
return undef unless $upgrade eq 'websocket' || $url->protocol eq 'https';

# CONNECT request
my $new = $self->tx(CONNECT => $url->clone->userinfo(undef));
Expand Down Expand Up @@ -178,11 +177,11 @@ sub websocket {
my $self = shift;

# New WebSocket transaction
my $tx = $self->tx(GET => @_);
my $req = $tx->req;
my $abs = $req->url->to_abs;
my $scheme = $abs->scheme;
$req->url($abs->scheme($scheme eq 'wss' ? 'https' : 'http')) if $scheme;
my $tx = $self->tx(GET => @_);
my $req = $tx->req;
my $abs = $req->url->to_abs;
my $proto = $abs->protocol;
$req->url($abs->scheme($proto eq 'wss' ? 'https' : 'http')) if $proto;

# Handshake
Mojo::Transaction::WebSocket->new(handshake => $tx, masked => 1)
Expand Down Expand Up @@ -232,16 +231,16 @@ sub _multipart {
}

sub _proxy {
my ($self, $tx, $scheme, $host, $port) = @_;
my ($self, $tx, $proto, $host, $port) = @_;

# Update with proxy information
if (my $proxy = $tx->req->proxy) {
$scheme = $proxy->scheme;
$host = $proxy->ihost;
$port = $proxy->port || ($scheme eq 'https' ? 443 : 80);
$proto = $proxy->protocol;
$host = $proxy->ihost;
$port = $proxy->port || ($proto eq 'https' ? 443 : 80);
}

return $scheme, $host, $port;
return $proto, $host, $port;
}

1;
Expand Down Expand Up @@ -279,7 +278,7 @@ implements the following new ones.
=head2 C<endpoint>
my ($scheme, $host, $port) = $t->endpoint(Mojo::Transaction::HTTP->new);
my ($proto, $host, $port) = $t->endpoint(Mojo::Transaction::HTTP->new);
Actual endpoint for transaction.
Expand Down Expand Up @@ -338,7 +337,7 @@ data.
=head2 C<peer>
my ($scheme, $host, $port) = $t->peer(Mojo::Transaction::HTTP->new);
my ($proto, $host, $port) = $t->peer(Mojo::Transaction::HTTP->new);
Actual peer for transaction.
Expand Down
2 changes: 1 addition & 1 deletion lib/Mojolicious/Controller.pm
Expand Up @@ -427,7 +427,7 @@ sub url_for {
if (!$target || $target eq 'current') && $req->url->path->trailing_slash;

# Fix scheme for WebSockets
$base->scheme(($base->scheme // '') eq 'https' ? 'wss' : 'ws') if $ws;
$base->scheme($base->protocol eq 'https' ? 'wss' : 'ws') if $ws;
}

# Make path absolute
Expand Down
20 changes: 17 additions & 3 deletions t/mojo/transactor.t
Expand Up @@ -205,7 +205,7 @@ is(($t->endpoint($tx))[1], 'mojolicio.us', 'right host');
is(($t->endpoint($tx))[2], 80, 'right port');

# HTTPS endpoint
$tx = $t->tx(GET => 'https://mojolicio.us');
$tx = $t->tx(GET => 'HTTPS://mojolicio.us');
is(($t->endpoint($tx))[0], 'https', 'right scheme');
is(($t->endpoint($tx))[1], 'mojolicio.us', 'right host');
is(($t->endpoint($tx))[2], 443, 'right port');
Expand All @@ -218,7 +218,7 @@ is(($t->endpoint($tx))[1], 'mojolicio.us', 'right host');
is(($t->endpoint($tx))[2], 443, 'right port');

# TLS WebSocket endpoint with proxy
$tx = $t->websocket('wss://mojolicio.us');
$tx = $t->websocket('WSS://mojolicio.us');
$tx->req->proxy('http://127.0.0.1:3000');
is(($t->endpoint($tx))[0], 'https', 'right scheme');
is(($t->endpoint($tx))[1], 'mojolicio.us', 'right host');
Expand All @@ -237,6 +237,20 @@ is(($t->peer($tx))[0], 'http', 'right scheme');
is(($t->peer($tx))[1], '127.0.0.1', 'right host');
is(($t->peer($tx))[2], 3000, 'right port');

# Simple peer with proxy (no port)
$tx = $t->tx(GET => 'http://mojolicio.us');
$tx->req->proxy('http://127.0.0.1');
is(($t->peer($tx))[0], 'http', 'right scheme');
is(($t->peer($tx))[1], '127.0.0.1', 'right host');
is(($t->peer($tx))[2], 80, 'right port');

# Simple peer with HTTPS proxy (no port)
$tx = $t->tx(GET => 'http://mojolicio.us');
$tx->req->proxy('HTTPS://127.0.0.1');
is(($t->peer($tx))[0], 'https', 'right scheme');
is(($t->peer($tx))[1], '127.0.0.1', 'right host');
is(($t->peer($tx))[2], 443, 'right port');

# Simple WebSocket peer with proxy
$tx = $t->websocket('ws://mojolicio.us');
$tx->req->proxy('http://127.0.0.1:3000');
Expand Down Expand Up @@ -290,7 +304,7 @@ ok $tx->req->headers->sec_websocket_version,
is $tx->req->headers->upgrade, 'websocket', 'right "Upgrade" value';

# Proxy CONNECT
$tx = $t->tx(GET => 'https://sri:secr3t@mojolicio.us');
$tx = $t->tx(GET => 'HTTPS://sri:secr3t@mojolicio.us');
$tx->req->proxy('http://sri:secr3t@127.0.0.1:3000');
ok !$tx->req->headers->authorization, 'no "Authorization" header';
ok !$tx->req->headers->proxy_authorization, 'no "Proxy-Authorization" header';
Expand Down
14 changes: 8 additions & 6 deletions t/mojo/url.t
Expand Up @@ -7,27 +7,29 @@ use Mojo::URL;

# Simple
my $url = Mojo::URL->new('HtTp://Kraih.Com');
is $url->scheme, 'HtTp', 'right scheme';
is $url->host, 'Kraih.Com', 'right host';
is $url->scheme, 'HtTp', 'right scheme';
is $url->protocol, 'http', 'right protocol';
is $url->host, 'Kraih.Com', 'right host';
is "$url", 'http://kraih.com', 'right format';

# Advanced
$url = Mojo::URL->new(
'http://sri:foobar@kraih.com:8080/test/index.html?monkey=biz&foo=1#/!%?@3');
'https://sri:foobar@kraih.com:8080/test/index.html?monkey=biz&foo=1#/!%?@3');
ok $url->is_abs, 'is absolute';
is $url->scheme, 'http', 'right scheme';
is $url->scheme, 'https', 'right scheme';
is $url->protocol, 'https', 'right protocol';
is $url->userinfo, 'sri:foobar', 'right userinfo';
is $url->host, 'kraih.com', 'right host';
is $url->port, '8080', 'right port';
is $url->path, '/test/index.html', 'right path';
is $url->query, 'monkey=biz&foo=1', 'right query';
is $url->fragment, '/!%?@3', 'right fragment';
is "$url",
'http://sri:foobar@kraih.com:8080/test/index.html?monkey=biz&foo=1#/!%?@3',
'https://sri:foobar@kraih.com:8080/test/index.html?monkey=biz&foo=1#/!%?@3',
'right format';
$url->path('/index.xml');
is "$url",
'http://sri:foobar@kraih.com:8080/index.xml?monkey=biz&foo=1#/!%?@3',
'https://sri:foobar@kraih.com:8080/index.xml?monkey=biz&foo=1#/!%?@3',
'right format';

# Advanced fragment roundtrip
Expand Down

0 comments on commit b473b78

Please sign in to comment.