Introduce CORS headers in proxy

Change-Id: Ibcc1033cbbfec268d9f2816cc6c4f1383563d8b1
diff --git a/Changes b/Changes
index 0b7ebb8..74f8ed6 100755
--- a/Changes
+++ b/Changes
@@ -1,3 +1,6 @@
+0.41 2021-01-14
+        - Introduce CORS headers to the proxy.
+
 0.40 2020-12-17
         - Modernize ES and fix in-loops.
         - add roll() method to state object.
diff --git a/README.md b/README.md
index 414087f..8e00ee2 100644
--- a/README.md
+++ b/README.md
@@ -267,7 +267,7 @@
 
 ### Original Software
 
-Copyright (C) 2015-2020, [IDS Mannheim](http://www.ids-mannheim.de/)<br>
+Copyright (C) 2015-2021, [IDS Mannheim](http://www.ids-mannheim.de/)<br>
 Author: [Nils Diewald](http://nils-diewald.de/), Helge Stallkamp<br>
 Contributor: Eliza Margaretha (Documentation), Susanne Feix (Translation)
 
diff --git a/lib/Kalamar.pm b/lib/Kalamar.pm
index ac69b8b..61827f8 100644
--- a/lib/Kalamar.pm
+++ b/lib/Kalamar.pm
@@ -8,7 +8,7 @@
 use List::Util 'none';
 
 # Minor version - may be patched from package.json
-our $VERSION = '0.40';
+our $VERSION = '0.41';
 
 # Supported version of Backend API
 our $API_VERSION = '1.0';
diff --git a/lib/Kalamar/Controller/Proxy.pm b/lib/Kalamar/Controller/Proxy.pm
index c84b5b9..8a52c25 100644
--- a/lib/Kalamar/Controller/Proxy.pm
+++ b/lib/Kalamar/Controller/Proxy.pm
@@ -39,6 +39,22 @@
     before_korap_request => ($c, $tx)
   );
 
+  my $h = $c->res->headers;
+  $h->access_control_allow_origin('*');
+  $h->header('Access-Control-Allow-Methods' => 'GET, OPTIONS');
+
+  # Retrieve CORS header
+  if ($c->req->method eq 'OPTIONS') {
+
+    # Remember this option for a day
+    $h->header('Access-Control-Max-Age' => '86400');
+    $h->header('Access-Control-Allow-Headers' => '*');
+    return $c->render(
+      status => 204,
+      text => ''
+    );
+  };
+
   # Start proxy transaction and catch failure
   $c->proxy->start_p($tx)->catch(
     sub {
@@ -56,15 +72,17 @@
 
   $tx->res->content->once(
     body => sub {
-      my $headers = $c->res->headers;
-      $headers->header('X-Proxy' => 'Kalamar');
-      $headers->header('X-Robots' => 'noindex');
+      my $h = $c->res->headers;
+      $h->header('X-Proxy' => 'Kalamar');
+      $h->header('X-Robots' => 'noindex');
+      $h->access_control_allow_origin('*');
+      $h->header('Access-Control-Allow-Methods' => 'GET, OPTIONS');
 
       # Response is a redirect
       if ($c->res->is_redirect) {
 
         # Rewrite redirect location to surface URL
-        my $location_url = $c->res->headers->location;
+        my $location_url = $h->location;
         my $base_url = Mojo::URL->new($c->korap->api)->to_abs->to_string;
 
         # Remove the api part
@@ -81,13 +99,13 @@
         my $loc_based = $location_url->base($proxy_url->to_abs);
 
         # Reset location
-        $c->res->headers->location($loc_based->to_abs);
+        $h->location($loc_based->to_abs);
       };
 
       # Workaround for a proxy problem when
       # another proxy, e.g. Apache, manages multiple
       # connections
-      $headers->connection('close');
+      $h->connection('close');
 
       $c->app->plugins->emit_hook(after_render => $c);
     }
diff --git a/t/proxy.t b/t/proxy.t
index 2b16623..518d7a4 100644
--- a/t/proxy.t
+++ b/t/proxy.t
@@ -58,6 +58,11 @@
 
 $t->get_ok('/api/v1.0/')
   ->status_is(200)
+  ->header_is('X-Proxy', 'Kalamar')
+  ->header_is('X-Robots', 'noindex')
+  ->header_is('Connection', 'close')
+  ->header_is('Access-Control-Allow-Origin', '*')
+  ->header_is('Access-Control-Allow-Methods', 'GET, OPTIONS')
   ->content_is('Fake server available')
   ;
 
@@ -66,6 +71,8 @@
 
 $t->get_ok('/api/v1.0/search?ql=cosmas3')
   ->status_is(400)
+  ->header_is('Access-Control-Allow-Origin', '*')
+  ->header_is('Access-Control-Allow-Methods', 'GET, OPTIONS')
   ->json_is('/errors/0/0','307')
   ->header_is('connection', 'close')
   ;
@@ -119,6 +126,8 @@
 
 $t->get_ok('/api/v1.0/redirect-target-a')
   ->status_is(200)
+  ->header_is('Access-Control-Allow-Origin', '*')
+  ->header_is('Access-Control-Allow-Methods', 'GET, OPTIONS')
   ->content_is('Redirect Target!')
   ;
 
@@ -131,8 +140,19 @@
 
 $t->get_ok('/api/v1.0/redirect')
   ->status_is(200)
+  ->header_is('Access-Control-Allow-Origin', '*')
   ->content_is('Redirect Target!')
   ;
 
+# Check CORS
+$t->options_ok('/api/v1.0/search?ql=cosmas3')
+  ->status_is(204)
+  ->content_is('')
+  ->header_is('Access-Control-Allow-Origin', '*')
+  ->header_is('Access-Control-Allow-Methods', 'GET, OPTIONS')
+  ->header_is('Access-Control-Max-Age', '86400')
+  ;
+
+
 done_testing;
 __END__