Skip to content

Commit

Permalink
Adding "preserve_host" flag to APIs, closes #444
Browse files Browse the repository at this point in the history
  • Loading branch information
subnetmarco committed Aug 3, 2015
1 parent 6af2a17 commit 25053ce
Show file tree
Hide file tree
Showing 5 changed files with 50 additions and 5 deletions.
17 changes: 17 additions & 0 deletions database/migrations/cassandra/2015-08-21-813213_0.5.0.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
local Migration = {
name = "2015-08-21-813213_0.5.0",

up = function(options)
return [[
ALTER TABLE apis ADD preserve_host boolean;
]]
end,

down = function(options)
return [[
ALTER TABLE apis DROP preserve_host;
]]
end
}

return Migration
4 changes: 3 additions & 1 deletion kong.yml
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,8 @@ nginx: |
location / {
default_type 'text/plain';
# This property will be used later by proxy_pass
# These properties will be used later by proxy_pass
set $backend_host nil;
set $backend_url nil;
# Authenticate the user and load the API info
Expand All @@ -148,6 +149,7 @@ nginx: |
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Host $backend_host;
proxy_pass $backend_url;
proxy_pass_header Server;
Expand Down
3 changes: 2 additions & 1 deletion kong/dao/schemas/apis.lua
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ return {
regex = "([a-zA-Z0-9-]+(\\.[a-zA-Z0-9-]+)*)" },
path = { type = "string", unique = true, func = check_path },
strip_path = { type = "boolean" },
target_url = { type = "string", required = true, func = validate_target_url }
target_url = { type = "string", required = true, func = validate_target_url },
preserve_host = { type = "boolean" }
}
}
8 changes: 6 additions & 2 deletions kong/resolver/access.lua
Original file line number Diff line number Diff line change
Expand Up @@ -176,8 +176,12 @@ function _M.execute(conf)

-- Setting the backend URL for the proxy_pass directive
ngx.var.backend_url = get_backend_url(api)..request_uri
ngx.req.set_header("Host", get_host_from_url(ngx.var.backend_url))

if api.preserve_host then
ngx.var.backend_host = ngx.req.get_headers()["host"]
else
ngx.var.backend_host = get_host_from_url(ngx.var.backend_url)
end

ngx.ctx.api = api
end

Expand Down
23 changes: 22 additions & 1 deletion spec/integration/proxy/api_resolver_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ local http_client = require "kong.tools.http_client"

local STUB_GET_URL = spec_helper.STUB_GET_URL
local STUB_GET_SSL_URL = spec_helper.STUB_GET_SSL_URL
local PROXY_URL = spec_helper.PROXY_URL

-- Parses an SSL certificate returned by LuaSec
local function parse_cert(cert)
Expand All @@ -32,7 +33,9 @@ describe("Resolver", function()
{name = "tests stripped path resolver with pattern characters", target_url = "http://mockbin.com", path = "/mockbin-with-pattern/", strip_path = true},
{name = "tests deep path resolver", target_url = "http://mockbin.com", path = "/deep/path/", strip_path = true},
{name = "tests wildcard subdomain", target_url = "http://mockbin.com/status/200", public_dns = "*.wildcard.com"},
{name = "tests wildcard subdomain 2", target_url = "http://mockbin.com/status/201", public_dns = "wildcard.*"}
{name = "tests wildcard subdomain 2", target_url = "http://mockbin.com/status/201", public_dns = "wildcard.*"},
{name = "tests preserve host", public_dns = "httpbin-nopreserve.com", target_url = "http://httpbin.org"},

This comment has been minimized.

Copy link
@ahmadnassri

ahmadnassri Aug 4, 2015

Contributor

you can use mockbin.com & mockbin.org here

This comment has been minimized.

Copy link
@subnetmarco

subnetmarco Aug 4, 2015

Author Member

@ahmadnassri it doesn't work because of CloudFlare not being able to detect the host when it's not being preserved (which is exactly the problem we are trying to fix). HttpBin on the other side has nothing sitting in front of their web server, which makes it work.

The test is more reliable by using the same target_url for both the preserve and no-preserve tests, to avoid unexpected behavior.

This comment has been minimized.

Copy link
@ahmadnassri

ahmadnassri Aug 6, 2015

Contributor

that is correct, hopefully we're fixing that with the help of this patch :)

{name = "tests preserve host 2", public_dns = "httpbin-preserve.com", target_url = "http://httpbin.org", preserve_host = true}
},
plugin_configuration = {
{ name = "keyauth", value = {key_names = {"apikey"} }, __api = 2 }
Expand Down Expand Up @@ -192,4 +195,22 @@ describe("Resolver", function()
end)

end)

describe("Preseve Host", function()

it("should not preserve the host (default behavior)", function()
local response, status = http_client.get(PROXY_URL.."/get", nil, { host = "httpbin-nopreserve.com"})
assert.equal(200, status)
local parsed_response = cjson.decode(response)
assert.equal("httpbin.org", parsed_response.headers["Host"])
end)

it("should preserve the host (default behavior)", function()
local response, status = http_client.get(PROXY_URL.."/get", nil, { host = "httpbin-preserve.com"})
assert.equal(200, status)
local parsed_response = cjson.decode(response)
assert.equal("httpbin-preserve.com", parsed_response.headers["Host"])
end)

end)
end)

0 comments on commit 25053ce

Please # to comment.