Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
fixed Mojo::UserAgent::Transactor to handle redirects more like most …
…common browsers
  • Loading branch information
kraih committed Jan 31, 2014
1 parent 92c4bdc commit ce643c6
Show file tree
Hide file tree
Showing 4 changed files with 72 additions and 42 deletions.
2 changes: 2 additions & 0 deletions Changes
Expand Up @@ -2,6 +2,8 @@
4.73 2014-01-31
- Improved xml_escape performance significantly.
- Improved html_unescape and url_unescape performance.
- Fixed Mojo::UserAgent::Transactor to handle redirects more like most
common browsers.

4.72 2014-01-29
- Added accepts, template_for and template_handler methods to
Expand Down
5 changes: 1 addition & 4 deletions lib/Mojo/Headers.pm
Expand Up @@ -44,10 +44,7 @@ sub append {
return $self->header($name => defined $old ? "$old, $value" : $value);
}

sub clone {
my $self = shift;
return $self->new->from_hash($self->to_hash(1));
}
sub clone { $_[0]->new->from_hash($_[0]->to_hash(1)) }

sub from_hash {
my ($self, $hash) = @_;
Expand Down
14 changes: 9 additions & 5 deletions lib/Mojo/UserAgent/Transactor.pm
Expand Up @@ -84,12 +84,16 @@ sub redirect {
my $req = $old->req;
my $method = uc $req->method;
if ($code eq 301 || $code eq 307 || $code eq 308) {
return undef unless my $req = $req->clone;
$new->req($req);
$req->headers->remove('Host')->remove('Cookie')->remove('Referer');
return undef unless my $clone = $req->clone;
$new->req($clone);
}
elsif ($method ne 'HEAD') { $method = 'GET' }
$new->req->method($method)->url($location);
else {
$method = 'GET' if $method ne 'HEAD';
my $headers = $new->req->content->headers($req->headers->clone)->headers;
$headers->remove($_) for grep {/^content-/i} @{$headers->names};
}
my $headers = $new->req->method($method)->url($location)->headers;
$headers->remove($_) for qw(Authorization Cookie Host Referer);
return $new->previous($old);
}

Expand Down
93 changes: 60 additions & 33 deletions t/mojo/transactor.t
Expand Up @@ -504,8 +504,8 @@ is $tx->req->headers->accept, 'application/json', 'right "Accept" value';
is $tx->req->body, '', 'no content';
$tx = $t->redirect($tx);
is $tx->req->method, 'GET', 'right method';
is $tx->req->url->to_abs, 'http://example.com/bar', 'right URL';
is $tx->req->headers->accept, undef, 'no "Accept" value';
is $tx->req->url->to_abs, 'http://example.com/bar', 'right URL';
is $tx->req->headers->accept, 'application/json', 'right "Accept" value';
is $tx->req->headers->location, undef, 'no "Location" value';
is $tx->req->body, '', 'no content';
is $tx->res->code, undef, 'no status';
Expand Down Expand Up @@ -538,6 +538,27 @@ is $tx->req->body, '', 'no content';
is $tx->res->code, undef, 'no status';
is $tx->res->headers->location, undef, 'no "Location" value';

# 302 redirect with content
$tx = $t->tx(
POST => 'http://mojolicio.us/foo' => {Accept => '*/*'} => 'whatever');
$tx->req->fix_headers->headers->content_type('text/plain');
$tx->res->code(302);
$tx->res->headers->location('http://example.com/bar');
is $tx->req->headers->accept, '*/*', 'right "Accept" value';
is $tx->req->headers->content_type, 'text/plain', 'right "Content-Type" value';
is $tx->req->headers->content_length, 8, 'right "Content-Length" value';
is $tx->req->body, 'whatever', 'right content';
$tx = $t->redirect($tx);
is $tx->req->method, 'GET', 'right method';
is $tx->req->url->to_abs, 'http://example.com/bar', 'right URL';
is $tx->req->headers->accept, '*/*', 'right "Accept" value';
is $tx->req->headers->content_type, undef, 'no "Content-Type" value';
is $tx->req->headers->content_length, undef, 'no "Content-Length" value';
is $tx->req->headers->location, undef, 'no "Location" value';
is $tx->req->body, '', 'no content';
is $tx->res->code, undef, 'no status';
is $tx->res->headers->location, undef, 'no "Location" value';

# Simple 303 redirect
$tx = $t->tx(
POST => 'http://mojolicio.us/foo' => {Accept => 'application/json'});
Expand All @@ -547,8 +568,8 @@ is $tx->req->headers->accept, 'application/json', 'right "Accept" value';
is $tx->req->body, '', 'no content';
$tx = $t->redirect($tx);
is $tx->req->method, 'GET', 'right method';
is $tx->req->url->to_abs, 'http://example.com/bar', 'right URL';
is $tx->req->headers->accept, undef, 'no "Accept" value';
is $tx->req->url->to_abs, 'http://example.com/bar', 'right URL';
is $tx->req->headers->accept, 'application/json', 'right "Accept" value';
is $tx->req->headers->location, undef, 'no "Location" value';
is $tx->req->body, '', 'no content';
is $tx->res->code, undef, 'no status';
Expand All @@ -571,27 +592,30 @@ is $tx->res->headers->location, undef, 'no "Location" value';
# 303 redirect (additional headers)
$tx = $t->tx(
POST => 'http://mojolicio.us/foo' => {
Accept => 'application/json',
Cookie => 'one',
Host => 'two',
Referer => 'three'
Accept => 'application/json',
Authorization => 'one',
Cookie => 'two',
Host => 'three',
Referer => 'four'
}
);
$tx->res->code(303);
$tx->res->headers->location('http://example.com/bar');
is $tx->req->headers->accept, 'application/json', 'right "Accept" value';
is $tx->req->headers->cookie, 'one', 'right "Cookie" value';
is $tx->req->headers->host, 'two', 'right "Host" value';
is $tx->req->headers->referrer, 'three', 'right "Referer" value';
is $tx->req->headers->accept, 'application/json', 'right "Accept" value';
is $tx->req->headers->authorization, 'one', 'right "Authorization" value';
is $tx->req->headers->cookie, 'two', 'right "Cookie" value';
is $tx->req->headers->host, 'three', 'right "Host" value';
is $tx->req->headers->referrer, 'four', 'right "Referer" value';
is $tx->req->body, '', 'no content';
$tx = $t->redirect($tx);
is $tx->req->method, 'GET', 'right method';
is $tx->req->url->to_abs, 'http://example.com/bar', 'right URL';
is $tx->req->headers->accept, undef, 'no "Accept" value';
is $tx->req->headers->cookie, undef, 'no "Cookie" value';
is $tx->req->headers->host, undef, 'no "Host" value';
is $tx->req->headers->location, undef, 'no "Location" value';
is $tx->req->headers->referrer, undef, 'no "Referer" value';
is $tx->req->headers->accept, 'application/json', 'right "Accept" value';
is $tx->req->headers->authorization, undef, 'no "Authorization" value';
is $tx->req->headers->cookie, undef, 'no "Cookie" value';
is $tx->req->headers->host, undef, 'no "Host" value';
is $tx->req->headers->location, undef, 'no "Location" value';
is $tx->req->headers->referrer, undef, 'no "Referer" value';
is $tx->req->body, '', 'no content';
is $tx->res->code, undef, 'no status';
is $tx->res->headers->location, undef, 'no "Location" value';
Expand Down Expand Up @@ -677,27 +701,30 @@ is $t->redirect($tx), undef, 'unsupported redirect';
# 307 redirect (additional headers)
$tx = $t->tx(
POST => 'http://mojolicio.us/foo' => {
Accept => 'application/json',
Cookie => 'one',
Host => 'two',
Referer => 'three'
Accept => 'application/json',
Authorization => 'one',
Cookie => 'two',
Host => 'three',
Referer => 'four'
}
);
$tx->res->code(307);
$tx->res->headers->location('http://example.com/bar');
is $tx->req->headers->accept, 'application/json', 'right "Accept" value';
is $tx->req->headers->cookie, 'one', 'right "Cookie" value';
is $tx->req->headers->host, 'two', 'right "Host" value';
is $tx->req->headers->referrer, 'three', 'right "Referer" value';
is $tx->req->headers->accept, 'application/json', 'right "Accept" value';
is $tx->req->headers->authorization, 'one', 'right "Authorization" value';
is $tx->req->headers->cookie, 'two', 'right "Cookie" value';
is $tx->req->headers->host, 'three', 'right "Host" value';
is $tx->req->headers->referrer, 'four', 'right "Referer" value';
is $tx->req->body, '', 'no content';
$tx = $t->redirect($tx);
is $tx->req->method, 'POST', 'right method';
is $tx->req->url->to_abs, 'http://example.com/bar', 'right URL';
is $tx->req->headers->accept, 'application/json', 'right "Accept" value';
is $tx->req->headers->cookie, undef, 'no "Cookie" value';
is $tx->req->headers->host, undef, 'no "Host" value';
is $tx->req->headers->location, undef, 'no "Location" value';
is $tx->req->headers->referrer, undef, 'no "Referer" value';
is $tx->req->headers->authorization, undef, 'no "Authorization" value';
is $tx->req->headers->cookie, undef, 'no "Cookie" value';
is $tx->req->headers->host, undef, 'no "Host" value';
is $tx->req->headers->location, undef, 'no "Location" value';
is $tx->req->headers->referrer, undef, 'no "Referer" value';
is $tx->req->body, '', 'no content';
is $tx->res->code, undef, 'no status';
is $tx->res->headers->location, undef, 'no "Location" value';
Expand Down Expand Up @@ -761,9 +788,9 @@ $tx = $t->redirect($tx);
is $tx->req->method, 'GET', 'right method';
is $tx->req->url->to_abs, 'http://mojolicio.us/foo/baz?f%23oo=bar',
'right URL';
is $tx->req->url->query, 'f%23oo=bar', 'right query';
is $tx->req->headers->accept, undef, 'no "Accept" value';
is $tx->req->headers->location, undef, 'no "Location" value';
is $tx->req->url->query, 'f%23oo=bar', 'right query';
is $tx->req->headers->accept, 'application/json', 'right "Accept" value';
is $tx->req->headers->location, undef, 'no "Location" value';
is $tx->req->body, '', 'no content';
is $tx->res->code, undef, 'no status';
is $tx->res->headers->location, undef, 'no "Location" value';
Expand All @@ -779,7 +806,7 @@ $tx = $t->redirect($tx);
is $tx->req->method, 'GET', 'right method';
is $tx->req->url->to_abs, 'http://mojolicio.us/baz?f%23oo=bar', 'right URL';
is $tx->req->url->query, 'f%23oo=bar', 'right query';
is $tx->req->headers->accept, undef, 'no "Accept" value';
is $tx->req->headers->accept, 'application/json', 'right "Accept" value';
is $tx->req->headers->location, undef, 'no "Location" value';
is $tx->req->body, '', 'no content';
is $tx->res->code, undef, 'no status';
Expand Down

0 comments on commit ce643c6

Please sign in to comment.