Kong: the PDK is the supported way to touch a request

kong.request reads what the client sent, kong.service.request changes what the upstream receives, and kong.response shapes what goes back. Using ngx.* directly bypasses Kong's own bookkeeping.

Code
-- read
local path   = kong.request.get_path()
local method = kong.request.get_method()
local token  = kong.request.get_header("authorization")
local q      = kong.request.get_query_arg("page")

-- change what the upstream gets
kong.service.request.set_header("X-Tenant", "acme")
kong.service.request.clear_header("Cookie")

-- answer without proxying at all
if not token then
  return kong.response.exit(401, { message = "token required" },
                            { ["Content-Type"] = "application/json" })
end
Output
# kong.response.exit stops the plugin chain and replies immediately - the
# upstream is never called. It is how every auth plugin rejects a request.
#
# kong.request.get_header vs kong.service.request.set_header is the
# distinction people miss: the first reads the CLIENT's request, the second
# edits the request Kong is about to make. Setting a header with
# kong.response.set_header in the access phase does nothing useful.
Advertisement

Run this yourself in the Online Java Compiler, spin up a live REST API in the API Sandbox, or practise with Java interview questions.

Published 2026-08-25