Added experimental proxy route to backend api - fixes #91
Change-Id: I9a055b33c8cacef6cfa564467a17e7f55a1eeef5
diff --git a/Changes b/Changes
index 6efd47c..b33b2e3 100755
--- a/Changes
+++ b/Changes
@@ -1,3 +1,8 @@
+0.35 2019-07-05
+ - Added EXPERIMENTAL proxy to API route.
+ - Remove deprecated api configuration
+ (requires api_path instead now).
+
0.34 2019-06-26
- Introduced guided tour (hebasta, #19).
- Updated dependency on M::P::Notifications to
diff --git a/Makefile.PL b/Makefile.PL
index 19c606e..92c8b68 100644
--- a/Makefile.PL
+++ b/Makefile.PL
@@ -14,9 +14,9 @@
},
LICENSE => 'freebsd',
PREREQ_PM => {
- 'Mojolicious' => '8.06',
+ 'Mojolicious' => '8.18',
'Mojolicious::Plugin::TagHelpers::Pagination' => 0.07,
- 'Mojolicious::Plugin::TagHelpers::MailToChiffre' => 0.09,
+ 'Mojolicious::Plugin::TagHelpers::MailToChiffre' => 0.10,
'Mojolicious::Plugin::ClosedRedirect' => 0.14,
'Mojolicious::Plugin::Notifications' => 1.03,
'Mojolicious::Plugin::MailException' => 0.20,
diff --git a/lib/Kalamar.pm b/lib/Kalamar.pm
index 7856e91..c9e9374 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.34';
+our $VERSION = '0.35';
# Supported version of Backend API
our $API_VERSION = '1.0';
@@ -58,9 +58,29 @@
$self->log->info('Mode is ' . $self->mode);
- # Specific path prefixing
+ # Get configuration
my $conf = $self->config('Kalamar');
- if ($conf && $conf->{proxy_prefix}) {
+ unless ($conf) {
+ $self->config(Kalamar => {});
+ $conf = $self->config('Kalamar');
+ };
+
+ # Check for API endpoint and set the endpoint accordingly
+ if ($conf->{api}) {
+
+ # The api endpoint should be defined as a separated path
+ # and version string
+ $self->log->warn(
+ 'Kalamar.api is no longer supported in configurations '.
+ 'in favor of Kalamar.api_path'
+ );
+ };
+
+ unless ($conf->{api_path} || $ENV{KALAMAR_API}) {
+ $self->log->warn('Kalamar-api_path not defined in configuration');
+ };
+
+ if ($conf->{proxy_prefix}) {
for ($self->sessions) {
$_->cookie_path($conf->{proxy_prefix});
@@ -78,28 +98,9 @@
});
};
- # Check for API endpoint and set the endpoint accordingly
- if ($conf->{api}) {
-
- # The api endpoint should be defined as a separated path
- # and version string
- $self->log->info(
- 'Kalamar.api is deprecated in configurations '.
- 'in favor of Kalamar.api_path'
- );
- }
-
- # Set from environment variable
- elsif ($ENV{'KALAMAR_API'}) {
- $conf->{api} = $ENV{'KALAMAR_API'};
- }
-
# API is not yet set - define
- else {
-
- $conf->{api} =
- Mojo::URL->new($conf->{api_path})->path('v' . ($conf->{api_version} // $API_VERSION) . '/')->to_string;
- };
+ $conf->{api_path} //= $ENV{KALAMAR_API};
+ $conf->{api_version} //= $API_VERSION;
# Add development path
if ($self->mode eq 'development') {
@@ -211,7 +212,7 @@
$self->config(navi => $navi);
- $self->log->info('API expected at ' . $self->config->{Kalamar}->{api});
+ $self->log->info('API expected at ' . $self->korap->api);
# Establish routes with authentification
my $r = $self->routes;
@@ -234,6 +235,10 @@
$r->get('/contact')->to('documentation#contact');
$r->get('/contact')->mail_to_chiffre('documentation#contact');
+ # API proxy route
+ # $r->any('/api/v#apiv' => [apiv => ['1.0']])->to('Proxy#pass');
+ # $r->any('/api/v#apiv/*path' => [apiv => ['1.0']])->to('Proxy#pass');
+
# Match route
# Corpus route
my $corpus = $r->get('/corpus')->to('search#corpus_info')->name('corpus');
@@ -266,7 +271,7 @@
=head2 COPYRIGHT AND LICENSE
-Copyright (C) 2015-2018, L<IDS Mannheim|http://www.ids-mannheim.de/>
+Copyright (C) 2015-2019, L<IDS Mannheim|http://www.ids-mannheim.de/>
Author: L<Nils Diewald|http://nils-diewald.de/>
Kalamar is developed as part of the L<KorAP|http://korap.ids-mannheim.de/>
diff --git a/lib/Kalamar/Controller/Proxy.pm b/lib/Kalamar/Controller/Proxy.pm
new file mode 100644
index 0000000..ed9acef
--- /dev/null
+++ b/lib/Kalamar/Controller/Proxy.pm
@@ -0,0 +1,53 @@
+package Kalamar::Controller::Proxy;
+use Mojo::Base 'Mojolicious::Controller';
+
+# Pass proxy command to API
+sub pass {
+ my $c = shift;
+
+ my $apiv = $c->stash('apiv');
+ my $path = $c->stash('path') // '';
+
+ # Get the original request
+ my $req = $c->req;
+
+ # Clone and clean request headers
+ my $headers = $req->headers->clone->dehop;
+
+ # Set Proxy information
+ $headers->header('X-Proxy' => 'Kalamar');
+
+ # Set clean X-Forwarded-For header
+ $headers->header(
+ 'X-Forwarded-For' => $c->client_ip
+ );
+
+ # Get parameters of the request
+ my $params = $req->query_params->clone;
+ my $api_url;
+
+ # Get API request for proxying
+ my $url = Mojo::URL->new($c->korap->api($apiv))->path($path)->query($params);
+
+ # Resend headers
+ my $tx = $c->kalamar_ua->build_tx(
+ $req->method => $url => $headers->to_hash => $req->body
+ );
+
+ # Pipe through system (which means
+ # an authorization header may be set)
+ $c->app->plugins->emit_hook(
+ before_korap_request => ($c, $tx)
+ );
+
+ # return $c->render(text => 'okay ' . $url);
+
+ $c->proxy->start_p($tx)->wait;
+ # $tx->res->content->once(
+ # body => sub {
+ # $c->res->headers->header('X-Proxy' => 'Kalamar');
+ # }
+ # );
+};
+
+1;
diff --git a/lib/Kalamar/Plugin/KalamarHelpers.pm b/lib/Kalamar/Plugin/KalamarHelpers.pm
index a85f2ae..f97f453 100644
--- a/lib/Kalamar/Plugin/KalamarHelpers.pm
+++ b/lib/Kalamar/Plugin/KalamarHelpers.pm
@@ -13,6 +13,14 @@
sub register {
my ($plugin, $mojo) = @_;
+ # Get config
+ my $conf = $mojo->config('Kalamar');
+
+ # Define API_URL
+ my $api_url = Mojo::URL->new(
+ $conf->{api_path} // '-'
+ )->path('v' . ($conf->{api_version} // '-') . '/')->to_string;
+
# Embed the korap architecture image
$mojo->helper(
korap_overview => sub {
@@ -290,7 +298,19 @@
# Get the KorAP API endpoint
$mojo->helper(
'korap.api' => sub {
- return shift->config('Kalamar')->{api};
+ my $c = shift;
+
+ # TODO:
+ # May clone a Mojo::URL object instead
+ return $api_url unless @_;
+
+ my $apiv = shift;
+ if (!$apiv || $apiv eq $conf->{api_version}) {
+ return $api_url;
+ };
+
+ # Return newly created API URL
+ return Mojo::URL->new($conf->{api_path})->path('v' . $apiv . '/')->to_string;
}
);
diff --git a/lib/Kalamar/Plugin/KalamarUser.pm b/lib/Kalamar/Plugin/KalamarUser.pm
index 60fadfe..cbbcda0 100644
--- a/lib/Kalamar/Plugin/KalamarUser.pm
+++ b/lib/Kalamar/Plugin/KalamarUser.pm
@@ -11,6 +11,9 @@
# This Plugin will be removed in favour of
# Kalamar::Plugin::Auth!
+# TODO:
+# Replace plugin-api with korap->api!
+
sub register {
my ($plugin, $mojo, $param) = @_;
diff --git a/package.json b/package.json
index e06a30c..088ed25 100755
--- a/package.json
+++ b/package.json
@@ -2,7 +2,7 @@
"name": "Kalamar",
"description": "Mojolicious-based Frontend for KorAP",
"license": "BSD-2-Clause",
- "version": "0.34.1",
+ "version": "0.35.1",
"pluginVersion": "0.1",
"repository": {
"type": "git",
diff --git a/t/corpus_info.t b/t/corpus_info.t
index e174bf0..ecbf2dd 100644
--- a/t/corpus_info.t
+++ b/t/corpus_info.t
@@ -7,7 +7,7 @@
#####################
# Start Fake server #
#####################
-my $mount_point = '/api/';
+my $mount_point = '/realapi/';
$ENV{KALAMAR_API} = $mount_point;
my $t = Test::Mojo->new('Kalamar');
diff --git a/t/corpus_info_cache.t b/t/corpus_info_cache.t
index 916a2d7..a11fb8b 100644
--- a/t/corpus_info_cache.t
+++ b/t/corpus_info_cache.t
@@ -7,7 +7,7 @@
#####################
# Start Fake server #
#####################
-my $mount_point = '/api/';
+my $mount_point = '/realapi/';
$ENV{KALAMAR_API} = $mount_point;
# New test with new cache
diff --git a/t/docembed.t b/t/docembed.t
index 24503f7..8224fa7 100644
--- a/t/docembed.t
+++ b/t/docembed.t
@@ -6,7 +6,7 @@
my $t = Test::Mojo->new('Kalamar' => {
Kalamar => {
- api => 'xyz',
+ api_path => 'xyz',
navi_ext => [
{
title => 'Privacy',
diff --git a/t/fixtures.t b/t/fixtures.t
index 598b918..6508cfc 100644
--- a/t/fixtures.t
+++ b/t/fixtures.t
@@ -8,23 +8,23 @@
my $t = Test::Mojo->new($mock_server);
-$t->get_ok('/')
+$t->get_ok('/v1.0')
->status_is(200)
->content_is('Fake server available');
-$t->get_ok('/search?ql=cosmas3')
+$t->get_ok('/v1.0/search?ql=cosmas3')
->status_is(400)
->json_is('/errors/0/0',"307")
->json_is('/errors/0/1',"cosmas3 is not a supported query language!")
;
-$t->get_ok('/search?q=server_fail')
+$t->get_ok('/v1.0/search?q=server_fail')
->status_is(500)
->text_is('#error', '')
->content_like(qr!Oooops!)
;
-$t->get_ok('/search?q=[orth=das&ql=poliqarp&offset=0&count=25')
+$t->get_ok('/v1.0/search?q=[orth=das&ql=poliqarp&offset=0&count=25')
->status_is(400)
->text_is('#error', '')
->json_is('/errors/0/0',302)
@@ -33,7 +33,7 @@
->json_is('/errors/1/1','Could not parse query >>> [orth=das <<<.')
;
-$t->get_ok('/search?q=baum&ql=poliqarp&offset=0&count=25')
+$t->get_ok('/v1.0/search?q=baum&ql=poliqarp&offset=0&count=25')
->status_is(200)
->text_is('#error', '')
->json_is('/meta/count', 25)
@@ -41,7 +41,7 @@
->json_is('/matches/0/docSigle', "GOE/AGI")
;
-$t->get_ok('/corpus/WPD15/232/39681/p2133-2134/matchInfo?spans=false&foundry=*')
+$t->get_ok('/v1.0/corpus/WPD15/232/39681/p2133-2134/matchInfo?spans=false&foundry=*')
->status_is(200)
->json_is('/textSigle', 'WPD15/232/39681')
;
diff --git a/t/match_info.t b/t/match_info.t
index 59f12ed..486fe11 100644
--- a/t/match_info.t
+++ b/t/match_info.t
@@ -7,7 +7,7 @@
#####################
# Start Fake server #
#####################
-my $mount_point = '/api/';
+my $mount_point = '/realapi/';
$ENV{KALAMAR_API} = $mount_point;
my $t = Test::Mojo->new('Kalamar');
diff --git a/t/plugin/auth-oauth.t b/t/plugin/auth-oauth.t
index d67837f..0239efe 100644
--- a/t/plugin/auth-oauth.t
+++ b/t/plugin/auth-oauth.t
@@ -8,7 +8,7 @@
#####################
# Start Fake server #
#####################
-my $mount_point = '/api/';
+my $mount_point = '/realapi/';
$ENV{KALAMAR_API} = $mount_point;
my $t = Test::Mojo->new('Kalamar' => {
@@ -34,7 +34,7 @@
# Configure fake backend
$fake_backend->pattern->defaults->{app}->log($t->app->log);
-$t->get_ok('/api')
+$t->get_ok('/realapi/v1.0')
->status_is(200)
->content_is('Fake server available');
diff --git a/t/plugin/auth.t b/t/plugin/auth.t
index 6b5818d..e310988 100644
--- a/t/plugin/auth.t
+++ b/t/plugin/auth.t
@@ -8,7 +8,7 @@
#####################
# Start Fake server #
#####################
-my $mount_point = '/api/';
+my $mount_point = '/realapi/';
$ENV{KALAMAR_API} = $mount_point;
my $t = Test::Mojo->new('Kalamar' => {
@@ -29,7 +29,7 @@
# Configure fake backend
$fake_backend->pattern->defaults->{app}->log($t->app->log);
-$t->get_ok('/api')
+$t->get_ok('/realapi/v1.0')
->status_is(200)
->content_is('Fake server available');
diff --git a/t/proxy.t b/t/proxy.t
new file mode 100644
index 0000000..f754f11
--- /dev/null
+++ b/t/proxy.t
@@ -0,0 +1,77 @@
+use Mojo::Base -strict;
+use Test::More;
+use Test::Mojo;
+use Mojo::File qw/path/;
+use Data::Dumper;
+
+
+#####################
+# Start Fake server #
+#####################
+my $mount_point = '/realapi/';
+$ENV{KALAMAR_API} = $mount_point;
+
+my $t = Test::Mojo->new('Kalamar' => {
+ Kalamar => {
+ plugins => ['Auth']
+ }
+});
+
+# Mount fake backend
+# Get the fixture path
+my $fixtures_path = path(Mojo::File->new(__FILE__)->dirname, 'server');
+my $fake_backend = $t->app->plugin(
+ Mount => {
+ $mount_point =>
+ $fixtures_path->child('mock.pl')
+ }
+);
+# Configure fake backend
+$fake_backend->pattern->defaults->{app}->log($t->app->log);
+
+# Globally set server
+$t->app->ua->server->app($t->app);
+
+my $r = $t->app->routes;
+
+# API proxy route
+$r->any('/api/v#apiv' => [apiv => ['1.0']])->to('Proxy#pass');
+$r->any('/api/v#apiv/*path' => [apiv => ['1.0']])->to('Proxy#pass');
+
+$t->get_ok('/realapi/v1.0')
+ ->status_is(200)
+ ->content_is('Fake server available')
+ ;
+
+$t->get_ok('/api/v1.0/')
+ ->status_is(200)
+ ->content_is('Fake server available')
+ ;
+
+$t->get_ok('/api/v1.0/search?ql=cosmas3')
+ ->status_is(400)
+ ->json_is('/errors/0/0','307')
+ ;
+
+$t->post_ok('/api/v1.0/oauth2/token' => {} => form => {
+ username => 'test',
+ password => 'pass'
+})
+ ->status_is(400)
+ ->json_is('/errors/0/1','Grant Type unknown')
+ ;
+
+$t->post_ok('/api/v1.0/oauth2/token' => {} => form => {
+ grant_type => 'password',
+ client_id => 2,
+ client_secret => 'k414m4r-s3cr3t',
+ username => 'test',
+ password => 'pass'
+})
+ ->status_is(200)
+ ->json_is('/token_type', 'Bearer')
+ ;
+
+
+done_testing;
+__END__
diff --git a/t/query.t b/t/query.t
index 2ce7a90..81c4ac8 100644
--- a/t/query.t
+++ b/t/query.t
@@ -7,7 +7,7 @@
#####################
# Start Fake server #
#####################
-my $mount_point = '/api/';
+my $mount_point = '/realapi/';
$ENV{KALAMAR_API} = $mount_point;
my $t = Test::Mojo->new('Kalamar');
diff --git a/t/server/mock.pl b/t/server/mock.pl
index 359f78c..2c7f43b 100644
--- a/t/server/mock.pl
+++ b/t/server/mock.pl
@@ -65,13 +65,13 @@
# Base page
-get '/' => sub {
+get '/v1.0/' => sub {
shift->render(text => 'Fake server available');
};
# Search fixtures
-get '/search' => sub {
+get '/v1.0/search' => sub {
my $c = shift;
my $v = $c->validation;
$v->optional('q');
@@ -133,7 +133,7 @@
};
# Textinfo fixtures
-get '/corpus/:corpusId/:docId/:textId' => sub {
+get '/v1.0/corpus/:corpusId/:docId/:textId' => sub {
my $c = shift;
my $file = join('_', (
@@ -152,7 +152,7 @@
# Matchinfo fixtures
-get '/corpus/:corpusId/:docId/:textId/:matchId/matchInfo' => sub {
+get '/v1.0/corpus/:corpusId/:docId/:textId/:matchId/matchInfo' => sub {
my $c = shift;
my $file = join('_', (
@@ -172,7 +172,7 @@
# Statistics endpoint
-get '/statistics' => sub {
+get '/v1.0/statistics' => sub {
my $c = shift;
my $v = $c->validation;
$v->optional('corpusQuery');
@@ -193,7 +193,7 @@
############
# Request API token
-get '/auth/logout' => sub {
+get '/v1.0/auth/logout' => sub {
my $c = shift;
if (my $auth = $c->req->headers->header('Authorization')) {
@@ -210,7 +210,7 @@
# Request API token
-get '/auth/apiToken' => sub {
+get '/v1.0/auth/apiToken' => sub {
my $c = shift;
# Get auth header
@@ -275,10 +275,12 @@
# Request API token
-post '/oauth2/token' => sub {
+post '/v1.0/oauth2/token' => sub {
my $c = shift;
- if ($c->param('grant_type') eq 'password') {
+ my $grant_type = $c->param('grant_type') // 'undefined';
+
+ if ($grant_type eq 'password') {
# Check for wrong client id
if ($c->param('client_id') ne '2') {
@@ -346,7 +348,7 @@
}
# Refresh token
- elsif ($c->param('grant_type') eq 'refresh_token') {
+ elsif ($grant_type eq 'refresh_token') {
return $c->render(
status => 200,
json => {
@@ -361,10 +363,11 @@
# Unknown token grant
else {
return $c->render(
+ status => 400,
json => {
"errors" => [
[
- 0, "Grant Type unknown", $c->param("grant_type")
+ 0, "Grant Type unknown", $grant_type
]
]
}
diff --git a/t/text_info.t b/t/text_info.t
index 49be159..82e6a97 100644
--- a/t/text_info.t
+++ b/t/text_info.t
@@ -7,7 +7,7 @@
#####################
# Start Fake server #
#####################
-my $mount_point = '/api/';
+my $mount_point = '/realapi/';
$ENV{KALAMAR_API} = $mount_point;
my $t = Test::Mojo->new('Kalamar');