Mercurial > hg > ngx_http_delay_body_filter_module
annotate ngx_http_delay_body_filter_module.c @ 3:53cbdb610633 default tip
Fixed error handling.
Request body filters are not allowed to return NGX_ERROR, they are
expected to use NGX_HTTP_* errors, notably NGX_HTTP_INTERNAL_SERVER_ERROR.
author | Maxim Dounin <mdounin@mdounin.ru> |
---|---|
date | Thu, 26 Aug 2021 04:46:49 +0300 |
parents | b049c3a0543e |
children |
rev | line source |
---|---|
0 | 1 |
2 /* | |
3 * Copyright (C) Maxim Dounin | |
4 */ | |
5 | |
6 #include <ngx_config.h> | |
7 #include <ngx_core.h> | |
8 #include <ngx_http.h> | |
9 | |
10 | |
11 typedef struct { | |
1
7c2d64d9c656
Working delay body and tests.
Maxim Dounin <mdounin@mdounin.ru>
parents:
0
diff
changeset
|
12 ngx_msec_t delay; |
0 | 13 } ngx_http_delay_body_conf_t; |
14 | |
15 | |
1
7c2d64d9c656
Working delay body and tests.
Maxim Dounin <mdounin@mdounin.ru>
parents:
0
diff
changeset
|
16 typedef struct { |
7c2d64d9c656
Working delay body and tests.
Maxim Dounin <mdounin@mdounin.ru>
parents:
0
diff
changeset
|
17 ngx_event_t event; |
7c2d64d9c656
Working delay body and tests.
Maxim Dounin <mdounin@mdounin.ru>
parents:
0
diff
changeset
|
18 ngx_chain_t *out; |
7c2d64d9c656
Working delay body and tests.
Maxim Dounin <mdounin@mdounin.ru>
parents:
0
diff
changeset
|
19 } ngx_http_delay_body_ctx_t; |
7c2d64d9c656
Working delay body and tests.
Maxim Dounin <mdounin@mdounin.ru>
parents:
0
diff
changeset
|
20 |
7c2d64d9c656
Working delay body and tests.
Maxim Dounin <mdounin@mdounin.ru>
parents:
0
diff
changeset
|
21 |
7c2d64d9c656
Working delay body and tests.
Maxim Dounin <mdounin@mdounin.ru>
parents:
0
diff
changeset
|
22 static ngx_int_t ngx_http_delay_body_filter(ngx_http_request_t *r, |
7c2d64d9c656
Working delay body and tests.
Maxim Dounin <mdounin@mdounin.ru>
parents:
0
diff
changeset
|
23 ngx_chain_t *in); |
7c2d64d9c656
Working delay body and tests.
Maxim Dounin <mdounin@mdounin.ru>
parents:
0
diff
changeset
|
24 static void ngx_http_delay_body_cleanup(void *data); |
7c2d64d9c656
Working delay body and tests.
Maxim Dounin <mdounin@mdounin.ru>
parents:
0
diff
changeset
|
25 static void ngx_http_delay_body_event_handler(ngx_event_t *ev); |
0 | 26 static void *ngx_http_delay_body_create_conf(ngx_conf_t *cf); |
27 static char *ngx_http_delay_body_merge_conf(ngx_conf_t *cf, void *parent, | |
28 void *child); | |
29 static ngx_int_t ngx_http_delay_body_init(ngx_conf_t *cf); | |
30 | |
31 | |
32 static ngx_command_t ngx_http_delay_body_commands[] = { | |
33 | |
34 { ngx_string("delay_body"), | |
35 NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, | |
36 ngx_conf_set_msec_slot, | |
37 NGX_HTTP_LOC_CONF_OFFSET, | |
38 offsetof(ngx_http_delay_body_conf_t, delay), | |
39 NULL }, | |
40 | |
41 ngx_null_command | |
42 }; | |
43 | |
44 | |
45 static ngx_http_module_t ngx_http_delay_body_module_ctx = { | |
46 NULL, /* preconfiguration */ | |
47 ngx_http_delay_body_init, /* postconfiguration */ | |
48 | |
49 NULL, /* create main configuration */ | |
50 NULL, /* init main configuration */ | |
51 | |
52 NULL, /* create server configuration */ | |
53 NULL, /* merge server configuration */ | |
54 | |
55 ngx_http_delay_body_create_conf, /* create location configuration */ | |
56 ngx_http_delay_body_merge_conf /* merge location configuration */ | |
57 }; | |
58 | |
59 | |
60 ngx_module_t ngx_http_delay_body_filter_module = { | |
61 NGX_MODULE_V1, | |
62 &ngx_http_delay_body_module_ctx, /* module context */ | |
63 ngx_http_delay_body_commands, /* module directives */ | |
64 NGX_HTTP_MODULE, /* module type */ | |
65 NULL, /* init master */ | |
66 NULL, /* init module */ | |
67 NULL, /* init process */ | |
68 NULL, /* init thread */ | |
69 NULL, /* exit thread */ | |
70 NULL, /* exit process */ | |
71 NULL, /* exit master */ | |
72 NGX_MODULE_V1_PADDING | |
73 }; | |
74 | |
75 | |
76 static ngx_http_request_body_filter_pt ngx_http_next_request_body_filter; | |
77 | |
78 | |
79 static ngx_int_t | |
80 ngx_http_delay_body_filter(ngx_http_request_t *r, ngx_chain_t *in) | |
81 { | |
1
7c2d64d9c656
Working delay body and tests.
Maxim Dounin <mdounin@mdounin.ru>
parents:
0
diff
changeset
|
82 ngx_int_t rc; |
7c2d64d9c656
Working delay body and tests.
Maxim Dounin <mdounin@mdounin.ru>
parents:
0
diff
changeset
|
83 ngx_chain_t *cl, *ln; |
7c2d64d9c656
Working delay body and tests.
Maxim Dounin <mdounin@mdounin.ru>
parents:
0
diff
changeset
|
84 ngx_http_cleanup_t *cln; |
7c2d64d9c656
Working delay body and tests.
Maxim Dounin <mdounin@mdounin.ru>
parents:
0
diff
changeset
|
85 ngx_http_delay_body_ctx_t *ctx; |
0 | 86 ngx_http_delay_body_conf_t *conf; |
87 | |
88 conf = ngx_http_get_module_loc_conf(r, ngx_http_delay_body_filter_module); | |
89 | |
90 if (!conf->delay) { | |
91 return ngx_http_next_request_body_filter(r, in); | |
92 } | |
93 | |
94 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, | |
95 "delay request body filter"); | |
96 | |
1
7c2d64d9c656
Working delay body and tests.
Maxim Dounin <mdounin@mdounin.ru>
parents:
0
diff
changeset
|
97 ctx = ngx_http_get_module_ctx(r, ngx_http_delay_body_filter_module); |
7c2d64d9c656
Working delay body and tests.
Maxim Dounin <mdounin@mdounin.ru>
parents:
0
diff
changeset
|
98 |
7c2d64d9c656
Working delay body and tests.
Maxim Dounin <mdounin@mdounin.ru>
parents:
0
diff
changeset
|
99 if (ctx == NULL) { |
7c2d64d9c656
Working delay body and tests.
Maxim Dounin <mdounin@mdounin.ru>
parents:
0
diff
changeset
|
100 ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_delay_body_ctx_t)); |
7c2d64d9c656
Working delay body and tests.
Maxim Dounin <mdounin@mdounin.ru>
parents:
0
diff
changeset
|
101 if (ctx == NULL) { |
3 | 102 return NGX_HTTP_INTERNAL_SERVER_ERROR; |
1
7c2d64d9c656
Working delay body and tests.
Maxim Dounin <mdounin@mdounin.ru>
parents:
0
diff
changeset
|
103 } |
7c2d64d9c656
Working delay body and tests.
Maxim Dounin <mdounin@mdounin.ru>
parents:
0
diff
changeset
|
104 |
7c2d64d9c656
Working delay body and tests.
Maxim Dounin <mdounin@mdounin.ru>
parents:
0
diff
changeset
|
105 ngx_http_set_ctx(r, ctx, ngx_http_delay_body_filter_module); |
0 | 106 |
1
7c2d64d9c656
Working delay body and tests.
Maxim Dounin <mdounin@mdounin.ru>
parents:
0
diff
changeset
|
107 r->request_body->filter_need_buffering = 1; |
7c2d64d9c656
Working delay body and tests.
Maxim Dounin <mdounin@mdounin.ru>
parents:
0
diff
changeset
|
108 } |
7c2d64d9c656
Working delay body and tests.
Maxim Dounin <mdounin@mdounin.ru>
parents:
0
diff
changeset
|
109 |
7c2d64d9c656
Working delay body and tests.
Maxim Dounin <mdounin@mdounin.ru>
parents:
0
diff
changeset
|
110 if (ngx_chain_add_copy(r->pool, &ctx->out, in) != NGX_OK) { |
3 | 111 return NGX_HTTP_INTERNAL_SERVER_ERROR; |
1
7c2d64d9c656
Working delay body and tests.
Maxim Dounin <mdounin@mdounin.ru>
parents:
0
diff
changeset
|
112 } |
7c2d64d9c656
Working delay body and tests.
Maxim Dounin <mdounin@mdounin.ru>
parents:
0
diff
changeset
|
113 |
7c2d64d9c656
Working delay body and tests.
Maxim Dounin <mdounin@mdounin.ru>
parents:
0
diff
changeset
|
114 if (!ctx->event.timedout) { |
7c2d64d9c656
Working delay body and tests.
Maxim Dounin <mdounin@mdounin.ru>
parents:
0
diff
changeset
|
115 if (!ctx->event.timer_set) { |
0 | 116 |
1
7c2d64d9c656
Working delay body and tests.
Maxim Dounin <mdounin@mdounin.ru>
parents:
0
diff
changeset
|
117 /* cleanup to remove the timer in case of abnormal termination */ |
7c2d64d9c656
Working delay body and tests.
Maxim Dounin <mdounin@mdounin.ru>
parents:
0
diff
changeset
|
118 |
7c2d64d9c656
Working delay body and tests.
Maxim Dounin <mdounin@mdounin.ru>
parents:
0
diff
changeset
|
119 cln = ngx_http_cleanup_add(r, 0); |
7c2d64d9c656
Working delay body and tests.
Maxim Dounin <mdounin@mdounin.ru>
parents:
0
diff
changeset
|
120 if (cln == NULL) { |
3 | 121 return NGX_HTTP_INTERNAL_SERVER_ERROR; |
1
7c2d64d9c656
Working delay body and tests.
Maxim Dounin <mdounin@mdounin.ru>
parents:
0
diff
changeset
|
122 } |
7c2d64d9c656
Working delay body and tests.
Maxim Dounin <mdounin@mdounin.ru>
parents:
0
diff
changeset
|
123 |
7c2d64d9c656
Working delay body and tests.
Maxim Dounin <mdounin@mdounin.ru>
parents:
0
diff
changeset
|
124 cln->handler = ngx_http_delay_body_cleanup; |
7c2d64d9c656
Working delay body and tests.
Maxim Dounin <mdounin@mdounin.ru>
parents:
0
diff
changeset
|
125 cln->data = ctx; |
7c2d64d9c656
Working delay body and tests.
Maxim Dounin <mdounin@mdounin.ru>
parents:
0
diff
changeset
|
126 |
7c2d64d9c656
Working delay body and tests.
Maxim Dounin <mdounin@mdounin.ru>
parents:
0
diff
changeset
|
127 /* add timer */ |
7c2d64d9c656
Working delay body and tests.
Maxim Dounin <mdounin@mdounin.ru>
parents:
0
diff
changeset
|
128 |
7c2d64d9c656
Working delay body and tests.
Maxim Dounin <mdounin@mdounin.ru>
parents:
0
diff
changeset
|
129 ctx->event.handler = ngx_http_delay_body_event_handler; |
7c2d64d9c656
Working delay body and tests.
Maxim Dounin <mdounin@mdounin.ru>
parents:
0
diff
changeset
|
130 ctx->event.data = r; |
7c2d64d9c656
Working delay body and tests.
Maxim Dounin <mdounin@mdounin.ru>
parents:
0
diff
changeset
|
131 ctx->event.log = r->connection->log; |
7c2d64d9c656
Working delay body and tests.
Maxim Dounin <mdounin@mdounin.ru>
parents:
0
diff
changeset
|
132 |
7c2d64d9c656
Working delay body and tests.
Maxim Dounin <mdounin@mdounin.ru>
parents:
0
diff
changeset
|
133 ngx_add_timer(&ctx->event, conf->delay); |
0 | 134 } |
135 | |
1
7c2d64d9c656
Working delay body and tests.
Maxim Dounin <mdounin@mdounin.ru>
parents:
0
diff
changeset
|
136 return ngx_http_next_request_body_filter(r, NULL); |
7c2d64d9c656
Working delay body and tests.
Maxim Dounin <mdounin@mdounin.ru>
parents:
0
diff
changeset
|
137 } |
7c2d64d9c656
Working delay body and tests.
Maxim Dounin <mdounin@mdounin.ru>
parents:
0
diff
changeset
|
138 |
7c2d64d9c656
Working delay body and tests.
Maxim Dounin <mdounin@mdounin.ru>
parents:
0
diff
changeset
|
139 rc = ngx_http_next_request_body_filter(r, ctx->out); |
7c2d64d9c656
Working delay body and tests.
Maxim Dounin <mdounin@mdounin.ru>
parents:
0
diff
changeset
|
140 |
7c2d64d9c656
Working delay body and tests.
Maxim Dounin <mdounin@mdounin.ru>
parents:
0
diff
changeset
|
141 for (cl = ctx->out; cl; /* void */) { |
7c2d64d9c656
Working delay body and tests.
Maxim Dounin <mdounin@mdounin.ru>
parents:
0
diff
changeset
|
142 ln = cl; |
7c2d64d9c656
Working delay body and tests.
Maxim Dounin <mdounin@mdounin.ru>
parents:
0
diff
changeset
|
143 cl = cl->next; |
7c2d64d9c656
Working delay body and tests.
Maxim Dounin <mdounin@mdounin.ru>
parents:
0
diff
changeset
|
144 ngx_free_chain(r->pool, ln); |
0 | 145 } |
146 | |
1
7c2d64d9c656
Working delay body and tests.
Maxim Dounin <mdounin@mdounin.ru>
parents:
0
diff
changeset
|
147 ctx->out = NULL; |
7c2d64d9c656
Working delay body and tests.
Maxim Dounin <mdounin@mdounin.ru>
parents:
0
diff
changeset
|
148 |
7c2d64d9c656
Working delay body and tests.
Maxim Dounin <mdounin@mdounin.ru>
parents:
0
diff
changeset
|
149 return rc; |
7c2d64d9c656
Working delay body and tests.
Maxim Dounin <mdounin@mdounin.ru>
parents:
0
diff
changeset
|
150 } |
7c2d64d9c656
Working delay body and tests.
Maxim Dounin <mdounin@mdounin.ru>
parents:
0
diff
changeset
|
151 |
7c2d64d9c656
Working delay body and tests.
Maxim Dounin <mdounin@mdounin.ru>
parents:
0
diff
changeset
|
152 |
7c2d64d9c656
Working delay body and tests.
Maxim Dounin <mdounin@mdounin.ru>
parents:
0
diff
changeset
|
153 static void |
7c2d64d9c656
Working delay body and tests.
Maxim Dounin <mdounin@mdounin.ru>
parents:
0
diff
changeset
|
154 ngx_http_delay_body_cleanup(void *data) |
7c2d64d9c656
Working delay body and tests.
Maxim Dounin <mdounin@mdounin.ru>
parents:
0
diff
changeset
|
155 { |
7c2d64d9c656
Working delay body and tests.
Maxim Dounin <mdounin@mdounin.ru>
parents:
0
diff
changeset
|
156 ngx_http_delay_body_ctx_t *ctx = data; |
7c2d64d9c656
Working delay body and tests.
Maxim Dounin <mdounin@mdounin.ru>
parents:
0
diff
changeset
|
157 |
7c2d64d9c656
Working delay body and tests.
Maxim Dounin <mdounin@mdounin.ru>
parents:
0
diff
changeset
|
158 if (ctx->event.timer_set) { |
7c2d64d9c656
Working delay body and tests.
Maxim Dounin <mdounin@mdounin.ru>
parents:
0
diff
changeset
|
159 ngx_del_timer(&ctx->event); |
7c2d64d9c656
Working delay body and tests.
Maxim Dounin <mdounin@mdounin.ru>
parents:
0
diff
changeset
|
160 } |
7c2d64d9c656
Working delay body and tests.
Maxim Dounin <mdounin@mdounin.ru>
parents:
0
diff
changeset
|
161 } |
7c2d64d9c656
Working delay body and tests.
Maxim Dounin <mdounin@mdounin.ru>
parents:
0
diff
changeset
|
162 |
7c2d64d9c656
Working delay body and tests.
Maxim Dounin <mdounin@mdounin.ru>
parents:
0
diff
changeset
|
163 |
7c2d64d9c656
Working delay body and tests.
Maxim Dounin <mdounin@mdounin.ru>
parents:
0
diff
changeset
|
164 static void |
7c2d64d9c656
Working delay body and tests.
Maxim Dounin <mdounin@mdounin.ru>
parents:
0
diff
changeset
|
165 ngx_http_delay_body_event_handler(ngx_event_t *ev) |
7c2d64d9c656
Working delay body and tests.
Maxim Dounin <mdounin@mdounin.ru>
parents:
0
diff
changeset
|
166 { |
7c2d64d9c656
Working delay body and tests.
Maxim Dounin <mdounin@mdounin.ru>
parents:
0
diff
changeset
|
167 ngx_connection_t *c; |
7c2d64d9c656
Working delay body and tests.
Maxim Dounin <mdounin@mdounin.ru>
parents:
0
diff
changeset
|
168 ngx_http_request_t *r; |
7c2d64d9c656
Working delay body and tests.
Maxim Dounin <mdounin@mdounin.ru>
parents:
0
diff
changeset
|
169 |
7c2d64d9c656
Working delay body and tests.
Maxim Dounin <mdounin@mdounin.ru>
parents:
0
diff
changeset
|
170 r = ev->data; |
7c2d64d9c656
Working delay body and tests.
Maxim Dounin <mdounin@mdounin.ru>
parents:
0
diff
changeset
|
171 c = r->connection; |
7c2d64d9c656
Working delay body and tests.
Maxim Dounin <mdounin@mdounin.ru>
parents:
0
diff
changeset
|
172 |
7c2d64d9c656
Working delay body and tests.
Maxim Dounin <mdounin@mdounin.ru>
parents:
0
diff
changeset
|
173 ngx_log_debug0(NGX_LOG_DEBUG_HTTP, c->log, 0, |
7c2d64d9c656
Working delay body and tests.
Maxim Dounin <mdounin@mdounin.ru>
parents:
0
diff
changeset
|
174 "delay request body event"); |
7c2d64d9c656
Working delay body and tests.
Maxim Dounin <mdounin@mdounin.ru>
parents:
0
diff
changeset
|
175 |
7c2d64d9c656
Working delay body and tests.
Maxim Dounin <mdounin@mdounin.ru>
parents:
0
diff
changeset
|
176 ngx_post_event(c->read, &ngx_posted_events); |
0 | 177 } |
178 | |
179 | |
180 static void * | |
181 ngx_http_delay_body_create_conf(ngx_conf_t *cf) | |
182 { | |
183 ngx_http_delay_body_conf_t *conf; | |
184 | |
185 conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_delay_body_conf_t)); | |
186 if (conf == NULL) { | |
187 return NULL; | |
188 } | |
189 | |
190 conf->delay = NGX_CONF_UNSET_MSEC; | |
191 | |
192 return conf; | |
193 } | |
194 | |
195 | |
196 static char * | |
197 ngx_http_delay_body_merge_conf(ngx_conf_t *cf, void *parent, void *child) | |
198 { | |
199 ngx_http_delay_body_conf_t *prev = parent; | |
200 ngx_http_delay_body_conf_t *conf = child; | |
201 | |
202 ngx_conf_merge_msec_value(conf->delay, prev->delay, 0); | |
203 | |
204 return NGX_CONF_OK; | |
205 } | |
206 | |
207 | |
208 static ngx_int_t | |
209 ngx_http_delay_body_init(ngx_conf_t *cf) | |
210 { | |
211 ngx_http_next_request_body_filter = ngx_http_top_request_body_filter; | |
212 ngx_http_top_request_body_filter = ngx_http_delay_body_filter; | |
213 | |
214 return NGX_OK; | |
215 } |