Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

http_proxy: set Host domain correctly #1143

Merged
merged 1 commit into from
Jan 10, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
### Fixed

- When PATH routing was enabled the URL was not correctly escaped [THREESCALE-3468](https://issues.jboss.org/browse/THREESCALE-3468) [PR #1150](https://github.com/3scale/APIcast/pull/1150)
- Add the correct host header when using an http proxy [THREESCALE-4178](https://issues.jboss.org/browse/THREESCALE-4178) [PR #1143](https://github.com/3scale/APIcast/pull/1143)



### Fixed
Expand Down
3 changes: 2 additions & 1 deletion gateway/src/apicast/http_proxy.lua
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,8 @@ function _M.request(upstream, proxy_uri)

if uri.scheme == 'http' then -- rewrite the request to use http_proxy
local err
upstream:use_host_header(uri.host) -- to keep correct Host header in case we need to resolve it to IP
local host = upstream:set_host_header()
upstream:use_host_header(host)
upstream.servers, err = resolve_servers(proxy_uri)
if err then
ngx.log(ngx.WARN, "HTTP proxy is set, but no servers have been resolved, err: ", err)
Expand Down
29 changes: 25 additions & 4 deletions gateway/src/apicast/upstream.lua
Original file line number Diff line number Diff line change
Expand Up @@ -138,11 +138,13 @@ end

--- Rewrite request Host header to what is provided in the argument or in the URL.
function _M:rewrite_request()
local uri = self.uri

if not uri then return nil, 'not initialized' end
local _, err = self:set_host_header()
if err then
return nil, 'not initialized'
end

ngx.req.set_header('Host', self.host or host_header(uri))
local uri = self.uri

if uri.path then
ngx.req.set_uri(prefix_path(uri.path))
Expand All @@ -162,6 +164,22 @@ local function exec(self)
end
end

function _M:set_host_header()
if self.host then
ngx.req.set_header('Host', self.host)
return self.host, nil
end

-- set Host from uri if Host is not defined
local uri = self.uri
if not uri then
return nil, "Upstream URI not initialized"
end
local host = host_header(uri)
ngx.req.set_header('Host', host)
return host, nil
end

--- Execute the upstream.
--- @tparam table context any table (policy context, ngx.ctx) to store the upstream for later use by balancer
function _M:call(context)
Expand All @@ -182,7 +200,10 @@ function _M:call(context)
-- to a proxy
http_proxy.request(self, proxy_uri)
else
self:rewrite_request()
local err = self:rewrite_request()
if err then
ngx.log(ngx.WARN, "Upstream rewrite request failed:", err)
end
end

if not self.servers then self:resolve() end
Expand Down
51 changes: 50 additions & 1 deletion spec/upstream_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -296,9 +296,58 @@ describe('Upstream', function()
local host = 'http://another_host'

upstream:use_host_header(host)

upstream:rewrite_request()
assert.spy(ngx.req.set_header).was_called_with('Host', host)
end)
end)

describe(".set_host_header", function()

before_each(stub_ngx_request)

it('self.host is defined', function()
local host = "test.com"
local upstream = Upstream.new('http://example.com')
upstream:use_host_header(host)

local tmp_host, err = upstream:set_host_header()

assert.equal(tmp_host, host)
assert.falsy(err)
assert.spy(ngx.req.set_header).was_called_with('Host', host)
end)

it('self.uri is not defined', function()
local host = "test.com"
local upstream = Upstream.new('http://example.com')
upstream.uri = nil

local tmp_host, err = upstream:set_host_header()

assert.falsy(tmp_host, host)
assert.equal(err, "Upstream URI not initialized")
end)

it('self.uri is defined in a not default port', function()
local expected_host = "example.com:10000"
local upstream = Upstream.new('http://example.com:10000')

local tmp_host, err = upstream:set_host_header()

assert.equal(tmp_host, expected_host)
assert.falsy(err)
assert.spy(ngx.req.set_header).was_called_with('Host', expected_host)
end)

it('self.uri is defined in a default port', function()
local expected_host = "example.com"
local upstream = Upstream.new('http://example.com')

local tmp_host, err = upstream:set_host_header()

assert.equal(tmp_host, expected_host)
assert.falsy(err)
assert.spy(ngx.req.set_header).was_called_with('Host', expected_host)
end)
end)
end)
28 changes: 22 additions & 6 deletions t/apicast-policy-http-proxy.t
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,13 @@ __DATA__
}
--- upstream
location / {
echo 'yay, api backend';
access_by_lua_block {
local host = ngx.req.get_headers()["Host"]
local result = string.match(host, "^test:")
local assert = require('luassert')
assert.equals(result, "test:")
ngx.say("yay, api backend")
}
}
--- request
GET /?user_key=value
Expand Down Expand Up @@ -95,7 +101,13 @@ using proxy: $TEST_NGINX_HTTP_PROXY
}
--- upstream
location / {
echo 'yay, api backend';
access_by_lua_block {
local host = ngx.req.get_headers()["Host"]
local result = string.match(host, "^test:")
local assert = require('luassert')
assert.equals(result, "test:")
ngx.say("yay, api backend")
}
}
--- request
GET /?user_key=value
Expand Down Expand Up @@ -150,10 +162,14 @@ location /test {
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', ngx.var.ssl_server_name)
assert = require('luassert')
assert.equal('https', ngx.var.scheme)
assert.equal('$TEST_NGINX_RANDOM_PORT', ngx.var.server_port)
assert.equal('test', ngx.var.ssl_server_name)

local host = ngx.req.get_headers()["Host"]
local result = string.match(host, "^test:")
assert.equals(result, "test:")
}
}
--- request
Expand Down
14 changes: 8 additions & 6 deletions t/http-proxy.t
Original file line number Diff line number Diff line change
Expand Up @@ -159,8 +159,8 @@ proxy request: CONNECT 127.0.0.1:$TEST_NGINX_RANDOM_PORT
}
--- request
GET /?user_key=value
--- response_body
yay, api backend: test
--- response_body_like
yay, api backend: test:.*
--- error_code: 200
--- error_log env
proxy request: GET http://127.0.0.1:$TEST_NGINX_SERVER_PORT/transactions/authrep.xml?service_token=token-value&service_id=42&usage%5Bhits%5D=2&user_key=value HTTP/1.1
Expand Down Expand Up @@ -282,8 +282,8 @@ location /apicast {
proxy_set_header Host localhost;
proxy_pass http://$server_addr:$apicast_port;
}
--- response_body
yay, api backend: test
--- response_body_like
yay, api backend: test:.*
--- error_code: 200
--- error_log env
proxy request: GET http://127.0.0.1:$TEST_NGINX_SERVER_PORT/transactions/authrep.xml?service_token=token-value&service_id=42&usage%5Bhits%5D=2&user_key=value HTTP/1.1
Expand Down Expand Up @@ -398,11 +398,13 @@ apicast cache write key: 42:value:usage%5Bhits%5D=2, ttl: nil, context: ngx.time
--- upstream
location /test {
echo 'yay, api backend: $http_host, uri: $uri, is_args: $is_args, args: $args';
# echo 'yay, api backend: $http_host, uri:';
}
--- request
GET /test?user_key=value
--- response_body
yay, api backend: test, uri: /test, is_args: ?, args: user_key=value

--- response_body_like eval
qw/yay, api backend: test:ooo\d+, uri: \/test, is_args: \?, args: user_key=value/
--- error_code: 200
--- error_log env
proxy request: GET http://127.0.0.1:$TEST_NGINX_SERVER_PORT/test?user_key=value HTTP/1.1
Expand Down