diff --git a/CHANGELOG.md b/CHANGELOG.md index 0a210e1c1..27c0f5589 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -41,6 +41,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - Fixed dirty context (part 2 of PR #1328) when tls termination policy is in the policy chain [PR #1333](https://github.com/3scale/APIcast/pull/1333) - Fixed NGINX filters policy error [PR #1339](https://github.com/3scale/APIcast/pull/1339) [THREESCALE-7349](https://issues.redhat.com/browse/THREESCALE-7349) - Fix to avoid uninitialized variables when request URI is too large [PR #1340](https://github.com/3scale/APIcast/pull/1340) [THREESCALE-7906](https://issues.redhat.com/browse/THREESCALE-7906) +- Fixed issue where request path is stripped for proxied https requests [PR #1342](https://github.com/3scale/APIcast/pull/1342) [THREESCALE-8426](https://issues.redhat.com/browse/THREESCALE-8426) ### Added diff --git a/gateway/src/apicast/http_proxy.lua b/gateway/src/apicast/http_proxy.lua index 5a62e1bd1..66d5dca07 100644 --- a/gateway/src/apicast/http_proxy.lua +++ b/gateway/src/apicast/http_proxy.lua @@ -81,10 +81,6 @@ local function absolute_url(uri) ) end -local function current_path(uri) - return format('%s%s%s', uri.path or ngx.var.uri, ngx.var.is_args, ngx.var.query_string or '') -end - local function forward_https_request(proxy_uri, uri, skip_https_connect) -- This is needed to call ngx.req.get_body_data() below. ngx.req.read_body() @@ -93,7 +89,7 @@ local function forward_https_request(proxy_uri, uri, skip_https_connect) uri = uri, method = ngx.req.get_method(), headers = ngx.req.get_headers(0, true), - path = current_path(uri), + path = format('%s%s%s', ngx.var.uri, ngx.var.is_args, ngx.var.query_string or ''), -- We cannot use resty.http's .get_client_body_reader(). -- In POST requests with HTTPS, the result of that call is nil, and it diff --git a/t/http-proxy.t b/t/http-proxy.t index 06fc744fb..52af97ff2 100644 --- a/t/http-proxy.t +++ b/t/http-proxy.t @@ -1075,3 +1075,162 @@ Request body is bigger than client_body_buffer_size --- no_error_log [error] --- user_files fixture=tls.pl eval + + +=== TEST 21: https upstream API connection routes to the upstream (host + path) + request path +--- env eval +( + "https_proxy" => $ENV{TEST_NGINX_HTTPS_PROXY}, + 'BACKEND_ENDPOINT_OVERRIDE' => "http://test_backend.lvh.me:$ENV{TEST_NGINX_SERVER_PORT}" +) +--- configuration random_port env +{ + "services": [ + { + "backend_version": 1, + "proxy": { + "api_backend": "https://test-upstream.lvh.me:$TEST_NGINX_RANDOM_PORT/somepath", + "proxy_rules": [ + { "pattern": "/test", "http_method": "GET", "metric_system_name": "hits", "delta": 2 } + ], + "policy_chain": [ + {"name": "apicast","version": "builtin"} + ] + } + } + ] +} +--- backend +server_name test_backend.lvh.me; + + location /transactions/authrep.xml { + content_by_lua_block { + ngx.exit(ngx.OK) + } + } +--- upstream env +server_name test-upstream.lvh.me; + +listen $TEST_NGINX_RANDOM_PORT ssl; +ssl_certificate $TEST_NGINX_SERVER_ROOT/html/server.crt; +ssl_certificate_key $TEST_NGINX_SERVER_ROOT/html/server.key; +location /somepath { + echo_foreach_split '\r\n' $echo_client_request_headers; + echo $echo_it; + echo_end; + access_by_lua_block { + assert = require('luassert') + assert.equal('https', ngx.var.scheme) + assert.equal('$TEST_NGINX_RANDOM_PORT', ngx.var.server_port) + assert.equal('test-upstream.lvh.me', ngx.var.ssl_server_name) + } +} +--- request +GET /test?user_key=test3 +--- more_headers +User-Agent: Test::APIcast::Blackbox +ETag: foobar +--- expected_response_body_like_multiple eval +[[ + qr{GET \/somepath\/test\?user_key=test3 HTTP\/1\.1}, + qr{ETag\: foobar}, + qr{Connection\: close}, + qr{User\-Agent\: Test\:\:APIcast\:\:Blackbox}, + qr{Host\: test-upstream.lvh.me\:\d+} +]] +--- error_code: 200 +--- error_log env +proxy request: CONNECT test-upstream.lvh.me:$TEST_NGINX_RANDOM_PORT HTTP/1.1 +--- no_error_log +[error] +--- user_files fixture=tls.pl eval + + +=== TEST 22: https upstream API connection routes to the upstream (host + path) ++ request path with routing policy also enabled +--- env eval +( + "https_proxy" => $ENV{TEST_NGINX_HTTPS_PROXY}, + 'BACKEND_ENDPOINT_OVERRIDE' => "http://test_backend.lvh.me:$ENV{TEST_NGINX_SERVER_PORT}" +) +--- configuration random_port env +{ + "services": [ + { + "backend_version": 1, + "proxy": { + "api_backend": "https://test-upstream.lvh.me:$TEST_NGINX_RANDOM_PORT/somepath", + "proxy_rules": [ + { "pattern": "/", "http_method": "GET", "metric_system_name": "hits", "delta": 2 } + ], + "policy_chain": [ + { + "name": "apicast.policy.routing", + "configuration": { + "rules": [ + { + "url": "https://test-upstream.lvh.me:$TEST_NGINX_RANDOM_PORT/somepath", + "replace_path": "{{uri | remove_first: '/test'}}", + "condition": { + "operations": [ + { + "match": "path", + "op": "matches", + "value": "^(/test/.*|/test/?)" + } + ] + } + } + ] + } + }, + {"name": "apicast","version": "builtin"} + ] + } + } + ] +} +--- backend +server_name test_backend.lvh.me; + + location /transactions/authrep.xml { + content_by_lua_block { + ngx.exit(ngx.OK) + } + } +--- upstream env +server_name test-upstream.lvh.me; + +listen $TEST_NGINX_RANDOM_PORT ssl; +ssl_certificate $TEST_NGINX_SERVER_ROOT/html/server.crt; +ssl_certificate_key $TEST_NGINX_SERVER_ROOT/html/server.key; +location /somepath { + echo_foreach_split '\r\n' $echo_client_request_headers; + echo $echo_it; + echo_end; + access_by_lua_block { + assert = require('luassert') + assert.equal('https', ngx.var.scheme) + assert.equal('$TEST_NGINX_RANDOM_PORT', ngx.var.server_port) + assert.equal('test-upstream.lvh.me', ngx.var.ssl_server_name) + } +} +--- request +GET /test/foo/bar?user_key=test3 +--- more_headers +User-Agent: Test::APIcast::Blackbox +ETag: foobar +--- expected_response_body_like_multiple eval +[[ + qr{GET \/somepath\/foo\/bar\?user_key=test3 HTTP\/1\.1}, + qr{ETag\: foobar}, + qr{Connection\: close}, + qr{User\-Agent\: Test\:\:APIcast\:\:Blackbox}, + qr{Host\: test-upstream.lvh.me\:\d+} +]] +--- error_code: 200 +--- error_log env +proxy request: CONNECT test-upstream.lvh.me:$TEST_NGINX_RANDOM_PORT HTTP/1.1 +--- no_error_log +[error] +--- user_files fixture=tls.pl eval