Skip to content

Commit

Permalink
experimental path based routing
Browse files Browse the repository at this point in the history
1. match services by host
2. when host matches, try to match mapping rules
3. if no services match both host and mapping rules
4. fallback to matching by host
  • Loading branch information
mikz committed Sep 13, 2016
1 parent 5dc4061 commit 20467a7
Show file tree
Hide file tree
Showing 3 changed files with 119 additions and 1 deletion.
1 change: 1 addition & 0 deletions conf/nginx.conf
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ worker_processes 1;
env THREESCALE_DEPLOYMENT_ENV;
env THREESCALE_PORTAL_ENDPOINT;
env THREESCALE_CONFIG_FILE;
env APICAST_PATH_ROUTING_ENABLED;

# error_log stderr notice;
# error_log logs/error.log warn;
Expand Down
29 changes: 28 additions & 1 deletion src/provider.lua
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ local function get_debug_value()
end
end

function _M.find_service(host)
local function find_service_strict(host)
for _,service in ipairs(_M.services or {}) do
for _,_host in ipairs(service.hosts or {}) do
if _host == host then
Expand All @@ -141,6 +141,33 @@ function _M.find_service(host)
end
end

local function find_service_cascade(host)
local request = ngx.var.request
for _,service in ipairs(_M.services or {}) do
for _,_host in ipairs(service.hosts or {}) do
if _host == host then
local name = service.system_name or service.id
ngx.log(ngx.DEBUG, 'service ' .. name .. ' matched host ' .. _host)
local usage, matched_patterns = service:extract_usage(request)

if next(usage) and matched_patterns ~= '' then
ngx.log(ngx.DEBUG, 'service ' .. name .. ' matched patterns ' .. matched_patterns)
return service
end
end
end
end

return find_service_strict(host)
end

if os.getenv('APICAST_PATH_ROUTING_ENABLED') then
ngx.log(ngx.WARN, 'apicast experimental path routing enabled')
_M.find_service = find_service_cascade
else
_M.find_service = find_service_strict
end

local http = {
get = function(url)
ngx.log(ngx.INFO, '[http] requesting ' .. url)
Expand Down
90 changes: 90 additions & 0 deletions t/004-apicast-path-routing.t
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
use Test::Nginx::Socket::Lua 'no_plan';
use Cwd qw(cwd);

my $pwd = cwd();

$ENV{TEST_NGINX_LUA_PATH} = "$pwd/src/?.lua;;";

$ENV{TEST_NGINX_BACKEND_CONFIG} = "$pwd/conf.d/backend.conf";
$ENV{TEST_NGINX_APICAST_CONFIG} = "$pwd/conf.d/apicast.conf";

log_level('debug');
repeat_each(1);
no_root_location();
run_tests();

__DATA__
=== TEST 1: multi service configuration with path based routing
Two services can exist together and are split by their hostname and mapping rules.
--- main_config
env APICAST_PATH_ROUTING_ENABLED=1;
--- http_config
lua_package_path "$TEST_NGINX_LUA_PATH";
init_by_lua_block {
require('configuration').save({
services = {
{
id = 42,
backend_version = 1,
proxy = {
api_backend = "http://127.0.0.1:$TEST_NGINX_SERVER_PORT/api-backend/one/",
hosts = { 'same' },
backend_authentication_type = 'service_token',
backend_authentication_value = 'service-one',
proxy_rules = {
{ pattern = '/one', http_method = 'GET', metric_system_name = 'one', delta = 1 }
}
}
},
{
id = 21,
backend_version = 2,
proxy = {
api_backend = "http://127.0.0.1:$TEST_NGINX_SERVER_PORT/api-backend/two/",
hosts = { 'same' },
backend_authentication_type = 'service_token',
backend_authentication_value = 'service-two',
proxy_rules = {
{ pattern = '/two', http_method = 'GET', metric_system_name = 'two', delta = 2 }
}
}
}
}
})
}
lua_shared_dict api_keys 10m;
--- config
include $TEST_NGINX_APICAST_CONFIG;
set $backend_endpoint 'http://127.0.0.1:$TEST_NGINX_SERVER_PORT';
location /transactions/authrep.xml {
content_by_lua_block { ngx.exit(200) }
}
location ~ /api-backend(/.+) {
echo 'yay, api backend: $1';
}
location ~ /test/(.+) {
proxy_pass $scheme://127.0.0.1:$server_port/$1$is_args$args;
proxy_set_header Host same;
}
location = /t {
echo_subrequest GET /test/one -q user_key=one-key;
echo_subrequest GET /test/two -q app_id=two-id&app_key=two-key;
}
--- request
GET /t
--- response_body
yay, api backend: /one/
yay, api backend: /two/
--- error_code: 200
--- grep_error_log eval: qr/apicast cache (?:hit|miss|write) key: [^,\s]+/
--- grep_error_log_out
apicast cache miss key: 42:one-key:usage[one]=1
apicast cache write key: 42:one-key:usage[one]=1
apicast cache miss key: 21:two-id:two-key:usage[two]=2
apicast cache write key: 21:two-id:two-key:usage[two]=2

0 comments on commit 20467a7

Please sign in to comment.