Skip to content

Commit

Permalink
fix(grpc-web): err when > client_body_buffer_size
Browse files Browse the repository at this point in the history
  • Loading branch information
StarlightIbuki committed Dec 7, 2023
1 parent 89e6266 commit 391d45a
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 14 deletions.
3 changes: 3 additions & 0 deletions changelog/unreleased/kong/grpc-web-large-req-error.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
message: "**grpc-web**: fix an issue where large requests would result in an error"
type: bugfix
scope: Plugin
25 changes: 24 additions & 1 deletion kong/plugins/grpc-web/handler.lua
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ local ngx = ngx
local kong = kong

local string_format = string.format
local io_open = io.open

local ngx_arg = ngx.arg
local ngx_var = ngx.var
Expand All @@ -15,10 +16,12 @@ 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 ngx_req_get_body_file = ngx.req.get_body_file
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 warn = kong.log.warn


local grpc_web = {
Expand All @@ -34,6 +37,26 @@ local CORS_HEADERS = {
["Access-Control-Allow-Headers"] = "content-type,x-grpc-web,x-user-agent",
}

local function get_body()
local body, err = kong_request_get_raw_body()
if body then
return body
end

-- if body_file is not nil, the error of get_raw_body is expected
-- otherwise return the error
local body_file = ngx_req_get_body_file()
assert(body_file, err)

warn("client_body_buffer_size exceeded and reading the request from disk. Please consider increasing the value.")

local file = assert(io_open(body_file, "rb"))
body = assert(file:read("*a"))
file:close()

return body
end

function grpc_web:access(conf)
kong_response_set_header("Access-Control-Allow-Origin", conf.allow_origin_header)

Expand Down Expand Up @@ -63,7 +86,7 @@ function grpc_web:access(conf)

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()))
kong_service_request_set_raw_body(dec:upstream(get_body()))
end


Expand Down
45 changes: 32 additions & 13 deletions spec/03-plugins/32-grpc-web/01-proxy_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ for _, strategy in helpers.each_strategy() do
"gAAAAB5ncnBjLXN0YXR1czowDQpncnBjLW1lc3NhZ2U6DQo="
local HELLO_RESPONSE_BODY = ngx.decode_base64("AAAAAAwKCmhlbGxvIGhleWE=") ..
ngx.decode_base64("gAAAAB5ncnBjLXN0YXR1czowDQpncnBjLW1lc3NhZ2U6DQo=")
-- larger than 1k
local LARGE_MESSAGE = string.rep("OK", 10000)
local LARGE_REQUEST_BODY = '{"greeting": \"' .. LARGE_MESSAGE .. '\"}'
local LARGE_RESPONSE_BODY = '{"reply":\"hello ' .. LARGE_MESSAGE .. '\"}'

lazy_setup(function()
local bp = helpers.get_db_utils(strategy, {
Expand Down Expand Up @@ -78,7 +82,7 @@ for _, strategy in helpers.each_strategy() do
end)

lazy_teardown(function()
helpers.stop_kong()
helpers.stop_kong(nil, true)
end)


Expand Down Expand Up @@ -155,7 +159,7 @@ for _, strategy in helpers.each_strategy() do
assert.is_nil(err)
end)

test("Call plain JSON via HTTP", function()
test("Call plain JSON via HTTP", function()
local res, err = proxy_client:post("/hello.HelloService/SayHello", {
headers = {
["Content-Type"] = "application/json",
Expand All @@ -167,16 +171,31 @@ for _, strategy in helpers.each_strategy() do
assert.is_nil(err)
end)

test("Pass stripped URI", function()
local res, err = proxy_client:post("/prefix/hello.HelloService/SayHello", {
headers = {
["Content-Type"] = "application/json",
},
body = cjson.encode{ greeting = "heya" },
})

assert.same({ reply = "hello heya" }, cjson.decode((res:read_body())))
assert.is_nil(err)
end)
test("Pass stripped URI", function()
local res, err = proxy_client:post("/prefix/hello.HelloService/SayHello", {
headers = {
["Content-Type"] = "application/json",
},
body = cjson.encode{ greeting = "heya" },
})

assert.same({ reply = "hello heya" }, cjson.decode((res:read_body())))
assert.is_nil(err)
end)

test("#regression large body causes error", function()
local res = assert(proxy_client:post("/hello.HelloService/SayHello", {
headers = {
["Content-Type"] = "application/json",
["Content-Length"] = tostring(#LARGE_REQUEST_BODY),
},
body = LARGE_REQUEST_BODY,
}))

local body = assert(res:read_body())
assert.equal(LARGE_RESPONSE_BODY, body)

assert.logfile().has.line("client_body_buffer_size exceeded")
end)
end)
end

0 comments on commit 391d45a

Please sign in to comment.