Improve proxy for redirects
Change-Id: I3d62dd698ced3d406fd4ff8377de1a01a0fde319
diff --git a/Changes b/Changes
index 3e6d12f..45365b1 100755
--- a/Changes
+++ b/Changes
@@ -1,6 +1,7 @@
-0.38 2020-02-04
+0.38 2020-02-05
- Support X-Forwarded-Host name for proxy.
- Document API URI.
+ - Improve redirect handling in proxy.
0.37 2020-01-16
- Removed deprecated 'kalamar_test_port' helper.
diff --git a/lib/Kalamar/Controller/Proxy.pm b/lib/Kalamar/Controller/Proxy.pm
index af1eb75..2078d85 100644
--- a/lib/Kalamar/Controller/Proxy.pm
+++ b/lib/Kalamar/Controller/Proxy.pm
@@ -39,7 +39,7 @@
before_korap_request => ($c, $tx)
);
- # Start proxy transaction and cache failure
+ # Start proxy transaction and catch failure
$c->proxy->start_p($tx)->catch(
sub {
my $err = shift;
@@ -48,6 +48,10 @@
status => 400
);
}
+ )->finally(
+ sub {
+ $c->rendered;
+ }
)->wait;
$tx->res->content->once(
@@ -55,6 +59,30 @@
my $headers = $c->res->headers;
$headers->header('X-Proxy' => 'Kalamar');
+ # Response is a redirect
+ if ($c->res->is_redirect) {
+
+ # Rewrite redirect location to surface URL
+ my $location_url = $c->res->headers->location;
+ my $base_url = Mojo::URL->new($c->korap->api)->to_abs->to_string;
+
+ # Remove the api part
+ # ".*?" is just required for non-absolute base_urls
+ $location_url =~ s/^.*?${base_url}//;
+
+ # Turn the rewritten location into a URL object
+ $location_url = Mojo::URL->new($location_url);
+
+ my $proxy_url = $c->url_for('proxy');
+ $proxy_url->path->trailing_slash(1);
+
+ # Rebase to proxy path
+ my $loc_based = $location_url->base($proxy_url->to_abs);
+
+ # Reset location
+ $c->res->headers->location($loc_based->to_abs);
+ };
+
# Workaround for a proxy problem when
# another proxy, e.g. Apache, manages multiple
# connections
diff --git a/t/proxy.t b/t/proxy.t
index 7c54127..1dc1d08 100644
--- a/t/proxy.t
+++ b/t/proxy.t
@@ -118,5 +118,22 @@
->content_is('Proxy error: Inactivity timeout')
;
+$t->get_ok('/api/v1.0/redirect-target-a')
+ ->status_is(200)
+ ->content_is('Redirect Target!')
+ ;
+
+$t->get_ok('/api/v1.0/redirect')
+ ->status_is(308)
+ ->content_is('')
+ ;
+
+$t->ua->max_redirects(2);
+
+$t->get_ok('/api/v1.0/redirect')
+ ->status_is(200)
+ ->content_is('Redirect Target!')
+ ;
+
done_testing;
__END__
diff --git a/t/server/mock.pl b/t/server/mock.pl
index 2e14035..a1f0596 100644
--- a/t/server/mock.pl
+++ b/t/server/mock.pl
@@ -100,6 +100,20 @@
};
+get '/v1.0/redirect-target-a' => sub {
+ shift->render(text => 'Redirect Target!');
+} => 'redirect-target';
+
+
+# Base page
+get '/v1.0/redirect' => sub {
+ my $c = shift;
+ $c->res->code(308);
+ $c->res->headers->location($c->url_for('redirect-target')->to_abs);
+ return $c->render(text => '');
+};
+
+
# Search fixtures
get '/v1.0/search' => sub {
my $c = shift;