Skip to content

Commit de57d6a

Browse files
authored
fix(pdk) kong.response.error honors grpc content-type and headers (Kong#6214)
1 parent 56f49e5 commit de57d6a

File tree

2 files changed

+136
-9
lines changed

2 files changed

+136
-9
lines changed

kong/pdk/response.lua

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -529,6 +529,12 @@ local function new(self, major_version)
529529
-- -- TODO: implement, but how?
530530
--end
531531

532+
local function is_grpc_request()
533+
local req_ctype = ngx.var.content_type
534+
return req_ctype
535+
and find(req_ctype, CONTENT_TYPE_GRPC, 1, true) == 1
536+
and ngx.req.http_version() == 2
537+
end
532538

533539
local function send(status, body, headers)
534540
if ngx.headers_sent then
@@ -558,16 +564,14 @@ local function new(self, major_version)
558564
end
559565

560566
local res_ctype = ngx.header[CONTENT_TYPE_NAME]
561-
local req_ctype = ngx.var.content_type
562567

563568
local is_grpc
564569
local is_grpc_output
565570
if res_ctype then
566571
is_grpc = find(res_ctype, CONTENT_TYPE_GRPC, 1, true) == 1
567572
is_grpc_output = is_grpc
568-
elseif req_ctype then
569-
is_grpc = find(req_ctype, CONTENT_TYPE_GRPC, 1, true) == 1
570-
and ngx.req.http_version() == 2
573+
else
574+
is_grpc = is_grpc_request()
571575
end
572576

573577
local grpc_status
@@ -1000,14 +1004,19 @@ local function new(self, major_version)
10001004
end
10011005

10021006
local content_type_header = headers[CONTENT_TYPE_NAME]
1003-
local content_type = content_type_header and content_type_header[1] or content_type_header
1007+
local content_type = content_type_header and content_type_header[1]
1008+
or content_type_header
10041009

10051010
if content_type_header == nil then
1006-
content_type_header = ngx.req.get_headers()[ACCEPT_NAME]
1007-
if type(content_type_header) == "table" then
1008-
content_type_header = content_type_header[1]
1011+
if is_grpc_request() then
1012+
content_type = CONTENT_TYPE_GRPC
1013+
else
1014+
content_type_header = ngx.req.get_headers()[ACCEPT_NAME]
1015+
if type(content_type_header) == "table" then
1016+
content_type_header = content_type_header[1]
1017+
end
1018+
content_type = get_response_type(content_type_header)
10091019
end
1010-
content_type = get_response_type(content_type_header)
10111020
end
10121021

10131022
headers[CONTENT_TYPE_NAME] = content_type

t/01-pdk/08-response/13-error.t

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ plan tests => repeat_each() * (blocks() * 4);
1010
run_tests();
1111

1212
__DATA__
13+
1314
=== TEST 1: service.response.error() use accept header
1415
--- http_config eval: $t::Util::HttpConfig
1516
--- config
@@ -35,6 +36,8 @@ Content-Type: application/json; charset=utf-8
3536
--- no_error_log
3637
[error]
3738
39+
40+
3841
=== TEST 2: service.response.error() fallbacks to json
3942
--- http_config eval: $t::Util::HttpConfig
4043
--- config
@@ -58,6 +61,8 @@ Content-Type: application/json; charset=utf-8
5861
--- no_error_log
5962
[error]
6063
64+
65+
6166
=== TEST 3: service.response.error() may ignore accept header
6267
--- http_config eval: $t::Util::HttpConfig
6368
--- config
@@ -88,6 +93,8 @@ Content-Type: application/xml
8893
--- no_error_log
8994
[error]
9095
96+
97+
9198
=== TEST 4: service.response.error() respects accept header priorities
9299
--- http_config eval: $t::Util::HttpConfig
93100
--- config
@@ -122,6 +129,7 @@ Content-Type: text/html; charset=utf-8
122129
[error]
123130
124131
132+
125133
=== TEST 5: service.response.error() has higher priority than handle_errors
126134
--- http_config eval: $t::Util::HttpConfig
127135
--- config
@@ -155,6 +163,8 @@ Content-Type: application/json; charset=utf-8
155163
--- no_error_log
156164
[error]
157165
166+
167+
158168
=== TEST 6: service.response.error() formats default template
159169
--- http_config eval: $t::Util::HttpConfig
160170
--- config
@@ -180,6 +190,8 @@ Content-Type: application/json; charset=utf-8
180190
--- no_error_log
181191
[error]
182192
193+
194+
183195
=== TEST 7: service.response.error() overrides default message
184196
--- http_config eval: $t::Util::HttpConfig
185197
--- config
@@ -205,6 +217,8 @@ Content-Type: application/json; charset=utf-8
205217
--- no_error_log
206218
[error]
207219
220+
221+
208222
=== TEST 8: service.response.error() use accept header "*" mime sub-type
209223
--- http_config eval: $t::Util::HttpConfig
210224
--- config
@@ -227,3 +241,107 @@ Content-Type: text/plain; charset=utf-8
227241
Gone
228242
--- no_error_log
229243
[error]
244+
245+
246+
247+
=== TEST 9: response.error() maps http 400 to grpc InvalidArgument
248+
--- http_config eval: $t::Util::HttpConfig
249+
--- config
250+
location = /t {
251+
default_type 'text/test';
252+
access_by_lua_block {
253+
ngx.req.http_version = function() return 2 end
254+
local PDK = require "kong.pdk"
255+
local pdk = PDK.new()
256+
257+
pdk.response.error(400)
258+
}
259+
}
260+
--- request
261+
GET /t
262+
--- more_headers
263+
Content-Type: application/grpc
264+
--- error_code: 400
265+
--- response_headers_like
266+
grpc-status: 3
267+
grpc-message: InvalidArgument
268+
--- no_error_log
269+
[error]
270+
271+
272+
273+
=== TEST 10: response.error() maps http 401 to grpc Unauthenticated
274+
--- http_config eval: $t::Util::HttpConfig
275+
--- config
276+
location = /t {
277+
default_type 'text/test';
278+
access_by_lua_block {
279+
ngx.req.http_version = function() return 2 end
280+
local PDK = require "kong.pdk"
281+
local pdk = PDK.new()
282+
283+
pdk.response.error(401)
284+
}
285+
}
286+
--- request
287+
GET /t
288+
--- more_headers
289+
Content-Type: application/grpc
290+
--- error_code: 401
291+
--- response_headers_like
292+
grpc-status: 16
293+
grpc-message: Unauthenticated
294+
--- no_error_log
295+
[error]
296+
297+
298+
299+
=== TEST 11: response.error() maps http 403 to grpc PermissionDenied
300+
--- http_config eval: $t::Util::HttpConfig
301+
--- config
302+
location = /t {
303+
default_type 'text/test';
304+
access_by_lua_block {
305+
ngx.req.http_version = function() return 2 end
306+
local PDK = require "kong.pdk"
307+
local pdk = PDK.new()
308+
309+
pdk.response.error(403)
310+
}
311+
}
312+
--- request
313+
GET /t
314+
--- more_headers
315+
Content-Type: application/grpc
316+
--- error_code: 403
317+
--- response_headers_like
318+
grpc-status: 7
319+
grpc-message: PermissionDenied
320+
--- no_error_log
321+
[error]
322+
323+
324+
325+
=== TEST 12: response.error() maps http 429 to grpc ResourceExhausted
326+
--- http_config eval: $t::Util::HttpConfig
327+
--- config
328+
location = /t {
329+
default_type 'text/test';
330+
access_by_lua_block {
331+
ngx.req.http_version = function() return 2 end
332+
local PDK = require "kong.pdk"
333+
local pdk = PDK.new()
334+
335+
pdk.response.error(429)
336+
}
337+
}
338+
--- request
339+
GET /t
340+
--- more_headers
341+
Content-Type: application/grpc
342+
--- error_code: 429
343+
--- response_headers_like
344+
grpc-status: 8
345+
grpc-message: ResourceExhausted
346+
--- no_error_log
347+
[error]

0 commit comments

Comments
 (0)