summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJesse Luehrs <doy@tozt.net>2011-01-06 14:38:24 -0600
committerJesse Luehrs <doy@tozt.net>2011-01-06 14:38:24 -0600
commit642b11b4f8d5edacd55e6b10e0b287047acc1ae1 (patch)
treeaf7604e5dbd96d5bc99fbab4c2b7aa9a678029d6
parent5cd0eab98e088720e6090e8533b1fb8e52a8a214 (diff)
downloadplack-client-642b11b4f8d5edacd55e6b10e0b287047acc1ae1.tar.gz
plack-client-642b11b4f8d5edacd55e6b10e0b287047acc1ae1.zip
major refactoring, things are a lot cleaner now
-rw-r--r--lib/Plack/Client.pm150
-rw-r--r--t/02-inputs.t28
2 files changed, 117 insertions, 61 deletions
diff --git a/lib/Plack/Client.pm b/lib/Plack/Client.pm
index 5a2abb4..80824d8 100644
--- a/lib/Plack/Client.pm
+++ b/lib/Plack/Client.pm
@@ -7,7 +7,7 @@ use HTTP::Request;
use Plack::App::Proxy;
use Plack::Middleware::ContentLength;
use Plack::Response;
-use Scalar::Util qw(blessed);
+use Scalar::Util qw(blessed reftype);
sub new {
my $class = shift;
@@ -30,37 +30,9 @@ sub app_for {
sub request {
my $self = shift;
- my $req = blessed($_[0]) && ($_[0]->isa('HTTP::Request')
- || $_[0]->isa('Plack::Request'))
- ? $_[0]
- : ref($_[0]) eq 'HASH'
- ? Plack::Request->new(@_)
- : HTTP::Request->new(@_);
-
- # both Plack::Request and HTTP::Request have a ->uri method
- my $scheme = $req->uri->scheme;
- my $app;
- if ($scheme eq 'psgi-local') {
- if ($req->isa('Plack::Request')) {
- $req->env->{REQUEST_URI} = '/' unless length $req->request_uri;
- }
- else {
- $req->uri->path('/') unless length $req->uri->path;
- }
- my $app_name = $req->uri->authority;
- $app_name =~ s/:.*//;
- $app = $self->app_for($app_name);
- $app = Plack::Middleware::ContentLength->wrap($app);
- }
- elsif ($scheme eq 'http' || $scheme eq 'https') {
- my $uri = $req->uri->clone;
- $uri->path('/');
- $app = Plack::App::Proxy->new(remote => $uri->as_string)->to_app;
- }
- die 'XXX' unless $app;
+ my ($app, $env) = $self->_parse_request_args(@_);
- my $env = $self->_req_to_env($req);
my $psgi_res = $self->_resolve_response($app->($env));
# is there a better place to do this? Plack::App::Proxy already takes care
# of this (since it's making a real http request)
@@ -70,41 +42,121 @@ sub request {
return Plack::Response->new(@$psgi_res);
}
-sub _req_to_env {
+sub _parse_request_args {
my $self = shift;
- my ($req) = @_;
- my $env;
- if ($req->isa('HTTP::Request')) {
- my $scheme = $req->uri->scheme;
- # hack around with this - psgi requires a host and port to exist, and
- # for the scheme to be either http or https
- if ($scheme eq 'psgi-local') {
- $req->uri->scheme('http');
- $req->uri->host('Plack::Client');
- $req->uri->port(-1);
+ if (blessed($_[0])) {
+ if ($_[0]->isa('HTTP::Request')) {
+ return $self->_request_from_http_request(@_);
}
- elsif ($scheme eq 'psgi-local-ssl') {
- $req->uri->scheme('https');
- $req->uri->host('Plack::Client');
- $req->uri->port(-1);
+ elsif ($_[0]->isa('Plack::Request')) {
+ return $self->_request_from_plack_request(@_);
}
- elsif ($scheme ne 'http' && $scheme ne 'https') {
+ else {
die 'XXX';
}
-
- $env = $req->to_psgi;
+ }
+ elsif ((reftype($_[0]) || '') eq 'HASH') {
+ return $self->_request_from_env(@_);
}
else {
- $env = $req->env;
+ return $self->_request_from_http_request_args(@_);
}
+}
+
+sub _request_from_http_request {
+ my $self = shift;
+ my ($http_request) = @_;
+ my $env = $self->_http_request_to_env($http_request);
+ return $self->_request_from_env($env);
+}
+
+sub _request_from_plack_request {
+ my $self = shift;
+ my ($req) = @_;
+
+ return ($self->_app_from_req($req), $req->env);
+}
+
+sub _request_from_env {
+ my $self = shift;
+ return $self->_request_from_plack_request(Plack::Request->new(@_));
+}
+
+sub _request_from_http_request_args {
+ my $self = shift;
+ return $self->_request_from_http_request(HTTP::Request->new(@_));
+}
+
+sub _http_request_to_env {
+ my $self = shift;
+ my ($req) = @_;
+
+ my $scheme = $req->uri->scheme;
+ my $app_name;
+ # hack around with this - psgi requires a host and port to exist, and
+ # for the scheme to be either http or https
+ if ($scheme eq 'psgi-local') {
+ $app_name = $req->uri->authority;
+ $req->uri->scheme('http');
+ $req->uri->host('Plack::Client');
+ $req->uri->port(-1);
+ }
+ elsif ($scheme eq 'psgi-local-ssl') {
+ $app_name = $req->uri->authority;
+ $req->uri->scheme('https');
+ $req->uri->host('Plack::Client');
+ $req->uri->port(-1);
+ }
+ elsif ($scheme ne 'http' && $scheme ne 'https') {
+ die 'XXX';
+ }
+
+ # work around http::message::psgi bug - see github issue 163 for plack
+ if (!$req->uri->path) {
+ $req->uri->path('/');
+ }
+
+ my $env = $req->to_psgi;
# work around http::message::psgi bug - see github issue 150 for plack
$env->{CONTENT_LENGTH} ||= length($req->content);
+ $env->{'plack.client.url_scheme'} = $scheme;
+ $env->{'plack.client.app_name'} = $app_name
+ if defined $app_name;
+
return $env;
}
+sub _app_from_req {
+ my $self = shift;
+ my ($req) = @_;
+
+ my $uri = $req->uri;
+ my $scheme = $req->env->{'plack.client.url_scheme'} || $uri->scheme;
+ my $app_name = $req->env->{'plack.client.app_name'};
+
+ my $app;
+ if ($scheme eq 'psgi-local') {
+ if (!defined $app_name) {
+ $app_name = $uri->authority;
+ $app_name =~ s/(.*):.*/$1/; # in case a port was added at some point
+ }
+ $app = $self->app_for($app_name);
+ $app = Plack::Middleware::ContentLength->wrap($app);
+ }
+ elsif ($scheme eq 'http' || $scheme eq 'https') {
+ my $uri = $uri->clone;
+ $uri->path('/');
+ $app = Plack::App::Proxy->new(remote => $uri->as_string)->to_app;
+ }
+
+ die 'XXX' unless $app;
+
+ return $app;
+}
+
sub _resolve_response {
my $self = shift;
my ($psgi_res) = @_;
diff --git a/t/02-inputs.t b/t/02-inputs.t
index 4b27630..faa5e5a 100644
--- a/t/02-inputs.t
+++ b/t/02-inputs.t
@@ -125,18 +125,22 @@ sub test_responses {
"GET\n/\n\n"
);
- my $uri = URI->new($base_uri);
- $uri->scheme('http')
- if $base_uri =~ /psgi-local/;
- my $env = HTTP::Request->new(GET => $uri)->to_psgi;
- $env->{'psgi.url_scheme'} = 'psgi-local'
- if $base_uri =~ /psgi-local/;
- response_is(
- $client->request($env),
- 200,
- ['Content-Type' => 'text/plain', 'Content-Length' => '7'],
- "GET\n/\n\n"
- );
+ {
+ my $base = URI->new($base_uri);
+ my $uri = $base->clone;
+ $uri->scheme('http');
+ $uri->path('/') unless $uri->path;
+ my $env = HTTP::Request->new(GET => $uri)->to_psgi;
+ $env->{'plack.client.url_scheme'} = $base->scheme;
+ $env->{'plack.client.app_name'} = $base->authority
+ if $base->scheme eq 'psgi-local';
+ response_is(
+ $client->request($env),
+ 200,
+ ['Content-Type' => 'text/plain', 'Content-Length' => '7'],
+ "GET\n/\n\n"
+ );
+ }
}
done_testing;