diff --git a/kong/globalpatches.lua b/kong/globalpatches.lua index 61ca747fd4d..65f2d8cb470 100644 --- a/kong/globalpatches.lua +++ b/kong/globalpatches.lua @@ -127,6 +127,7 @@ return function(options) local get_uri_args = ngx.req.get_uri_args local get_post_args = ngx.req.get_post_args local decode_args = ngx.decode_args + local read_req_body = ngx.req.read_body local DEFAULT_MAX_REQ_HEADERS = 100 local DEFAULT_MAX_RESP_HEADERS = 100 @@ -232,6 +233,16 @@ return function(options) return decode_args_real(str, max_args or MAX_DECODE_ARGS, ...) end -- ] + + -- READ REQUEST BODY [ + _G.ngx.req.read_body = function() + -- for the same request, only one `read_body` call is needed + if not ngx.ctx._req_body_has_read then + read_req_body() + ngx.ctx._req_body_has_read = true + end + end + -- ] end end diff --git a/kong/pdk/request.lua b/kong/pdk/request.lua index fbd55a74194..aa648c42fd3 100644 --- a/kong/pdk/request.lua +++ b/kong/pdk/request.lua @@ -98,7 +98,7 @@ local function new(self) function _REQUEST.get_scheme() check_phase(PHASES.request) - return var.scheme + return ngx.ctx.scheme or var.scheme end @@ -116,7 +116,7 @@ local function new(self) function _REQUEST.get_host() check_phase(PHASES.request) - return var.host + return ngx.ctx.host or var.host end @@ -437,7 +437,7 @@ local function new(self) function _REQUEST.get_raw_path() check_phase(PHASES.request) - local uri = var.request_uri or "" + local uri = ngx.ctx.request_uri or var.request_uri or "" local s = find(uri, "?", 2, true) return s and sub(uri, 1, s - 1) or uri end @@ -456,7 +456,7 @@ local function new(self) -- kong.request.get_path_with_query() -- "/v1/movies?movie=foo" function _REQUEST.get_path_with_query() check_phase(PHASES.request) - return var.request_uri or "" + return ngx.ctx.request_uri or var.request_uri or "" end @@ -820,7 +820,6 @@ local function new(self) -- body.age -- "42" function _REQUEST.get_body(mimetype, max_args, max_allowed_file_size) check_phase(before_content) - local content_type = mimetype or _REQUEST.get_header(CONTENT_TYPE) if not content_type then return nil, "missing content type" diff --git a/kong/pdk/response.lua b/kong/pdk/response.lua index 844d5c7d139..bb6bee29fc6 100644 --- a/kong/pdk/response.lua +++ b/kong/pdk/response.lua @@ -244,7 +244,7 @@ local function new(self, major_version) error("header name must be a string", 2) end - local header_value = _RESPONSE.get_headers()[name] + local header_value = ngx.header[name] if type(header_value) == "table" then return header_value[1] end diff --git a/kong/pdk/service/request.lua b/kong/pdk/service/request.lua index f583d390fa1..a20daf4bbb3 100644 --- a/kong/pdk/service/request.lua +++ b/kong/pdk/service/request.lua @@ -23,6 +23,7 @@ local validate_header = checks.validate_header local validate_headers = checks.validate_headers local check_phase = phase_checker.check local escape = require("kong.tools.uri").escape +local get_header = require("kong.tools.http").get_header local search_remove = require("resty.ada.search").remove @@ -653,7 +654,7 @@ local function new(self) error("mime must be a string", 2) end if not mime then - mime = ngx.req.get_headers()[CONTENT_TYPE] + mime = get_header(CONTENT_TYPE) if not mime then return nil, "content type was neither explicitly given " .. "as an argument or received as a header" diff --git a/kong/pdk/service/response.lua b/kong/pdk/service/response.lua index 5a6621abf54..522d2cddeee 100644 --- a/kong/pdk/service/response.lua +++ b/kong/pdk/service/response.lua @@ -313,7 +313,8 @@ local function new(pdk, major_version) -- local body = kong.service.response.get_body() function response.get_body(mimetype, max_args) check_phase(header_body_log) - if not ngx.ctx.buffered_proxying then + local ctx = ngx.ctx + if not ctx.buffered_proxying then error("service body is only available with buffered proxying " .. "(see: kong.service.request.enable_buffering function)", 2) end @@ -344,7 +345,7 @@ local function new(pdk, major_version) end end - local body = response.get_raw_body() + local body = ctx.buffered_body or "" local pargs, err = ngx.decode_args(body, max_args or MAX_POST_ARGS_DEFAULT) if not pargs then return nil, err, CONTENT_TYPE_POST @@ -353,7 +354,7 @@ local function new(pdk, major_version) return pargs, nil, CONTENT_TYPE_POST elseif find(content_type_lower, CONTENT_TYPE_JSON, 1, true) == 1 then - local body = response.get_raw_body() + local body = ctx.buffered_body or "" local json = cjson.decode_with_array_mt(body) if type(json) ~= "table" then return nil, "invalid json body", CONTENT_TYPE_JSON @@ -362,7 +363,7 @@ local function new(pdk, major_version) return json, nil, CONTENT_TYPE_JSON elseif find(content_type_lower, CONTENT_TYPE_FORM_DATA, 1, true) == 1 then - local body = response.get_raw_body() + local body = ctx.buffered_body or "" local parts = multipart(body, content_type) if not parts then diff --git a/kong/plugins/basic-auth/access.lua b/kong/plugins/basic-auth/access.lua index d989738d5cb..f84eda0586d 100644 --- a/kong/plugins/basic-auth/access.lua +++ b/kong/plugins/basic-auth/access.lua @@ -28,9 +28,9 @@ local _M = {} -- @param {table} conf Plugin config -- @return {string} public_key -- @return {string} private_key -local function retrieve_credentials(header_name, conf) +local function retrieve_credentials(header_name, conf, header) local username, password - local authorization_header = kong.request.get_header(header_name) + local authorization_header = header or kong.request.get_header(header_name) if authorization_header then local iterator, iter_err = re_gmatch(authorization_header, "\\s*[Bb]asic\\s*(.+)", "oj") @@ -158,21 +158,23 @@ end local function do_authentication(conf) local www_authenticate = "Basic realm=\"" .. conf.realm .. "\"" + local authorization = kong.request.get_header("authorization") + local proxy_authorization = kong.request.get_header("proxy-authorization") -- If both headers are missing, return 401 - if not (kong.request.get_header("authorization") or kong.request.get_header("proxy-authorization")) then + if not (authorization or proxy_authorization) then return false, unauthorized("Unauthorized", www_authenticate) end local credential - local given_username, given_password = retrieve_credentials("proxy-authorization", conf) + local given_username, given_password = retrieve_credentials("proxy-authorization", conf, proxy_authorization) if given_username and given_password then credential = load_credential_from_db(given_username) end -- Try with the authorization header if not credential then - given_username, given_password = retrieve_credentials("authorization", conf) + given_username, given_password = retrieve_credentials("authorization", conf, authorization) if given_username and given_password then credential = load_credential_from_db(given_username) else diff --git a/kong/plugins/cors/handler.lua b/kong/plugins/cors/handler.lua index 3d62be38818..029744132d2 100644 --- a/kong/plugins/cors/handler.lua +++ b/kong/plugins/cors/handler.lua @@ -61,7 +61,7 @@ local function add_vary_header(header_filter) end end -local function configure_origin(conf, header_filter) +local function configure_origin(conf, header_filter, req_origin) local n_origins = conf.origins ~= nil and #conf.origins or 0 local set_header = kong.response.set_header @@ -89,7 +89,6 @@ local function configure_origin(conf, header_filter) end end - local req_origin = kong.request.get_header("origin") if req_origin then local cached_domains = config_cache[conf] if not cached_domains then @@ -167,7 +166,7 @@ local function configure_origin(conf, header_filter) end -local function configure_credentials(conf, allow_all, header_filter) +local function configure_credentials(conf, allow_all, header_filter, req_origin) local set_header = kong.response.set_header if not conf.credentials then @@ -181,7 +180,6 @@ local function configure_credentials(conf, allow_all, header_filter) -- Access-Control-Allow-Origin is '*', must change it because ACAC cannot -- be 'true' if ACAO is '*'. - local req_origin = kong.request.get_header("origin") if req_origin then add_vary_header(header_filter) set_header("Access-Control-Allow-Origin", req_origin) @@ -191,8 +189,9 @@ end function CorsHandler:access(conf) + local req_origin = kong.request.get_header("Origin") if kong.request.get_method() ~= "OPTIONS" - or not kong.request.get_header("Origin") + or not req_origin or not kong.request.get_header("Access-Control-Request-Method") then return @@ -207,8 +206,8 @@ function CorsHandler:access(conf) return end - local allow_all = configure_origin(conf, false) - configure_credentials(conf, allow_all, false) + local allow_all = configure_origin(conf, false, req_origin) + configure_credentials(conf, allow_all, false, req_origin) local set_header = kong.response.set_header @@ -247,8 +246,9 @@ function CorsHandler:header_filter(conf) return end - local allow_all = configure_origin(conf, true) - configure_credentials(conf, allow_all, true) + local req_origin = kong.request.get_header("Origin") + local allow_all = configure_origin(conf, true, req_origin) + configure_credentials(conf, allow_all, true, req_origin) if conf.exposed_headers and #conf.exposed_headers > 0 then kong.response.set_header("Access-Control-Expose-Headers", diff --git a/kong/runloop/handler.lua b/kong/runloop/handler.lua index 37efc7f8bb7..9d6573917d0 100644 --- a/kong/runloop/handler.lua +++ b/kong/runloop/handler.lua @@ -1166,7 +1166,8 @@ return { ctx.scheme = var.scheme ctx.request_uri = var.request_uri - + ctx.host = var.host + -- trace router local span = instrumentation.router() -- create the balancer span "in advance" so its ID is available @@ -1208,7 +1209,7 @@ return { req_dyn_hook_run_hook("timing", "workspace_id:got", ctx.workspace) end - local host = var.host + local host = ctx.host local port = ctx.host_port or tonumber(var.server_port, 10) local route = match_t.route diff --git a/t/01-pdk/08-response/02-get_header.t b/t/01-pdk/08-response/02-get_header.t index fd565ec4d7a..c6bec909981 100644 --- a/t/01-pdk/08-response/02-get_header.t +++ b/t/01-pdk/08-response/02-get_header.t @@ -116,7 +116,7 @@ X-Missing: nil -=== TEST 4: response.get_header() returns nil when response header does not fit in default max_headers +=== TEST 4: response.get_header() returns existing header will not limited by get_headers() default max_headers configuration --- http_config eval: $t::Util::HttpConfig --- config location = /t { @@ -145,7 +145,7 @@ X-Missing: nil --- request GET /t --- response_body chop -accept header value: nil +accept header value: string --- no_error_log [error]