Skip to content

Commit abc4a76

Browse files
authored
feat: enable mirror on demand (#30)
1 parent 7a14531 commit abc4a76

File tree

6 files changed

+196
-0
lines changed

6 files changed

+196
-0
lines changed

README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,9 @@
77
default: off
88

99
Delay client_max_body_size check until the body is read.
10+
11+
### apisix_mirror_on_demand [on|off]
12+
13+
default: off
14+
15+
Disable request mirror until we enable it in the Lua code.

lib/resty/apisix/client.lua

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@ typedef unsigned char u_char;
1717
ngx_int_t
1818
ngx_http_apisix_client_set_max_body_size(ngx_http_request_t *r, off_t bytes);
1919
20+
ngx_int_t
21+
ngx_http_apisix_enable_mirror(ngx_http_request_t *r);
22+
2023
ngx_int_t
2124
ngx_http_apisix_set_real_ip(ngx_http_request_t *r, const u_char *text, size_t len,
2225
unsigned int port);
@@ -35,6 +38,17 @@ function _M.set_client_max_body_size(bytes)
3538
end
3639

3740

41+
function _M.enable_mirror()
42+
local r = get_request()
43+
local ret = C.ngx_http_apisix_enable_mirror(r)
44+
if ret == NGX_ERROR then
45+
return nil, "error while disaling mirror"
46+
end
47+
48+
return true
49+
end
50+
51+
3852
function _M.set_real_ip(ip, port)
3953
-- APISIX will ensure the IP and port are valid
4054
if not port then

patch/1.19.9/nginx-mirror.patch

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
diff --git src/http/modules/ngx_http_mirror_module.c src/http/modules/ngx_http_mirror_module.c
2+
index 787adb3..61d0fd3 100644
3+
--- src/http/modules/ngx_http_mirror_module.c
4+
+++ src/http/modules/ngx_http_mirror_module.c
5+
@@ -8,10 +8,16 @@
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+
typedef struct {
15+
ngx_array_t *mirror;
16+
+#if (NGX_HTTP_APISIX)
17+
+ ngx_flag_t on_demand;
18+
+#endif
19+
ngx_flag_t request_body;
20+
} ngx_http_mirror_loc_conf_t;
21+
22+
@@ -33,6 +39,15 @@ static ngx_int_t ngx_http_mirror_init(ngx_conf_t *cf);
23+
24+
static ngx_command_t ngx_http_mirror_commands[] = {
25+
26+
+#if (NGX_HTTP_APISIX)
27+
+ { ngx_string("apisix_mirror_on_demand"),
28+
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
29+
+ ngx_conf_set_flag_slot,
30+
+ NGX_HTTP_LOC_CONF_OFFSET,
31+
+ offsetof(ngx_http_mirror_loc_conf_t, on_demand),
32+
+ NULL },
33+
+#endif
34+
+
35+
{ ngx_string("mirror"),
36+
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
37+
ngx_http_mirror,
38+
@@ -99,6 +114,12 @@ ngx_http_mirror_handler(ngx_http_request_t *r)
39+
return NGX_DECLINED;
40+
}
41+
42+
+#if (NGX_HTTP_APISIX)
43+
+ if (mlcf->on_demand && !ngx_http_apisix_is_mirror_enabled(r)) {
44+
+ return NGX_DECLINED;
45+
+ }
46+
+#endif
47+
+
48+
ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "mirror handler");
49+
50+
if (mlcf->request_body) {
51+
@@ -186,6 +207,9 @@ ngx_http_mirror_create_loc_conf(ngx_conf_t *cf)
52+
}
53+
54+
mlcf->mirror = NGX_CONF_UNSET_PTR;
55+
+#if (NGX_HTTP_APISIX)
56+
+ mlcf->on_demand = NGX_CONF_UNSET;
57+
+#endif
58+
mlcf->request_body = NGX_CONF_UNSET;
59+
60+
return mlcf;
61+
@@ -198,6 +222,9 @@ ngx_http_mirror_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
62+
ngx_http_mirror_loc_conf_t *prev = parent;
63+
ngx_http_mirror_loc_conf_t *conf = child;
64+
65+
+#if (NGX_HTTP_APISIX)
66+
+ ngx_conf_merge_value(conf->on_demand, prev->on_demand, 0);
67+
+#endif
68+
ngx_conf_merge_ptr_value(conf->mirror, prev->mirror, NULL);
69+
ngx_conf_merge_value(conf->request_body, prev->request_body, 1);
70+

src/ngx_http_apisix_module.c

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -472,3 +472,29 @@ ngx_http_apisix_set_real_ip(ngx_http_request_t *r, const u_char *text, size_t le
472472

473473
return NGX_OK;
474474
}
475+
476+
477+
ngx_int_t
478+
ngx_http_apisix_enable_mirror(ngx_http_request_t *r)
479+
{
480+
ngx_http_apisix_ctx_t *ctx;
481+
482+
ctx = ngx_http_apisix_get_module_ctx(r);
483+
484+
if (ctx == NULL) {
485+
return NGX_ERROR;
486+
}
487+
488+
ctx->mirror_enabled = 1;
489+
return NGX_OK;
490+
}
491+
492+
493+
ngx_int_t
494+
ngx_http_apisix_is_mirror_enabled(ngx_http_request_t *r)
495+
{
496+
ngx_http_apisix_ctx_t *ctx;
497+
498+
ctx = ngx_http_apisix_get_module_ctx(r);
499+
return ctx != NULL && ctx->mirror_enabled;
500+
}

src/ngx_http_apisix_module.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ typedef struct {
2626
ngx_http_apisix_gzip_t *gzip;
2727

2828
unsigned client_max_body_size_set:1;
29+
unsigned mirror_enabled:1;
2930
} ngx_http_apisix_ctx_t;
3031

3132

@@ -39,5 +40,7 @@ ngx_int_t ngx_http_apisix_get_gzip_buffer_conf(ngx_http_request_t *r,
3940
ngx_int_t *num, size_t *size);
4041
ngx_int_t ngx_http_apisix_get_gzip_compress_level(ngx_http_request_t *r);
4142

43+
ngx_int_t ngx_http_apisix_is_mirror_enabled(ngx_http_request_t *r);
44+
4245

4346
#endif /* _NGX_HTTP_APISIX_H_INCLUDED_ */

t/mirror.t

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
use t::APISIX_NGINX 'no_plan';
2+
3+
run_tests();
4+
5+
__DATA__
6+
7+
=== TEST 1: mirror
8+
--- config
9+
location /mirror {
10+
content_by_lua_block {
11+
ngx.log(ngx.WARN, "mirror request with ", ngx.req.get_method())
12+
}
13+
}
14+
location /t {
15+
mirror /mirror;
16+
content_by_lua_block {
17+
ngx.exit(200)
18+
}
19+
}
20+
--- request
21+
POST /t
22+
blahblah
23+
--- grep_error_log eval
24+
qr/mirror request with \w+/
25+
--- grep_error_log_out
26+
mirror request with POST
27+
28+
29+
30+
=== TEST 2: mirror on demand
31+
--- config
32+
location /mirror {
33+
content_by_lua_block {
34+
ngx.log(ngx.WARN, "mirror request with ", ngx.req.get_method())
35+
}
36+
}
37+
location /t {
38+
mirror /mirror;
39+
apisix_mirror_on_demand on;
40+
content_by_lua_block {
41+
ngx.exit(200)
42+
}
43+
}
44+
--- request
45+
POST /t
46+
blahblah
47+
--- grep_error_log eval
48+
qr/mirror request with \w+/
49+
--- grep_error_log_out
50+
51+
52+
53+
=== TEST 3: mirror on demand, enabled
54+
--- config
55+
location /mirror {
56+
content_by_lua_block {
57+
ngx.log(ngx.WARN, "mirror request with ", ngx.req.get_method())
58+
}
59+
}
60+
location /t {
61+
mirror /mirror;
62+
apisix_mirror_on_demand on;
63+
access_by_lua_block {
64+
local client = require("resty.apisix.client")
65+
assert(client.enable_mirror())
66+
}
67+
content_by_lua_block {
68+
ngx.exit(200)
69+
}
70+
}
71+
--- request
72+
POST /t
73+
blahblah
74+
--- grep_error_log eval
75+
qr/mirror request with \w+/
76+
--- grep_error_log_out
77+
mirror request with POST

0 commit comments

Comments
 (0)