Files
2026-07-13 12:32:21 +08:00

107 lines
2.6 KiB
Lua

-- Copyright (c) Kong Inc. 2020
local deco = require "kong.plugins.grpc-web.deco"
local kong_meta = require "kong.meta"
local ngx = ngx
local kong = kong
local string_format = string.format
local ngx_arg = ngx.arg
local ngx_var = ngx.var
local kong_request_get_path = kong.request.get_path
local kong_request_get_header = kong.request.get_header
local kong_request_get_method = kong.request.get_method
local kong_request_get_raw_body = kong.request.get_raw_body
local kong_response_exit = kong.response.exit
local kong_response_set_header = kong.response.set_header
local kong_service_request_set_header = kong.service.request.set_header
local kong_service_request_set_raw_body = kong.service.request.set_raw_body
local grpc_web = {
PRIORITY = 3,
VERSION = kong_meta.version,
}
local CORS_HEADERS = {
["Content-Type"] = "application/grpc-web-text+proto",
["Access-Control-Allow-Origin"] = "*",
["Access-Control-Allow-Methods"] = "POST",
["Access-Control-Allow-Headers"] = "content-type,x-grpc-web,x-user-agent",
}
function grpc_web:access(conf)
kong_response_set_header("Access-Control-Allow-Origin", conf.allow_origin_header)
if kong_request_get_method() == "OPTIONS" then
CORS_HEADERS["Access-Control-Allow-Origin"] = conf.allow_origin_header
return kong_response_exit(200, "OK", CORS_HEADERS)
end
local uri
if conf.pass_stripped_path then
uri = ngx_var.upstream_uri
ngx.req.set_uri(uri)
else
uri = kong_request_get_path()
end
local dec, err = deco.new(
kong_request_get_header("Content-Type"),
uri, conf.proto)
if not dec then
kong.log.err(err)
return kong_response_exit(400, err)
end
kong.ctx.plugin.dec = dec
kong_service_request_set_header("Content-Type", "application/grpc")
kong_service_request_set_header("TE", "trailers")
kong_service_request_set_raw_body(dec:upstream(kong_request_get_raw_body()))
end
function grpc_web:header_filter(conf)
if kong_request_get_method() == "OPTIONS" then
return
end
local dec = kong.ctx.plugin.dec
if dec then
kong_response_set_header("Content-Type", dec.mimetype)
end
end
function grpc_web:body_filter(conf)
if kong_request_get_method() ~= "POST" then
return
end
local dec = kong.ctx.plugin.dec
if not dec then
return
end
local chunk, eof = ngx_arg[1], ngx_arg[2]
chunk = dec:downstream(chunk)
if eof and dec.framing == "grpc" then
chunk = chunk .. dec:frame(0x80, string_format(
"grpc-status:%s\r\ngrpc-message:%s\r\n",
ngx_var["sent_trailer_grpc_status"] or "0",
ngx_var["sent_trailer_grpc_message"] or ""))
end
ngx_arg[1] = chunk
end
return grpc_web