Kong插件开发工具包
插件开发工具包(或称 PDK),是一组 Lua 方法和变量,插件可以使用这些方法和变量实现自己的逻辑,PDK 最初在 Kong 0.14.0 中发布,PDK 保证从 1.0.0 版本开始向前兼容,插件可以使用 PDK 里面的函数和变量来执行各种网关操作,如果用户尝试实现一些与 Kong 交互的逻辑时(例如检索请求头、生成响应、记录错误或调试信息),可以参考插件开发工具包。
插件执行顺序
某些插件可能依赖其他插件来执行某些操作,例如:依赖消费者身份的插件必须在身份验证插件之后运行,考虑到这一点,Kong 在插件执行期间定义了优先级,以确保插件执行顺序,用户可以定义这个属性值来配置插件优先级:
CustomHandler.PRIORITY = 10
优先级越高,插件执行的越早(例如 :access()、:log() 方法),预绑定插件的优先级如下:
插件 | 优先级 |
---|---|
pre-function | +inf |
zipkin | 100000 |
ip-restriction | 3000 |
bot-detection | 2500 |
cors | 2000 |
session | 1900 |
kubernetes-sidecar-injector | 1006 |
jwt | 1005 |
oauth2 | 1004 |
key-auth | 1003 |
ldap-auth | 1002 |
basic-auth | 1001 |
hmac-auth | 1000 |
request-size-limiting | 951 |
acl | 950 |
rate-limiting | 901 |
response-ratelimiting | 900 |
request-transformer | 801 |
response-transformer | 800 |
aws-lambda | 750 |
azure-functions | 749 |
prometheus | 13 |
http-log | 12 |
statsd | 11 |
datadog | 10 |
file-log | 9 |
udp-log | 8 |
tcp-log | 7 |
loggly | 6 |
syslog | 4 |
request-termination | 2 |
correlation-id | 1 |
post-function | -1000 |
Kong插件开发工具包说明
kong.version
当前 Kong 节点的版本号,字符串格式
用法:
print(kong.version) -- "0.14.0"
kong.version_num
当前 Kong 节点的版本号,用来做版本比较,整数格式
用法:
if kong.version_num < 13000 then -- 000.130.00 -> 0.13.0
-- no support for Routes & Services
end
kong.pdk_major_version
当前 PDK 的大版本号,整数格式
用法:
if kong.pdk_version_num < 2 then
-- PDK is below version 2
end
kong.pdk_version
当前 PDK 的版本号,字符串格式
用法:
print(kong.pdk_version) -- "1.0.0"
kong.configuration
当前 Kong 节点的配置信息,基于配置文件和环境变量,文件中以逗号分隔的列表此处显示为字符串数组
用法:
print(kong.configuration.prefix) -- "/usr/local/kong"
-- this table is read-only; the following throws an error:
kong.configuration.prefix = "foo"
kong.db
Kong 的 DAO 实例(kong.db 模块),包含对多个实体的访问对象
用法:
kong.db.services:insert()
kong.db.routes:select()
kong.dns
Kong 的 DNS 解析器实例
kong.worker_events
Kong 的 IPC 模块实例,用于内部 worker 进程通信
kong.cluster_events
Kong 的集群事件模块实例,用于节点间通信
kong.cache
Kong 缓存对象实例
kong.client
Client 模块是一组方法,通过请求上下文,用于检索连接到Kong的客户端的信息
kong.client.get_ip()
返回发起请求的远程 IP 地址,它将始终返回直连到 Kong 的客户端的地址,所以,当 Kong 之前有负载均衡器的情况下,这个方法会返回负载均衡器的地址,而不是下游客户端的地址
用法:
-- Given a client with IP 127.0.0.1 making connection through
-- a load balancer with IP 10.0.0.1 to Kong answering the request for
-- https://example.com:1234/v1/movies
kong.client.get_ip() -- "10.0.0.1"
kong.client.get_forwarded_ip()
返回发起请求的远程 IP 地址,与 kong.client.get_ip
不同,这个方法会考虑到位于 Kong 之前的负载均衡器以及转发地址,这个方法是否返回转发地址取决于几个 Kong 配置参数:trusted_ips
、real_ip_header
、real_ip_recursive
用法:
-- Given a client with IP 127.0.0.1 making connection through
-- a load balancer with IP 10.0.0.1 to Kong answering the request for
-- https://username:password@example.com:1234/v1/movies
kong.request.get_forwarded_ip() -- "127.0.0.1"
-- Note: assuming that 10.0.0.1 is one of the trusted IPs, and that
-- the load balancer adds the right headers matching with the configuration
-- of `real_ip_header`, e.g. `proxy_protocol`.
kong.client.get_port()
返回发起请求的端口,它将始终返回直连到 Kong 的客户端的端口,所以,当 Kong 之前有负载均衡器的情况下,这个方法会返回负载均衡器的端口,而不是下游客户端的端口
用法:
-- [client]:40000 <-> 80:[balancer]:30000 <-> 80:[kong]:20000 <-> 80:[service]
kong.client.get_port() -- 30000
kong.client.get_forwarded_port()
返回发起请求的端口,与 kong.client.get_port
不同,这个方法会考虑到位于 Kong 之前的负载均衡器以及转发端口,这个方法是否返回转发端口取决于几个 Kong 配置参数:trusted_ips
、real_ip_header
、real_ip_recursive
用法:
-- [client]:40000 <-> 80:[balancer]:30000 <-> 80:[kong]:20000 <-> 80:[service]
kong.client.get_forwarded_port() -- 40000
-- Note: assuming that [balancer] is one of the trusted IPs, and that
-- the load balancer adds the right headers matching with the configuration
-- of `real_ip_header`, e.g. `proxy_protocol`.
kong.client.get_credential()
返回当前经过身份验证的消费者的凭证,如果未设置,返回 nil
用法:
local credential = kong.client.get_credential()
if credential then
consumer_id = credential.consumer_id
else
-- request not authenticated yet
end
kong.client.get_consumer()
返回当前经过身份验证的消费者实体,如果未设置,返回 nil
用法:
local consumer = kong.client.get_consumer()
if consumer then
consumer_id = consumer.id
else
-- request not authenticated yet, or a credential
-- without a consumer (external auth)
end
kong.client.authenticate(consumer, credential)
为当前请求设置经过身份验证的消费者或凭证,消费者和凭证必须存在一个,否则方法将报错
参数:consumer(table|nil)
:设置消费者,如果不设置值,之前存在的值会被清空credential(table|nil)
:设置凭证,如果不设置值,之前存在的值会被清空
用法:
-- assuming `credential` and `consumer` have been set by some authentication code
kong.client.authenticate(consumer, credentials)
kong.client.get_protocol(allow_terminated)
返回当前路由匹配的协议,如果没有路由匹配,返回 nil
参数:
allow_terminated:布尔值,如果设置,则在检查 https 时检查 X-Forwarded-Proto
头
返回值:
string | nil
:"http"、"https"、"tcp"、"tls" 或 nilnil | err
:成功返回 nil,失败返回错误信息
用法:
kong.client.get_protocol() -- "http"
kong.ctx
当前请求上下文
kong.ctx.shared
一个 table 结构的数据,它用于在给定请求的多个插件之间共享数据,由于它只与请求的上下文相关,所有无法从 Lua 模块的顶级块访问此表,只能在请求段中访问,对应插件的 rewrite
、access
、header_filter
、body_filter
、log
接口,所有插件都可以看到单个插件在此 table 中插入的值,与其加护时必须谨慎,因为命名冲突会导致数据被覆盖
用法:
-- Two plugins A and B, and if plugin A has a higher priority than B's
-- (it executes before B):
-- plugin A handler.lua
function plugin_a_handler:access(conf)
kong.ctx.shared.foo = "hello world"
kong.ctx.shared.tab = {
bar = "baz"
}
end
-- plugin B handler.lua
function plugin_b_handler:access(conf)
kong.log(kong.ctx.shared.foo) -- "hello world"
kong.log(kong.ctx.shared.tab.bar) -- "baz"
end
kong.ctx.plugin
一个 table 结构的数据,与 kong.ctx.shared
不同,此 table 不在插件之间共享,相反,它仅对当前插件实例可见,也就是说,如果配置了多个限流插件实例(在不同的服务上),每个实例对于每个请求都有自己的 table,由于它自带命名空间,所以它比 kong.ctx.shared
更安全,因为它避免了潜在的命名冲突,这可能导致多个插件在不知不觉中覆盖了彼此的数据
用法:
-- plugin handler.lua
function plugin_handler:access(conf)
kong.ctx.plugin.val_1 = "hello"
kong.ctx.plugin.val_2 = "world"
end
function plugin_handler:log(conf)
local value = kong.ctx.plugin.val_1 .. " " .. kong.ctx.plugin.val_2
kong.log(value) -- "hello world"
end
kong.ip
此模块根据 trusted_ips
配置确定给定的 IP 是否可信
kong.ip.is_trusted(address)
根据 trusted_ips
配置属性,此方法将返回给定的 IP 是否可信,并且是否同时支持 ipv4 和 ipv6
参数:address(string)
:IP 地址
返回值:
true 代表受信,false代表不受信,布尔格式
用法:
if kong.ip.is_trusted("1.1.1.1") then
kong.log("The IP is trusted")
end
kong.log
一个 table 结构的数据,此命名空间包含了日志工具的实例,含有下述所有方法,每个插件的实例有单独的命名空间,Kong 确保在执行插件之前,会将实例与专用于插件的日志工具交换,这允许日志以插件的名称作为前缀,以便进行调试
kong.log(…)
日志使用当前 Nginx 配置中的 error_log
指令,日志级别是 notice
,Nginx 的 error_log
指令通过 log_level
、proxy_error_log
和 admin_error_log
这三个配置设置;传入此方法的参数的拼接方式与 ngx.log()
类似,日志中将显示调用它的 Lua 文件和行号,与 ngx.log()
不同,此方法将使用 [kong]
,而不是 [lua]
,作为错误消息的前缀,参数可以是任何格式的,在打印日志时会调用 tostring
方法转换成字符串格式
核心生成的日志格式:
[kong] %file_src:%line_src %message
插件生成的日志格式:
[kong] %file_src:%line_src [%namespace] %message
%file_src
:调用日志的文件名%func_name
:调用日志的方法的名称%line_src
:调用日志的行号%message
:日志消息
参数:
在发送到日志之前,所有的参数会拼接到一起连成字符串
返回值:
没有返回,无效的输入抛错
用法:
kong.log("hello ", "world") -- alias to kong.log.notice()
kong.log.LEVEL(…)
与 kong.log()
类似,但生成的日志具有 \<level\>
日志级别,而不是 notice
,支持的日志级别包括:
kong.log.alert()
kong.log.crit()
kong.log.err()
kong.log.warn()
kong.log.notice()
kong.log.info()
kong.log.debug()
记录日志的语法与 kong.log()
类似。用法:
kong.log.warn("something require attention")
kong.log.err("something failed: ", err)
kong.log.alert("something requires immediate action")
kong.log.inspect(…)
与 kong.log()
类似,此方法会生成 notice
级别的日志,并且可以接受任意数量的参数,如果通过kong.log.inspect.off()
方法禁用了功能,那么此方法不会打印任何内容;与 kong.log()
不同的是,该方法会在拼接参数时加上空格,这个方法主要用于调试,应避免在生产代码中使用,因为它执行了很多格式化操作,消耗资源kong.log.inspect(…)
的日志格式如下:
%file_src:%func_name:%line_src %message
%file_src
:调用日志的文件名%func_name
:调用日志的方法的名称%line_src
:调用日志的行号%message
:日志消息
用法:
kong.log.inspect("some value", a_variable)
kong.nginx
Nginx 信息模块,一组用于检索 Nginx 实现细节和元信息的方法
kong.nginx.get_subsystem()
返回值:http
或 stream
,字符串格式
用法:
kong.nginx.get_subsystem() -- "http"
kong.node
节点级别信息
kong.node.get_id()
返回值:
节点 ID,字符串格式
用法:
local id = kong.node.get_id()
kong.node.get_memory_stats([unit[, scale]])
返回该节点的内存使用数据
参数:unit(string, optional)
:内存计量单位,可以是 b/B
、k/K
、m/M
或 g/G
scale(number, optional)
:精度,默认小数点后两位
返回值:
包含此节点的内存使用统计数据,如果单位是 b/B
(默认值),则值为数字,否则统计数据为字符串,后缀是单位,table 格式
用法:
local res = kong.node.get_memory_stats()
-- res will have the following structure:
{
lua_shared_dicts = {
kong = {
allocated_slabs = 12288,
capacity = 24576
},
kong_db_cache = {
allocated_slabs = 12288,
capacity = 12288
}
},
workers_lua_vms = {
{
http_allocated_gc = 1102,
pid = 18004
},
{
http_allocated_gc = 1102,
pid = 18005
}
}
}
local res = kong.node.get_memory_stats("k", 1)
-- res will have the following structure:
{
lua_shared_dicts = {
kong = {
allocated_slabs = "12.0 KiB",
capacity = "24.0 KiB",
},
kong_db_cache = {
allocated_slabs = "12.0 KiB",
capacity = "12.0 KiB",
}
},
workers_lua_vms = {
{
http_allocated_gc = "1.1 KiB",
pid = 18004
},
{
http_allocated_gc = "1.1 KiB",
pid = 18005
}
}
}
kong.request
一组方法,用于获取客户端发出的请求信息
kong.request.get_scheme()
返回请求 URL 的 schema 组件,返回值为小写格式
返回值:http
或者 https
,字符串格式
用法:
-- Given a request to https://example.com:1234/v1/movies
kong.request.get_scheme() -- "https"
kong.request.get_host()
返回请求 URL 的 host 组件,或者 Host 头的值,返回值为小写格式
返回值:
主机地址,字符串格式
用法:
-- Given a request to https://example.com:1234/v1/movies
kong.request.get_host() -- "example.com"
kong.request.get_port()
返回请求 URL 的 port 组件
返回值:
端口号,整数格式
用法:
-- Given a request to https://example.com:1234/v1/movies
kong.request.get_port() -- 1234
kong.request.get_forwarded_scheme()
返回请求 URL 的 schema 组件,如果请求来自可信源,也会考虑 X-Forwarded-Proto
请求头,返回值为小写格式,该方法是否考虑 X-Forwarded-Proto
请求头取决于几个 Kong 配置参数:trusted_ips
、real_ip_header
、real_ip_recursive
返回值:
转发的 schema,字符串格式
用法:
kong.request.get_forwarded_scheme() -- "https"
kong.request.get_forwarded_host()
返回请求 URL 的 host 组件,不同于 kong.request.get_host()
,如果请求来自可信源,也会考虑 X-Forwarded-Host
请求头,该方法是否考虑 X-Forwarded-Host
请求头取决于几个 Kong 配置参数:trusted_ips
、real_ip_header
、real_ip_recursive
返回值:
转发的主机地址,字符串格式
用法:
kong.request.get_forwarded_host() -- "example.com"
kong.request.get_forwareded_port()
返回请求 URL 的 port 组件,如果请求来自可信源,也会考虑 X-Forwarded-Host
请求头,该方法是否考虑 X-Forwarded-Proto
请求头取决于几个 Kong 配置参数:trusted_ips
、real_ip_header
、real_ip_recursive
返回值:
转发的端口,整数格式
用法:
kong.request.get_forwarded_port() -- 1234
kong.request.get_http_version()
返回 Http 协议使用的版本号,返回值为 1.1
或 2.0
返回值:
字符串类型,或者是 nil
用法:
kong.request.get_http_version() -- "1.1"
kong.request.get_method()
返回请求的 Http 方法,返回值为大写格式
返回值:
请求方法,字符串格式
用法:
kong.request.get_method() -- "GET"
kong.request.get_path()
返回请求 URL 的 path 组件,不包含请求参数
返回值:
请求路径,字符串格式
用法:
-- Given a request to https://example.com:1234/v1/movies?movie=foo
kong.request.get_path() -- "/v1/movies"
kong.request.get_path_with_query()
返回请求 URL 的 path 组件,包含请求参数
返回值:
请求路径,包含请求参数,字符串格式
用法:
-- Given a request to https://example.com:1234/v1/movies?movie=foo
kong.request.get_path_with_query() -- "/v1/movies?movie=foo"
kong.request.get_raw_query()
返回请求 URL 的 query 组件,不包含 ?
字符
返回值:
请求参数
用法:
-- Given a request to https://example.com/foo?msg=hello%20world&bla=&bar
kong.request.get_raw_query() -- "msg=hello%20world&bla=&bar"
kong.request.get_query_arg()
返回从当前请求的查询参数获取的指定参数的值,如果参数有值,返回的是字符串或者布尔类型,如果找不到参数,返回 nil,如果查询参数中多次出现具有相同名称的参数,该方法返回第一次出现的值
返回值:
请求参数,字符串类型、布尔类型、nil
用法:
-- Given a request GET /test?foo=hello%20world&bar=baz&zzz&blo=&bar=bla&bar
kong.request.get_query_arg("foo") -- "hello world"
kong.request.get_query_arg("bar") -- "baz"
kong.request.get_query_arg("zzz") -- true
kong.request.get_query_arg("blo") -- ""
kong.request.get_query([max_args])
返回从请求参数提取的参数表,键是参数名称,值是参数值,键和值都未经转义,默认情况下,这个方法返回100个参数,可以指定 max_args
调整这个值,参数范围是1至1000
参数:max_args(number, optional)
:参数表的最大个数
返回值:
请求参数,table 格式
用法:
-- Given a request GET /test?foo=hello%20world&bar=baz&zzz&blo=&bar=bla&bar
for k, v in pairs(kong.request.get_query()) do
kong.log.inspect(k, v)
end
-- Will print
-- "foo" "hello world"
-- "bar" {"baz", "bla", true}
-- "zzz" true
-- "blo" ""
kong.request.get_header(name)
返回请求头的值,请求头名不区分大小写,并全部采用小写形式,-
可以写成 _
,比如 X-Custom-Header
可以写成 x_custom_header
参数:name(string)
:请求头的名称
返回值:
请求头的值,字符串类型或者 nil
用法:
-- Given a request with the following headers:
-- Host: foo.com
-- X-Custom-Header: bla
-- X-Another: foo bar
-- X-Another: baz
kong.request.get_header("Host") -- "foo.com"
kong.request.get_header("x-custom-header") -- "bla"
kong.request.get_header("X-Another") -- "foo bar"
kong.request.get_headers([max_headers])
返回请求头表,键是请求头名,值是请求头值,默认情况下,这个方法返回100个请求头,可以指定 max_headers
调整这个值,参数范围是1至1000
参数:max_headers(number, optional)
:请求头表的最大个数
返回值:
请求头,table 格式
用法:
-- Given a request with the following headers:
-- Host: foo.com
-- X-Custom-Header: bla
-- X-Another: foo bar
-- X-Another: baz
local headers = kong.request.get_headers()
headers.host -- "foo.com"
headers.x_custom_header -- "bla"
headers.x_another[1] -- "foo bar"
headers["X-Another"][2] -- "baz"
kong.request.get_raw_body()
返回请求体,如果请求体没有内容,该方法返回一个空字符串,如果请求体大小大于 Nginx 缓冲区大小(通过 client_body_buffer_size
设置),该方法会失败并返回错误信息
返回值:
请求体,字符串格式
用法:
-- Given a body with payload "Hello, Earth!":
kong.request.get_raw_body():gsub("Earth", "Mars") -- "Hello, Mars!"
kong.request.get_body([mimetype[, max_args]])
以键值对形式返回请求体数据,请求体以最合适的格式解析:
- 如果指定了
mimetype
,根据 content type 对请求体进行解码 - 如果 content type 是
application/x-www-form-urlencoded
,以form-encoded
形式返回请求体 - 如果 content type 是
multipart/form-data
,以上述方式解析,multipart(kong.request.get_raw_body()
,kong.request.get_header("Content-Type")):get_all()
- 如果 content type 是
application/json
,以 JSON 形式解析请求体,JSON 格式对应 Lua 的基本类型 - 如果不是上述情况,返回 nil 表示请求未被解析
mimetype
可以取以下值:application/x-www-form-urlencoded
、application/json
、multipart/form-data
max_args
限定 application/x-www-form-urlencoded
解析参数的个数
参数:mimetype(string, optional)
:mimetypemax_args(number, optional)
:请求体表的最大个数
返回值:
请求体,table 格式或 nil
错误信息,table 格式或 nil
mimetype 类型,table 格式或 nil
用法:
local body, err, mimetype = kong.request.get_body()
body.name -- "John Doe"
body.age -- "42"
kong.response
响应模块,其中包含了一组方法,用于生成和操作发送发送给客户端的响应,响应可以由 Kong 生成,或者从服务的响应体中代理过来
kong.response.get_status()
返回当前为下游响应设置的的 Http 状态码,如果请求被代理,则返回值将是来自 Service 的响应值(与 kong.service.response.get_status()
相同),如果请求未被代理,并且响应是由 Kong 本身产生的(比如通过 kong.response.exit()
),则返回值将按原样返回
返回值:
为下游响应设置的 Http 状态码
用法:
kong.response.get_status() -- 200
kong.response.get_header(name)
返回指定响应头的值,该函数包含来自代理服务的响应头和 Kong 添加的响应头(例如,通过 kong.response.add_header()
)
参数:name(string)
:请求头的名称,请求头名不区分大小写,并全部采用小写形式,-
可以写成 _
,比如 X-Custom-Header
可以写成 x_custom_header
返回值:
响应头的值,字符串格式或 nil
用法:
-- Given a response with the following headers:
-- X-Custom-Header: bla
-- X-Another: foo bar
-- X-Another: baz
kong.response.get_header("x-custom-header") -- "bla"
kong.response.get_header("X-Another") -- "foo bar"
kong.response.get_header("X-None") -- nil
kong.response.get_headers([max_headers])
包含响应头的 Lua table,与 kong.service.response.get_headers()
不同,该方法会返回客户端接收到的所有响应头,包括 Kong 本身添加的响应有,默认情况下,该方法最多返回100个响应头,可以指定 max_headers
调整这个值,参数范围是1至1000
参数:
max_headers(number, optional)
返回值:
- 响应中的响应头 table,table 格式
- 如果响应头数目超过
max_headers
,返回truncated
,字符串格式
用法:
-- Given an response from the Service with the following headers:
-- X-Custom-Header: bla
-- X-Another: foo bar
-- X-Another: baz
local headers = kong.response.get_headers()
headers.x_custom_header -- "bla"
headers.x_another[1] -- "foo bar"
headers["X-Another"][2] -- "baz"
kong.response.get_source()
这个方法确定当前响应的来源,返回值可能包含三类字符串:
exit
:调用了kong.response.exit()
,即请求被插件或 Kong 本身短路的时候error
:发生错误,比如连接到上游服务超时,返回 errorservice
:连接到代理服务,返回 service
返回值:
响应源,字符串格式
用法:
if kong.response.get_source() == "service" then
kong.log("The response comes from the Service")
elseif kong.response.get_source() == "error" then
kong.log("There was an error while processing the request")
elseif kong.response.get_source() == "exit" then
kong.log("There was an early exit while processing the request")
end
kong.response.set_status(status)
更改 Http 状态码,这个方法应该在 header_filter
段中使用,此时 Kong 准备将响应头发送回客户端
参数:status(number)
:新的 Http 状态码
返回值:
无;无效的输入抛出错误
用法:
kong.response.set_status(404)
kong.response.set_header(name, value)
设置响应头,会覆盖已经存在的响应头,这个方法应该在 header_filter
段中使用,此时 Kong 准备将响应头发送回客户端
参数:name(string)
: 响应头的名称value(string,number,boolean)
:响应头的值
返回值:
无;无效的输入抛出错误
用法:
kong.response.set_header("X-Foo", "value")
kong.response.add_header(name, value)
设置响应头,与 kong.response.set_header()
不同,这个方法不会覆盖已经存在的响应头,另外相同的响应头可以继续添加在响应中,这个方法应该在 header_filter
段中使用,此时 Kong 准备将响应头发送回客户端
参数:name(string)
: 响应头的名称value(string,number,boolean)
:响应头的值
返回值:
无;无效的输入抛出错误
用法:
kong.response.add_header("Cache-Control", "no-cache")
kong.response.add_header("Cache-Control", "no-store")
kong.response.clear_header(name)
删除响应头,这个方法应该在 header_filter
段中使用,此时 Kong 准备将响应头发送回客户端
参数:name(string)
: 需要清除的响应头的名称
返回值:
无;无效的输入抛出错误
用法:
kong.response.set_header("X-Foo", "foo")
kong.response.add_header("X-Foo", "bar")
kong.response.clear_header("X-Foo")
-- from here onwards, no X-Foo headers will exist in the response
kong.response.set_headers(headers)
设置响应头,与 kong.response.set_header()
不同,headers
参数是一个 table,键是字符串格式,值是字符串或字符串数组,这个方法应该在 header_filter
段中使用,此时 Kong 准备将响应头发送回客户端,此方法会覆盖已经存在的响应头
参数:
headers(table)
返回值:
无;无效的输入抛出错误
用法:
kong.response.set_headers({
["Bla"] = "boo",
["X-Foo"] = "foo3",
["Cache-Control"] = { "no-store", "no-cache" }
})
-- Will add the following headers to the response, in this order:
-- X-Bar: bar1
-- Bla: boo
-- Cache-Control: no-store
-- Cache-Control: no-cache
-- X-Foo: foo3
kong.response.exit(status[, body[, headers]])
参数:
status(number)
:Http 状态码body(table,string,optional)
:响应体headers(table,optional)
:响应头
返回值:
无;无效的输入抛出错误
用法:
return kong.response.exit(403, "Access Forbidden", {
["Content-Type"] = "text/plain",
["WWW-Authenticate"] = "Basic"
})
---
return kong.response.exit(403, [[{"message":"Access Forbidden"}]], {
["Content-Type"] = "application/json",
["WWW-Authenticate"] = "Basic"
})
---
return kong.response.exit(403, { message = "Access Forbidden" }, {
["WWW-Authenticate"] = "Basic"
})
kong.router
route 模块包含一组方法,用于访问请求的路由属性
kong.router.get_route()
返回路由实体,请求与此路由匹配
返回值:
路由实体,table 格式
用法:
if kong.router.get_route() then
-- routed by route & service entities
else
-- routed by a legacy API entity
end
kong.router.get_service()
返回当前服务实体,请求会路由到这个服务上
返回值:
服务实体,table 格式
用法:
if kong.router.get_service() then
-- routed by route & service entities
else
-- routed by a legacy API entity
end
kong.service
service 模块包含一组方法,用于操作请求连接到服务上的属性,比如连接的主机,IP 地址或端口,用于负载均衡和健康检查的 upstream 实体
kong.service.set_upstream(host)
设置所需的 upstream 实体处理请求的负载均衡,使用此方法相当于创建一个配置了 host
属性的服务,并关联到了相应的 upstream 实体(这种情况下,请求将代理到绑定到这个 upstream 的 target 上)
用法:
local ok, err = kong.service.set_upstream("service.prod")
if not ok then
kong.log.err(err)
return
end
kong.service.set_target(host, port)
设置代理该请求的主机和端口地址,使用这个方法相当于要求 Kong 在接收请求时不执行负载均衡阶段,而是手动覆盖它,这个请求还会忽略重试和健康检查等负载均衡组件,host
参数为字符串格式,是一个(IPv4/IPv6地址),port
参数为端口号
用法:
kong.service.set_target("service.local", 443)
kong.service.set_target("192.168.130.1", 80)
kong.service.set_tls_cert_key(chain, key)
设置与服务器端握手时使用的客户端证书,chain
参数是由 ngx.ssl.parse_pem_cert
等方法返回的客户端证书和中间链,key
参数是与 ngx.ssl.parse_pem_priv_key
等方法返回的客户端证书对应的私钥
参数:chain(cdata)
:客户端证书链key(cdata)
:客户端证书私钥
用法:
local chain = assert(ssl.parse_pem_cert(cert_data))
local key = assert(ssl.parse_pem_priv_key(key_data))
local ok, err = tls.set_cert_key(chain, key)
if not ok then
-- do something with error
end
kong.service.request
操作连接上服务的请求
kong.service.request.set_scheme(scheme)
在将请求路由到服务时设置 Http 协议
参数:schema(string)
:Http 协议,支持 http
或 https
用法:
kong.service.request.set_scheme("https")
kong.service.request.set_path(path)
设置请求路径,不包含请求参数
参数:path(string)
:请求路径
用法:
kong.service.request.set_path("/v2/movies")
kong.service.request.set_raw_query(query)
设置请求参数,query
参数是字符串格式(不包含 ?
字符),并且不会以任何方式处理,更高阶的设置请求参数方法参考 kong.service.request.set_query()
参数:query(string)
:原生的请求参数
用法:
kong.service.request.set_raw_query("zzz&bar=baz&bar=bla&bar&blo=&foo=hello%20world")
kong.service.request.set_method(method)
设置 Http 方法
参数:method(string)
:Http 方法,需要大小,支持的方法有:GET
、HEAD
、PUT
、POST
、DELETE
、OPTIONS
、MKCOL
、COPY
、MOVE
、PROPFIND
、PROPPATCH
、LOCK
、UNLOCK
、PATCH
、TRACE
用法:
kong.service.request.set_method("DELETE")
kong.service.request.set_query(args)
设置请求参数,与 kong.service.request.set_raw_query()
不同,args
参数必须是 table 格式,键是字符串类型,值可以是布尔值、字符串或数组,所有字符串都进行 URL 编码,生成的查询字符串根据字典顺序排序,保留同一键内的值顺序,如果需要进一步控制生成请求参数,可以使用 kong.service.request.set_raw_query()
方法
用法:
kong.service.request.set_query({
foo = "hello world",
bar = {"baz", "bla", true},
zzz = true,
blo = ""
})
-- Will produce the following query string:
-- bar=baz&bar=bla&bar&blo=&foo=hello%20world&zzz
kong.service.request.set_header(header, value)
设置请求头,会覆盖已经存在的请求头,如果 header
参数是 host
(大小写不敏感),会同时设置请求的 SNI
参数:header(string)
:请求头名称value(string,boolean,number)
:请求头值
用法:
kong.service.request.set_header("X-Foo", "value")
kong.service.request.add_header(header, value)
设置请求头,与 kong.service.request.set_header()
不同,不会覆盖已经存在的请求头
参数:header(string)
:请求头名称value(string,boolean,number)
:请求头值
用法:
kong.service.request.add_header("Cache-Control", "no-cache")
kong.service.request.add_header("Cache-Control", "no-store")
kong.service.request.clear_header(header)
清除请求头
参数:header(string)
:请求头名称
用法:
kong.service.request.set_header("X-Foo", "foo")
kong.service.request.add_header("X-Foo", "bar")
kong.service.request.clear_header("X-Foo")
-- from here onwards, no X-Foo headers will exist in the request
kong.service.request.set_headers(headers)
设置请求头,与 kong.service.request.set_header()
不同,headers
参数必须是 table 格式的
参数:headers(table)
:table 格式的请求头集合
用法:
kong.service.request.set_header("X-Foo", "foo1")
kong.service.request.add_header("X-Foo", "foo2")
kong.service.request.set_header("X-Bar", "bar1")
kong.service.request.set_headers({
["X-Foo"] = "foo3",
["Cache-Control"] = { "no-store", "no-cache" },
["Bla"] = "boo"
})
-- Will add the following headers to the request, in this order:
-- X-Bar: bar1
-- Bla: boo
-- Cache-Control: no-store
-- Cache-Control: no-cache
-- X-Foo: foo3
kong.service.request.set_raw_body(body)
设置请求体,body 参数必须是一个字符串,不会以任何方式处理处理,这个方法还会添加 Content-Length
头,如果想设置空请求体,直接设置空字符串,更高阶的设置参考 kong.service.request.set_body()
参数:body(string)
:原始 body 请求体
用法:
kong.service.request.set_raw_body("Hello, world!")
kong.service.request.set_body(args[, mimetype])
设置请求体,与 kong.service.request.set_body()
不同,args
必须是 table 格式,并且以 MIME type 格式编码
application/x-www-form-urlencoded
:以 form-encoded 方式对参数进行编码multipart/form-data
:以 multipart form data 方式对参数进行编码application/json
:以 JSON 格式对参数进行编码
用法:
kong.service.set_header("application/json")
local ok, err = kong.service.request.set_body({
name = "John Doe",
age = 42,
numbers = {1, 2, 3}
})
-- Produces the following JSON body:
-- { "name": "John Doe", "age": 42, "numbers":[1, 2, 3] }
local ok, err = kong.service.request.set_body({
foo = "hello world",
bar = {"baz", "bla", true},
zzz = true,
blo = ""
}, "application/x-www-form-urlencoded")
-- Produces the following body:
-- bar=baz&bar=bla&bar&blo=&foo=hello%20world&zzz
kong.service.response
操作服务的响应
kong.service.response.get_status()
从服务返回的响应的 Http 状态码
用法:
kong.log.inspect(kong.service.response.get_status()) -- 418
kong.service.response.get_headers([max_headers])
包含响应头的 Lua table,与 kong.response.get_headers()
不同,该方法仅会返回服务返回的响应中的请求头(忽略 Kong 本身添加的),如果请求未被代理到任何服务(比如被鉴权插件拒绝了并且产生了401响应),headers
值是 nil
,因为服务没有任何响应,默认情况下,该方法最多返回100个响应头,可以指定 max_headers
调整这个值,参数范围是1至1000
用法:
-- Given a response with the following headers:
-- X-Custom-Header: bla
-- X-Another: foo bar
-- X-Another: baz
local headers = kong.service.response.get_headers()
if headers then
kong.log.inspect(headers.x_custom_header) -- "bla"
kong.log.inspect(headers.x_another[1]) -- "foo bar"
kong.log.inspect(headers["X-Another"][2]) -- "baz"
end
kong.service.response.get_header(name)
返回指定响应头的值,与 kong.response.get_header()
不同,这个方法只会返回服务的响应中的请求头(忽略 Kong 本身添加的)
用法:
-- Given a response with the following headers:
-- X-Custom-Header: bla
-- X-Another: foo bar
-- X-Another: baz
kong.log.inspect(kong.service.response.get_header("x-custom-header")) -- "bla"
kong.log.inspect(kong.service.response.get_header("X-Another")) -- "foo bar"
kong.table
Lua table 工具类
kong.table.new([narr[, nrec]])
返回一个 table,其中包含了预先分配的数组和散列
参数:narr(number, optional)
:指定在数组组件中预分布的插槽数nrec(number, optional)
:指定在散列组件中预分布的插槽数
返回值:
新创建的 table,table 格式
用法:
local tab = kong.table.new(4, 4)
kong.table.clear(tab)
清理 table
参数:tab(table)
:需要被清理的 table
用法:
local tab = {
"hello",
foo = "bar"
}
kong.table.clear(tab)
kong.log(tab[1]) -- nil
kong.log(tab.foo) -- nil