Skip to content

Commit c967e83

Browse files
authored
feat: control the proxy_upstream in lua side (#98)
Set upstream next enablement of current request to the given string of table argument . Global setting set by proxy_next_upstream will be overwritten. AG-186
1 parent f85f921 commit c967e83

File tree

7 files changed

+509
-2
lines changed

7 files changed

+509
-2
lines changed

.github/workflows/tests.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ on:
55
push:
66

77
env:
8-
KONG_VERSION: master
8+
KONG_VERSION: feat-next-upstream
99
BUILD_ROOT: ${{ github.workspace }}/kong/bazel-bin/build
1010

1111
concurrency:

README.md

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@ Table of Contents
3131
* [resty.kong.log.set\_log\_level](#restykonglogset_log_level)
3232
* [resty.kong.log.get\_log\_level](#restykonglogget_log_level)
3333
* [resty.kong.peer_conn.get\_last\_peer\_connection\_cached](#restykongpeer_connget_last_peer_connection_cached)
34+
* [resty.kong.upstream.set\_next\_upstream](#restykongupstreamset_next_upstream)
35+
3436
* [License](#license)
3537

3638
Description
@@ -576,6 +578,43 @@ balancer_by_lua_block {
576578

577579
[Back to TOC](#table-of-contents)
578580

581+
582+
resty.kong.upstream.set\_next\_upstream
583+
----------------------------------
584+
**syntax:** *res = resty.kong.upstream.set_next_upstream("http_404")*
585+
586+
**context:** *rewrite_by_lua*, access_by_lua*, balancer_by_lua**
587+
588+
589+
**subsystems:** *http*
590+
591+
Set upstream next enablement of current request to the given string of table
592+
argument . Global setting set by [`proxy_next_upstream`](http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_next_upstream) will be overwritten.
593+
594+
The `set_next_upstream` function supports variable length of arguments, and each argument must be one of the following strings (also defined in [`proxy_next_upstream`](http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_next_upstream)):
595+
- `error`
596+
- `timeout`
597+
- `invalid_header`
598+
- `http_500`
599+
- `http_502`
600+
- `http_503`
601+
- `http_504`
602+
- `http_403`
603+
- `http_404`
604+
- `http_429`
605+
- `non_idempotent`
606+
- `off`
607+
608+
On success, this function returns `nil`. Otherwise throw a string
609+
describing the error will be returned.
610+
611+
This function can be called multiple times in the same request. Later calls override
612+
previous ones.
613+
614+
[Back to TOC](#table-of-contents)
615+
616+
617+
579618
License
580619
=======
581620

lualib/resty/kong/upstream.lua

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
-- Copyright 2019-2022 Kong Inc.
2+
3+
-- Licensed under the Apache License, Version 2.0 (the "License");
4+
-- you may not use this file except in compliance with the License.
5+
-- You may obtain a copy of the License at
6+
7+
-- http://www.apache.org/licenses/LICENSE-2.0
8+
9+
-- Unless required by applicable law or agreed to in writing, software
10+
-- distributed under the License is distributed on an "AS IS" BASIS,
11+
-- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
-- See the License for the specific language governing permissions and
13+
-- limitations under the License.
14+
15+
local _M = {}
16+
17+
local ffi = require("ffi")
18+
local base = require("resty.core.base")
19+
local select = select
20+
base.allows_subsystem("http")
21+
22+
ffi.cdef([[
23+
int
24+
ngx_http_lua_ffi_set_next_upstream(ngx_http_request_t *r, uint32_t next_upstream, char **err);
25+
const uint32_t ngx_http_lua_kong_next_upstream_mask_error;
26+
const uint32_t ngx_http_lua_kong_next_upstream_mask_timeout;
27+
const uint32_t ngx_http_lua_kong_next_upstream_mask_invalid_header;
28+
const uint32_t ngx_http_lua_kong_next_upstream_mask_http_500;
29+
const uint32_t ngx_http_lua_kong_next_upstream_mask_http_502;
30+
const uint32_t ngx_http_lua_kong_next_upstream_mask_http_503;
31+
const uint32_t ngx_http_lua_kong_next_upstream_mask_http_504;
32+
const uint32_t ngx_http_lua_kong_next_upstream_mask_http_403;
33+
const uint32_t ngx_http_lua_kong_next_upstream_mask_http_404;
34+
const uint32_t ngx_http_lua_kong_next_upstream_mask_http_429;
35+
const uint32_t ngx_http_lua_kong_next_upstream_mask_off;
36+
const uint32_t ngx_http_lua_kong_next_upstream_mask_non_idempotent;
37+
]])
38+
39+
local type = type
40+
local C = ffi.C
41+
local get_request = base.get_request
42+
local ffi_str = ffi.string
43+
44+
local NGX_OK = ngx.OK
45+
46+
local next_upstream_table = {
47+
error = C.ngx_http_lua_kong_next_upstream_mask_error,
48+
timeout = C.ngx_http_lua_kong_next_upstream_mask_timeout,
49+
invalid_header = C.ngx_http_lua_kong_next_upstream_mask_invalid_header,
50+
http_500 = C.ngx_http_lua_kong_next_upstream_mask_http_500,
51+
http_502 = C.ngx_http_lua_kong_next_upstream_mask_http_502,
52+
http_503 = C.ngx_http_lua_kong_next_upstream_mask_http_503,
53+
http_504 = C.ngx_http_lua_kong_next_upstream_mask_http_504,
54+
http_403 = C.ngx_http_lua_kong_next_upstream_mask_http_403,
55+
http_404 = C.ngx_http_lua_kong_next_upstream_mask_http_404,
56+
http_429 = C.ngx_http_lua_kong_next_upstream_mask_http_429,
57+
off = C.ngx_http_lua_kong_next_upstream_mask_off,
58+
non_idempotent = C.ngx_http_lua_kong_next_upstream_mask_non_idempotent,
59+
}
60+
61+
function _M.set_next_upstream(...)
62+
local nargs = select("#", ...)
63+
if nargs == 0 then
64+
return "no argument"
65+
end
66+
67+
local r = get_request()
68+
if not r then
69+
return "no request found"
70+
end
71+
72+
local arg_table = { ... }
73+
local next_upstream = 0
74+
for i = 1, nargs do
75+
local v = arg_table[i]
76+
if type(v) ~= "string" then
77+
return "argument #" .. i .. " is not a string"
78+
end
79+
80+
local next_upstream_value = next_upstream_table[v]
81+
if not next_upstream_value then
82+
return "argument #" .. i .. " is not a valid argument"
83+
end
84+
85+
next_upstream = bit.bor(next_upstream, next_upstream_value)
86+
end
87+
88+
local err = ffi.new("char *[1]")
89+
local rc = C.ngx_http_lua_ffi_set_next_upstream(r, next_upstream, err)
90+
91+
if rc ~= NGX_OK then
92+
return "failed to set upstream next: " .. ffi_str(err[0])
93+
end
94+
95+
return nil
96+
end
97+
98+
return _M

src/ngx_http_lua_kong_common.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ typedef struct {
2828
ngx_lua_kong_ssl_ctx_t ssl_ctx;
2929
ngx_str_t grpc_authority;
3030
ngx_http_log_handler_pt orig_log_handler;
31+
ngx_uint_t next_upstream;
3132
} ngx_http_lua_kong_ctx_t;
3233

3334

src/ngx_http_lua_kong_module.c

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616

1717

1818
#include "ngx_http_lua_kong_directive.h"
19-
19+
#include "ngx_http_upstream.h"
2020

2121
static ngx_int_t ngx_http_lua_kong_init(ngx_conf_t *cf);
2222
static void* ngx_http_lua_kong_create_loc_conf(ngx_conf_t* cf);
@@ -158,4 +158,46 @@ ngx_http_lua_kong_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
158158
return NGX_CONF_OK;
159159
}
160160

161+
const ngx_uint_t ngx_http_lua_kong_next_upstream_mask_error = NGX_HTTP_UPSTREAM_FT_ERROR;
162+
const ngx_uint_t ngx_http_lua_kong_next_upstream_mask_timeout = NGX_HTTP_UPSTREAM_FT_TIMEOUT;
163+
const ngx_uint_t ngx_http_lua_kong_next_upstream_mask_invalid_header = NGX_HTTP_UPSTREAM_FT_INVALID_HEADER;
164+
const ngx_uint_t ngx_http_lua_kong_next_upstream_mask_http_500 = NGX_HTTP_UPSTREAM_FT_HTTP_500;
165+
const ngx_uint_t ngx_http_lua_kong_next_upstream_mask_http_502 = NGX_HTTP_UPSTREAM_FT_HTTP_502;
166+
const ngx_uint_t ngx_http_lua_kong_next_upstream_mask_http_503 = NGX_HTTP_UPSTREAM_FT_HTTP_503;
167+
const ngx_uint_t ngx_http_lua_kong_next_upstream_mask_http_504 = NGX_HTTP_UPSTREAM_FT_HTTP_504;
168+
const ngx_uint_t ngx_http_lua_kong_next_upstream_mask_http_403 = NGX_HTTP_UPSTREAM_FT_HTTP_403;
169+
const ngx_uint_t ngx_http_lua_kong_next_upstream_mask_http_404 = NGX_HTTP_UPSTREAM_FT_HTTP_404;
170+
const ngx_uint_t ngx_http_lua_kong_next_upstream_mask_http_429 = NGX_HTTP_UPSTREAM_FT_HTTP_429;
171+
const ngx_uint_t ngx_http_lua_kong_next_upstream_mask_off = NGX_HTTP_UPSTREAM_FT_OFF;
172+
const ngx_uint_t ngx_http_lua_kong_next_upstream_mask_non_idempotent = NGX_HTTP_UPSTREAM_FT_NON_IDEMPOTENT;
173+
174+
ngx_flag_t
175+
ngx_http_lua_kong_get_next_upstream_mask(ngx_http_request_t *r,
176+
ngx_flag_t upstream_next)
177+
{
178+
ngx_http_lua_kong_ctx_t *ctx;
179+
180+
ctx = ngx_http_lua_kong_get_module_ctx(r);
181+
if (ctx == NULL) {
182+
return upstream_next;
183+
}
184+
185+
if(ctx->next_upstream != 0) {
186+
return ctx->next_upstream;
187+
}
188+
return upstream_next;
189+
}
190+
191+
int
192+
ngx_http_lua_ffi_set_next_upstream(ngx_http_request_t *r, ngx_uint_t next_upstream, char **err)
193+
{
194+
ngx_http_lua_kong_ctx_t *ctx;
195+
196+
ctx = ngx_http_lua_kong_get_module_ctx(r);
197+
if (ctx == NULL) {
198+
return NGX_ERROR;
199+
}
161200

201+
ctx->next_upstream = next_upstream;
202+
return NGX_OK;
203+
}

src/ngx_http_lua_kong_module.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,4 +40,8 @@ ngx_flag_t
4040
ngx_http_lua_kong_ssl_get_http2_alpn_enabled(ngx_ssl_connection_t *ssl,
4141
ngx_flag_t enable_http2);
4242

43+
ngx_flag_t
44+
ngx_http_lua_kong_get_next_upstream_mask(ngx_http_request_t *r,
45+
ngx_flag_t upstream_next);
46+
4347
#endif /* _NGX_HTTP_LUA_KONG_MODULE_H_INCLUDED_ */

0 commit comments

Comments
 (0)