Branch data Line data Source code
1 : : #define DDEBUG 0
2 : : #include "ddebug.h"
3 : :
4 : : #include "ngx_http_echo_util.h"
5 : : #include "ngx_http_echo_sleep.h"
6 : :
7 : :
8 : : ngx_http_echo_ctx_t *
9 : 104 : ngx_http_echo_create_ctx(ngx_http_request_t *r)
10 : : {
11 : : ngx_http_echo_ctx_t *ctx;
12 : :
13 : 104 : ctx = ngx_pcalloc(r->pool, sizeof(ngx_http_echo_ctx_t));
14 [ - + ]: 104 : if (ctx == NULL) {
15 : 0 : return NULL;
16 : : }
17 : :
18 : 104 : ctx->sleep.handler = ngx_http_echo_sleep_event_handler;
19 : 104 : ctx->sleep.data = r;
20 : 104 : ctx->sleep.log = r->connection->log;
21 : :
22 : 104 : return ctx;
23 : : }
24 : :
25 : :
26 : : ngx_int_t
27 : 120 : ngx_http_echo_eval_cmd_args(ngx_http_request_t *r,
28 : : ngx_http_echo_cmd_t *cmd, ngx_array_t *computed_args,
29 : : ngx_array_t *opts)
30 : : {
31 : : ngx_uint_t i;
32 : 120 : ngx_array_t *args = cmd->args;
33 : : ngx_str_t *arg, *raw, *opt;
34 : : ngx_http_echo_arg_template_t *value;
35 : 120 : ngx_flag_t expecting_opts = 1;
36 : :
37 : 120 : value = args->elts;
38 : :
39 [ + + ]: 243 : for (i = 0; i < args->nelts; i++) {
40 : 123 : raw = &value[i].raw_value;
41 : :
42 [ + + ][ + - ]: 123 : if (value[i].lengths == NULL && raw->len > 0) {
43 [ + - ]: 66 : if (expecting_opts) {
44 [ + + ][ + + ]: 66 : if (raw->len == 1 || raw->data[0] != '-') {
45 : 57 : expecting_opts = 0;
46 : :
47 [ - + ]: 9 : } else if (raw->data[1] == '-') {
48 : 0 : expecting_opts = 0;
49 : 0 : continue;
50 : :
51 : : } else {
52 : 9 : opt = ngx_array_push(opts);
53 [ - + ]: 9 : if (opt == NULL) {
54 : 0 : return NGX_HTTP_INTERNAL_SERVER_ERROR;
55 : : }
56 : :
57 : 9 : opt->len = raw->len - 1;
58 : 9 : opt->data = raw->data + 1;
59 : :
60 : 9 : continue;
61 : : }
62 : : }
63 : : }
64 : :
65 : 114 : arg = ngx_array_push(computed_args);
66 [ - + ]: 114 : if (arg == NULL) {
67 : 0 : return NGX_HTTP_INTERNAL_SERVER_ERROR;
68 : : }
69 : :
70 [ + + ]: 114 : if (value[i].lengths == NULL) { /* does not contain vars */
71 : : dd("Using raw value \"%.*s\"", (int) raw->len, raw->data);
72 : 57 : *arg = *raw;
73 : :
74 : : } else {
75 [ - + ]: 57 : if (ngx_http_script_run(r, arg, value[i].lengths->elts,
76 : 57 : 0, value[i].values->elts) == NULL)
77 : : {
78 : 0 : return NGX_HTTP_INTERNAL_SERVER_ERROR;
79 : : }
80 : : }
81 : : }
82 : :
83 : 120 : return NGX_OK;
84 : : }
85 : :
86 : :
87 : : ngx_int_t
88 : 218 : ngx_http_echo_send_chain_link(ngx_http_request_t* r,
89 : : ngx_http_echo_ctx_t *ctx, ngx_chain_t *in)
90 : : {
91 : : ngx_int_t rc;
92 : : size_t size;
93 : : ngx_chain_t *cl;
94 : :
95 : 218 : rc = ngx_http_echo_send_header_if_needed(r, ctx);
96 : :
97 [ + - ][ - + ]: 218 : if (r->header_only || rc >= NGX_HTTP_SPECIAL_RESPONSE) {
98 : 0 : return rc;
99 : : }
100 : :
101 [ + + ][ + + ]: 218 : if (r->http_version < NGX_HTTP_VERSION_11 && !ctx->headers_sent) {
102 : 11 : ctx->headers_sent = 1;
103 : :
104 : 11 : size = 0;
105 : :
106 [ + + ]: 27 : for (cl = in; cl; cl = cl->next) {
107 [ + - ][ - + ]: 16 : size += ngx_buf_size(cl->buf);
[ # # ]
108 : : }
109 : :
110 : 11 : r->headers_out.content_length_n = (off_t) size;
111 : :
112 [ - + ]: 11 : if (r->headers_out.content_length) {
113 : 0 : r->headers_out.content_length->hash = 0;
114 : : }
115 : :
116 : 11 : r->headers_out.content_length = NULL;
117 : :
118 : 11 : rc = ngx_http_send_header(r);
119 : :
120 [ - + ]: 11 : if (rc >= NGX_HTTP_SPECIAL_RESPONSE) {
121 : 0 : return rc;
122 : : }
123 : : }
124 : :
125 [ + + ]: 218 : if (in == NULL) {
126 : :
127 : : #if defined(nginx_version) && nginx_version <= 8004
128 : :
129 : : /* earlier versions of nginx does not allow subrequests
130 : : to send last_buf themselves */
131 : : if (r != r->main) {
132 : : return NGX_OK;
133 : : }
134 : :
135 : : #endif
136 : :
137 : 104 : rc = ngx_http_send_special(r, NGX_HTTP_LAST);
138 [ - + ]: 104 : if (rc >= NGX_HTTP_SPECIAL_RESPONSE) {
139 : 0 : return rc;
140 : : }
141 : :
142 : 104 : return NGX_OK;
143 : : }
144 : :
145 : 218 : return ngx_http_output_filter(r, in);
146 : : }
147 : :
148 : :
149 : : ngx_int_t
150 : 220 : ngx_http_echo_send_header_if_needed(ngx_http_request_t* r,
151 : : ngx_http_echo_ctx_t *ctx)
152 : : {
153 : : /* ngx_int_t rc; */
154 : :
155 [ + + ]: 220 : if ( ! ctx->headers_sent ) {
156 : 104 : r->headers_out.status = NGX_HTTP_OK;
157 : :
158 [ - + ]: 104 : if (ngx_http_set_content_type(r) != NGX_OK) {
159 : 0 : return NGX_HTTP_INTERNAL_SERVER_ERROR;
160 : : }
161 : :
162 [ - + ]: 104 : ngx_http_clear_content_length(r);
163 [ - + ]: 104 : ngx_http_clear_accept_ranges(r);
164 : :
165 [ + + ]: 104 : if (r->http_version >= NGX_HTTP_VERSION_11) {
166 : 93 : ctx->headers_sent = 1;
167 : 93 : return ngx_http_send_header(r);
168 : : }
169 : : }
170 : :
171 : 220 : return NGX_OK;
172 : : }
173 : :
174 : :
175 : : ssize_t
176 : 0 : ngx_http_echo_atosz(u_char *line, size_t n)
177 : : {
178 : : ssize_t value;
179 : :
180 [ # # ]: 0 : if (n == 0) {
181 : 0 : return NGX_ERROR;
182 : : }
183 : :
184 [ # # ]: 0 : for (value = 0; n--; line++) {
185 [ # # ]: 0 : if (*line == '_') { /* we ignore undercores */
186 : 0 : continue;
187 : : }
188 : :
189 [ # # ][ # # ]: 0 : if (*line < '0' || *line > '9') {
190 : 0 : return NGX_ERROR;
191 : : }
192 : :
193 : 0 : value = value * 10 + (*line - '0');
194 : : }
195 : :
196 [ # # ]: 0 : if (value < 0) {
197 : 0 : return NGX_ERROR;
198 : : }
199 : :
200 : 0 : return value;
201 : : }
202 : :
203 : :
204 : : /* Modified from the ngx_strlcasestrn function in ngx_string.h
205 : : * Copyright (C) by Igor Sysoev */
206 : : u_char *
207 : 0 : ngx_http_echo_strlstrn(u_char *s1, u_char *last, u_char *s2, size_t n)
208 : : {
209 : : ngx_uint_t c1, c2;
210 : :
211 : 0 : c2 = (ngx_uint_t) *s2++;
212 : 0 : last -= n;
213 : :
214 : : do {
215 : : do {
216 [ # # ]: 0 : if (s1 >= last) {
217 : 0 : return NULL;
218 : : }
219 : :
220 : 0 : c1 = (ngx_uint_t) *s1++;
221 : :
222 [ # # ]: 0 : } while (c1 != c2);
223 : :
224 [ # # ]: 0 : } while (ngx_strncmp(s1, s2, n) != 0);
225 : :
226 : 0 : return --s1;
227 : : }
228 : :
229 : :
230 : : ngx_int_t
231 : 0 : ngx_http_echo_post_request_at_head(ngx_http_request_t *r,
232 : : ngx_http_posted_request_t *pr)
233 : : {
234 : : dd_enter();
235 : :
236 [ # # ]: 0 : if (pr == NULL) {
237 : 0 : pr = ngx_palloc(r->pool, sizeof(ngx_http_posted_request_t));
238 [ # # ]: 0 : if (pr == NULL) {
239 : 0 : return NGX_ERROR;
240 : : }
241 : : }
242 : :
243 : 0 : pr->request = r;
244 : 0 : pr->next = r->main->posted_requests;
245 : 0 : r->main->posted_requests = pr;
246 : :
247 : 0 : return NGX_OK;
248 : : }
249 : :
250 : :
251 : : u_char *
252 : 0 : ngx_http_echo_rebase_path(ngx_pool_t *pool, u_char *src, size_t osize,
253 : : size_t *nsize)
254 : : {
255 : : u_char *p, *dst;
256 : :
257 [ # # ]: 0 : if (osize == 0) {
258 : 0 : return NULL;
259 : : }
260 : :
261 [ # # ]: 0 : if (src[0] == '/') {
262 : : /* being an absolute path already, just add a trailing '\0' */
263 : 0 : *nsize = osize;
264 : :
265 : 0 : dst = ngx_palloc(pool, *nsize + 1);
266 [ # # ]: 0 : if (dst == NULL) {
267 : 0 : *nsize = 0;
268 : 0 : return NULL;
269 : : }
270 : :
271 : 0 : p = ngx_copy(dst, src, osize);
272 : 0 : *p = '\0';
273 : :
274 : 0 : return dst;
275 : : }
276 : :
277 : 0 : *nsize = ngx_cycle->prefix.len + osize;
278 : :
279 : 0 : dst = ngx_palloc(pool, *nsize + 1);
280 [ # # ]: 0 : if (dst == NULL) {
281 : 0 : *nsize = 0;
282 : 0 : return NULL;
283 : : }
284 : :
285 : 0 : p = ngx_copy(dst, ngx_cycle->prefix.data, ngx_cycle->prefix.len);
286 : 0 : p = ngx_copy(p, src, osize);
287 : :
288 : 0 : *p = '\0';
289 : :
290 : 0 : return dst;
291 : : }
292 : :
293 : :
294 : : ngx_int_t
295 : 0 : ngx_http_echo_flush_postponed_outputs(ngx_http_request_t *r)
296 : : {
297 [ # # ][ # # ]: 0 : if (r == r->connection->data && r->postponed) {
298 : : /* notify the downstream postpone filter to flush the postponed
299 : : * outputs of the current request */
300 : 0 : return ngx_http_output_filter(r, NULL);
301 : : }
302 : :
303 : : /* do nothing */
304 : 0 : return NGX_OK;
305 : : }
|