Skip to content

Commit 721b9a0

Browse files
committed
feat: allow not pass trailers in nginx upstream
1 parent 3787343 commit 721b9a0

File tree

6 files changed

+199
-0
lines changed

6 files changed

+199
-0
lines changed

lib/resty/apisix/upstream.lua

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ local get_phase = ngx.get_phase
55
local C = ffi.C
66
local NGX_ERROR = ngx.ERROR
77
local NGX_OK = ngx.OK
8+
local type = type
89

910

1011
base.allows_subsystem("http")
@@ -15,6 +16,8 @@ typedef intptr_t ngx_int_t;
1516
ngx_int_t ngx_http_apisix_upstream_set_cert_and_key(ngx_http_request_t *r, void *cert, void *key);
1617
ngx_int_t ngx_http_apisix_upstream_set_ssl_trusted_store(ngx_http_request_t *r, void *store);
1718
int ngx_http_apisix_upstream_set_ssl_verify(ngx_http_request_t *r, int verify);
19+
20+
ngx_int_t ngx_http_apisix_set_upstream_pass_trailers(ngx_http_request_t *r, int on);
1821
]])
1922
local _M = {}
2023

@@ -106,4 +109,19 @@ end
106109
_M.set_ssl_verify = set_ssl_verify
107110

108111

112+
function _M.set_pass_trailers(on)
113+
if type(on) ~= 'boolean' then
114+
return nil, "on expects a boolean but found " .. type(on)
115+
end
116+
117+
local r = get_request()
118+
local ret = C.ngx_http_apisix_set_upstream_pass_trailers(r, on and 1 or 0)
119+
if ret == NGX_ERROR then
120+
return nil, "error while setting upstream pass_trailers"
121+
end
122+
123+
return true
124+
end
125+
126+
109127
return _M
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
diff --git a/src/http/ngx_http_upstream.c b/src/http/ngx_http_upstream.c
2+
index d29e503cb..014082d30 100644
3+
--- a/src/http/ngx_http_upstream.c
4+
+++ b/src/http/ngx_http_upstream.c
5+
@@ -8,6 +8,9 @@
6+
#include <ngx_config.h>
7+
#include <ngx_core.h>
8+
#include <ngx_http.h>
9+
+#if (NGX_HTTP_APISIX)
10+
+#include <ngx_http_apisix_module.h>
11+
+#endif
12+
13+
14+
#if (NGX_HTTP_CACHE)
15+
@@ -2977,6 +2980,12 @@ ngx_http_upstream_process_trailers(ngx_http_request_t *r,
16+
return NGX_OK;
17+
}
18+
19+
+#if (NGX_HTTP_APISIX)
20+
+ if (!ngx_http_apisix_is_upstream_pass_trailers(r)) {
21+
+ return NGX_OK;
22+
+ }
23+
+#endif
24+
+
25+
part = &u->headers_in.trailers.part;
26+
h = part->elts;
27+
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
diff --git a/src/http/ngx_http_upstream.c b/src/http/ngx_http_upstream.c
2+
index d29e503cb..014082d30 100644
3+
--- a/src/http/ngx_http_upstream.c
4+
+++ b/src/http/ngx_http_upstream.c
5+
@@ -8,6 +8,9 @@
6+
#include <ngx_config.h>
7+
#include <ngx_core.h>
8+
#include <ngx_http.h>
9+
+#if (NGX_HTTP_APISIX)
10+
+#include <ngx_http_apisix_module.h>
11+
+#endif
12+
13+
14+
#if (NGX_HTTP_CACHE)
15+
@@ -2977,6 +2980,12 @@ ngx_http_upstream_process_trailers(ngx_http_request_t *r,
16+
return NGX_OK;
17+
}
18+
19+
+#if (NGX_HTTP_APISIX)
20+
+ if (!ngx_http_apisix_is_upstream_pass_trailers(r)) {
21+
+ return NGX_OK;
22+
+ }
23+
+#endif
24+
+
25+
part = &u->headers_in.trailers.part;
26+
h = part->elts;
27+

src/ngx_http_apisix_module.c

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1048,3 +1048,34 @@ ngx_http_apisix_error_log_request_id(ngx_conf_t *cf, ngx_command_t *cmd, void *c
10481048
return NGX_CONF_OK;
10491049
}
10501050

1051+
1052+
ngx_int_t
1053+
ngx_http_apisix_set_upstream_pass_trailers(ngx_http_request_t *r, int on)
1054+
{
1055+
ngx_http_apisix_ctx_t *ctx;
1056+
1057+
ctx = ngx_http_apisix_get_module_ctx(r);
1058+
1059+
if (ctx == NULL) {
1060+
return NGX_ERROR;
1061+
}
1062+
1063+
ctx->upstream_pass_trailers = on;
1064+
ctx->upstream_pass_trailers_set = 1;
1065+
return NGX_OK;
1066+
}
1067+
1068+
1069+
ngx_int_t
1070+
ngx_http_apisix_is_upstream_pass_trailers(ngx_http_request_t *r)
1071+
{
1072+
ngx_http_apisix_ctx_t *ctx;
1073+
1074+
ctx = ngx_http_apisix_get_module_ctx(r);
1075+
1076+
if (ctx != NULL && ctx->upstream_pass_trailers_set) {
1077+
return ctx->upstream_pass_trailers;
1078+
}
1079+
1080+
return 1;
1081+
}

src/ngx_http_apisix_module.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ typedef struct {
3737
unsigned body_filter_by_lua_skipped:1;
3838
unsigned upstream_ssl_verify:1;
3939
unsigned upstream_ssl_verify_set:1;
40+
unsigned upstream_pass_trailers:1;
41+
unsigned upstream_pass_trailers_set:1;
4042
} ngx_http_apisix_ctx_t;
4143

4244

t/upstream_pass_trailers.t

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
use t::APISIX_NGINX 'no_plan';
2+
3+
run_tests();
4+
5+
add_block_preprocessor(sub {
6+
my ($block) = @_;
7+
8+
if (!$block->request) {
9+
$block->set_value("request", "");
10+
}
11+
});
12+
13+
__DATA__
14+
15+
=== TEST 1: pass upstream trailers to downstream
16+
This is the default behavior in the nginx upstream unless we change it.
17+
--- config
18+
location /up {
19+
# The trailer exists, but the Trailer header does not, which is an invalid response.
20+
add_trailer "foo" "bar";
21+
echo "hello";
22+
}
23+
location /t {
24+
content_by_lua_block {
25+
local sock = ngx.socket.tcp()
26+
27+
local ok, err = sock:connect("127.0.0.1", ngx.var.server_port)
28+
if not ok then
29+
ngx.say("failed to connect: ", err)
30+
return
31+
end
32+
33+
local _, err = sock:send("GET /up HTTP/1.1\r\nHost: 127.0.0.1:1984\r\nUser-Agent: curl/8.5.0\r\nAccept: */*\r\nConnection: close\r\n\r\n")
34+
if err then
35+
ngx.say("failed to send: ", err)
36+
return
37+
end
38+
39+
local data, err, partial = sock:receive("*a")
40+
if err then
41+
ngx.say("failed to receive: ", err)
42+
return
43+
end
44+
45+
assert(string.find(data, "HTTP/1.1 200 OK", 1, true), "status not 200")
46+
assert(not string.find(data, "Trailer: foo", 1, true), "exist trailer header")
47+
assert(string.find(data, "foo: bar", 1, true), "missing trailer")
48+
}
49+
}
50+
--- request
51+
GET /t
52+
53+
54+
55+
=== TEST 2: do not pass upstream trailers to downstream
56+
--- config
57+
location /up {
58+
add_trailer "foo" "bar";
59+
echo "hello";
60+
}
61+
location /t {
62+
access_by_lua_block {
63+
local upstream = require("resty.apisix.upstream")
64+
assert(upstream.set_pass_trailers(false))
65+
}
66+
67+
content_by_lua_block {
68+
local sock = ngx.socket.tcp()
69+
70+
local ok, err = sock:connect("127.0.0.1", ngx.var.server_port)
71+
if not ok then
72+
ngx.say("failed to connect: ", err)
73+
return
74+
end
75+
76+
local _, err = sock:send("GET /up HTTP/1.1\r\nHost: 127.0.0.1:1984\r\nUser-Agent: curl/8.5.0\r\nAccept: */*\r\nConnection: close\r\n\r\n")
77+
if err then
78+
ngx.say("failed to send: ", err)
79+
return
80+
end
81+
82+
local data, err, partial = sock:receive("*a")
83+
if err then
84+
ngx.say("failed to receive: ", err)
85+
return
86+
end
87+
88+
assert(string.find(data, "HTTP/1.1 200 OK", 1, true), "status not 200")
89+
assert(not string.find(data, "Trailer: foo", 1, true), "exist trailer header")
90+
assert(not string.find(data, "foo: bar", 1, true), "exist trailer")
91+
}
92+
}
93+
--- request
94+
GET /t

0 commit comments

Comments
 (0)