-
Notifications
You must be signed in to change notification settings - Fork 4.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(core) implement X-Kong-Upstream-Status header
If enabled, the `X-Kong-Upstream-Status` header is injected by Kong in the response for the client. It contains the status code returned by the upstream response. This header is disabled by default, and can be enabled by adding it to the `headers` configuration property. From #3263 Signed-off-by: Thibault Charbonnier <thibaultcha@me.com>
- Loading branch information
1 parent
a6dee10
commit 60c335e
Showing
6 changed files
with
216 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
194 changes: 194 additions & 0 deletions
194
spec/02-integration/05-proxy/14-upstream-status-header_spec.lua
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,194 @@ | ||
local helpers = require "spec.helpers" | ||
local constants = require "kong.constants" | ||
|
||
|
||
local function setup_db() | ||
local bp = helpers.get_db_utils() | ||
|
||
local service = bp.services:insert { | ||
host = helpers.mock_upstream_host, | ||
port = helpers.mock_upstream_port, | ||
protocol = helpers.mock_upstream_protocol, | ||
} | ||
|
||
bp.routes:insert { | ||
protocols = { "http" }, | ||
paths = { "/status/200" }, | ||
service = service, | ||
} | ||
|
||
local route2 = bp.routes:insert { | ||
protocols = { "http" }, | ||
paths = { "/status/plugin-changes-200-to-500" }, | ||
service = service, | ||
} | ||
|
||
bp.plugins:insert { | ||
name = "dummy", | ||
route_id = route2.id, | ||
config = { | ||
resp_code = 500, | ||
} | ||
} | ||
|
||
local route3 = bp.routes:insert { | ||
protocols = { "http" }, | ||
paths = { "/status/non-proxied-request" }, | ||
service = service, | ||
} | ||
|
||
bp.plugins:insert { | ||
name = "key-auth", | ||
route_id = route3.id, | ||
} | ||
end | ||
|
||
|
||
describe(constants.HEADERS.UPSTREAM_STATUS .. " header", function() | ||
local client | ||
|
||
describe("should be same as upstream status code", function() | ||
setup(function() | ||
setup_db() | ||
|
||
assert(helpers.start_kong { | ||
nginx_conf = "spec/fixtures/custom_nginx.template", | ||
headers = "server_tokens,latency_tokens,x-kong-upstream-status", | ||
custom_plugins = "dummy", | ||
}) | ||
|
||
client = helpers.proxy_client() | ||
end) | ||
|
||
teardown(function() | ||
if client then | ||
client:close() | ||
end | ||
|
||
helpers.stop_kong() | ||
end) | ||
|
||
it("when no plugin changes status code", function() | ||
local res = assert(client:send { | ||
method = "GET", | ||
path = "/status/200", | ||
headers = { | ||
host = helpers.mock_upstream_host, | ||
} | ||
}) | ||
assert.res_status(200, res) | ||
assert.equal("200", res.headers[constants.HEADERS.UPSTREAM_STATUS]) | ||
end) | ||
|
||
it("when a plugin changes status code", function() | ||
local res = assert(client:send { | ||
method = "GET", | ||
host = helpers.mock_upstream_host, | ||
path = "/status/plugin-changes-200-to-500", | ||
headers = { | ||
["Host"] = helpers.mock_upstream_host, | ||
} | ||
}) | ||
assert.res_status(500, res) | ||
assert.equal("200", res.headers[constants.HEADERS.UPSTREAM_STATUS]) | ||
end) | ||
end) | ||
|
||
describe("is not injected with default configuration", function() | ||
setup(function() | ||
setup_db() | ||
|
||
assert(helpers.start_kong { | ||
nginx_conf = "spec/fixtures/custom_nginx.template", | ||
}) | ||
end) | ||
|
||
teardown(function() | ||
if client then | ||
client:close() | ||
end | ||
|
||
helpers.stop_kong() | ||
end) | ||
|
||
it("", function() | ||
local client = helpers.proxy_client() | ||
local res = assert(client:send { | ||
method = "GET", | ||
path = "/status/200", | ||
headers = { | ||
host = helpers.mock_upstream_host, | ||
} | ||
}) | ||
assert.res_status(200, res) | ||
assert.is_nil(res.headers[constants.HEADERS.UPSTREAM_STATUS]) | ||
end) | ||
end) | ||
|
||
describe("is injected with configuration [headers=X-Kong-Upstream-Status]", function() | ||
setup(function() | ||
setup_db() | ||
|
||
assert(helpers.start_kong { | ||
nginx_conf = "spec/fixtures/custom_nginx.template", | ||
headers = "X-Kong-Upstream-Status", | ||
}) | ||
end) | ||
|
||
teardown(function() | ||
if client then | ||
client:close() | ||
end | ||
|
||
helpers.stop_kong() | ||
end) | ||
|
||
it("", function() | ||
local client = helpers.proxy_client() | ||
local res = assert(client:send { | ||
method = "GET", | ||
path = "/status/200", | ||
headers = { | ||
host = helpers.mock_upstream_host, | ||
} | ||
}) | ||
assert.res_status(200, res) | ||
assert("200", res.headers[constants.HEADERS.UPSTREAM_STATUS]) | ||
end) | ||
end) | ||
|
||
describe("short-circuited requests", function() | ||
setup(function() | ||
setup_db() | ||
|
||
assert(helpers.start_kong { | ||
nginx_conf = "spec/fixtures/custom_nginx.template", | ||
headers = "X-Kong-Upstream-Status", | ||
}) | ||
end) | ||
|
||
teardown(function() | ||
if client then | ||
client:close() | ||
end | ||
|
||
helpers.stop_kong() | ||
end) | ||
|
||
it("empty when rejected by authentication plugin", function() | ||
-- Added as a regression test during the merge of this patch to ensure | ||
-- the logic in the header_filter phase is defensive enough. | ||
-- As a result, the logic was moved within the `if proxied` branch. | ||
local client = helpers.proxy_client() | ||
local res = assert(client:send { | ||
method = "GET", | ||
path = "/status/non-proxied-request", | ||
headers = { | ||
host = helpers.mock_upstream_host, | ||
} | ||
}) | ||
assert.res_status(401, res) | ||
assert.is_nil(res.headers[constants.HEADERS.UPSTREAM_STATUS]) | ||
end) | ||
end) | ||
end) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters