Branch data Line data Source code
1 : : #define DDEBUG 0
2 : : #include "ddebug.h"
3 : :
4 : : #include "ngx_http_echo_echo.h"
5 : : #include "ngx_http_echo_util.h"
6 : : #include "ngx_http_echo_filter.h"
7 : :
8 : : #include <nginx.h>
9 : :
10 : : static ngx_buf_t ngx_http_echo_space_buf;
11 : :
12 : : static ngx_buf_t ngx_http_echo_newline_buf;
13 : :
14 : : ngx_int_t
15 : 88 : ngx_http_echo_echo_init(ngx_conf_t *cf)
16 : : {
17 : : static u_char space_str[] = " ";
18 : : static u_char newline_str[] = "\n";
19 : :
20 : : dd("global init...");
21 : :
22 : 88 : ngx_memzero(&ngx_http_echo_space_buf, sizeof(ngx_buf_t));
23 : 88 : ngx_http_echo_space_buf.memory = 1;
24 : 176 : ngx_http_echo_space_buf.start =
25 : 88 : ngx_http_echo_space_buf.pos =
26 : : space_str;
27 : 176 : ngx_http_echo_space_buf.end =
28 : 88 : ngx_http_echo_space_buf.last =
29 : : space_str + sizeof(space_str) - 1;
30 : :
31 : 88 : ngx_memzero(&ngx_http_echo_newline_buf, sizeof(ngx_buf_t));
32 : 88 : ngx_http_echo_newline_buf.memory = 1;
33 : 176 : ngx_http_echo_newline_buf.start =
34 : 88 : ngx_http_echo_newline_buf.pos =
35 : : newline_str;
36 : 176 : ngx_http_echo_newline_buf.end =
37 : 88 : ngx_http_echo_newline_buf.last =
38 : : newline_str + sizeof(newline_str) - 1;
39 : :
40 : 88 : return NGX_OK;
41 : : }
42 : :
43 : :
44 : : ngx_int_t
45 : 110 : ngx_http_echo_exec_echo(ngx_http_request_t *r,
46 : : ngx_http_echo_ctx_t *ctx, ngx_array_t *computed_args,
47 : : ngx_flag_t in_filter, ngx_array_t *opts)
48 : : {
49 : : ngx_uint_t i;
50 : :
51 : : ngx_buf_t *space_buf;
52 : : ngx_buf_t *newline_buf;
53 : : ngx_buf_t *buf;
54 : :
55 : : ngx_str_t *computed_arg;
56 : : ngx_str_t *computed_arg_elts;
57 : : ngx_str_t *opt;
58 : :
59 : 110 : ngx_chain_t *cl = NULL; /* the head of the chain link */
60 : 110 : ngx_chain_t **ll = &cl; /* always point to the address of the last link */
61 : :
62 : :
63 : : dd_enter();
64 : :
65 [ - + ]: 110 : if (computed_args == NULL) {
66 : 0 : return NGX_HTTP_INTERNAL_SERVER_ERROR;
67 : : }
68 : :
69 : 110 : computed_arg_elts = computed_args->elts;
70 [ + + ]: 222 : for (i = 0; i < computed_args->nelts; i++) {
71 : 112 : computed_arg = &computed_arg_elts[i];
72 : :
73 [ + + ]: 112 : if (computed_arg->len == 0) {
74 : 6 : buf = NULL;
75 : :
76 : : } else {
77 : 106 : buf = ngx_calloc_buf(r->pool);
78 [ - + ]: 106 : if (buf == NULL) {
79 : 0 : return NGX_HTTP_INTERNAL_SERVER_ERROR;
80 : : }
81 : :
82 : 106 : buf->start = buf->pos = computed_arg->data;
83 : 106 : buf->last = buf->end = computed_arg->data +
84 : : computed_arg->len;
85 : :
86 : 106 : buf->memory = 1;
87 : : }
88 : :
89 [ + + ]: 112 : if (cl == NULL) {
90 : 110 : cl = ngx_alloc_chain_link(r->pool);
91 [ - + ]: 110 : if (cl == NULL) {
92 : 0 : return NGX_HTTP_INTERNAL_SERVER_ERROR;
93 : : }
94 : 110 : cl->buf = buf;
95 : 110 : cl->next = NULL;
96 : 110 : ll = &cl->next;
97 : : } else {
98 : : /* append a space first */
99 : 2 : *ll = ngx_alloc_chain_link(r->pool);
100 : :
101 [ - + ]: 2 : if (*ll == NULL) {
102 : 0 : return NGX_HTTP_INTERNAL_SERVER_ERROR;
103 : : }
104 : :
105 : 2 : space_buf = ngx_calloc_buf(r->pool);
106 : :
107 [ - + ]: 2 : if (space_buf == NULL) {
108 : 0 : return NGX_HTTP_INTERNAL_SERVER_ERROR;
109 : : }
110 : :
111 : : /* nginx clears buf flags at the end of each request handling,
112 : : * so we have to make a clone here. */
113 : 2 : *space_buf = ngx_http_echo_space_buf;
114 : :
115 : 2 : (*ll)->buf = space_buf;
116 : 2 : (*ll)->next = NULL;
117 : :
118 : 2 : ll = &(*ll)->next;
119 : :
120 : : /* then append the buf only if it's non-empty */
121 [ - + ]: 2 : if (buf) {
122 : 0 : *ll = ngx_alloc_chain_link(r->pool);
123 [ # # ]: 0 : if (*ll == NULL) {
124 : 0 : return NGX_HTTP_INTERNAL_SERVER_ERROR;
125 : : }
126 : 0 : (*ll)->buf = buf;
127 : 0 : (*ll)->next = NULL;
128 : :
129 : 0 : ll = &(*ll)->next;
130 : : }
131 : : }
132 : : } /* end for */
133 : :
134 [ + - ][ + + ]: 110 : if (opts && opts->nelts > 0) {
135 : 9 : opt = opts->elts;
136 [ + - ][ + - ]: 9 : if (opt[0].len == 1 && opt[0].data[0] == 'n') {
137 : 9 : goto done;
138 : : }
139 : : }
140 : :
141 : : /* append the newline character */
142 : :
143 [ + - ][ + + ]: 101 : if (cl && cl->buf == NULL) {
144 : 4 : cl = cl->next;
145 : : }
146 : :
147 : 101 : newline_buf = ngx_calloc_buf(r->pool);
148 : :
149 [ - + ]: 101 : if (newline_buf == NULL) {
150 : 0 : return NGX_HTTP_INTERNAL_SERVER_ERROR;
151 : : }
152 : :
153 : 101 : *newline_buf = ngx_http_echo_newline_buf;
154 : :
155 [ + + ]: 101 : if (cl == NULL) {
156 : 4 : cl = ngx_alloc_chain_link(r->pool);
157 : :
158 [ - + ]: 4 : if (cl == NULL) {
159 : 0 : return NGX_HTTP_INTERNAL_SERVER_ERROR;
160 : : }
161 : :
162 : 4 : cl->buf = newline_buf;
163 : 4 : cl->next = NULL;
164 : : /* ll = &cl->next; */
165 : :
166 : : } else {
167 : 97 : *ll = ngx_alloc_chain_link(r->pool);
168 : :
169 [ - + ]: 97 : if (*ll == NULL) {
170 : 0 : return NGX_HTTP_INTERNAL_SERVER_ERROR;
171 : : }
172 : :
173 : 97 : (*ll)->buf = newline_buf;
174 : 97 : (*ll)->next = NULL;
175 : : /* ll = &(*ll)->next; */
176 : : }
177 : :
178 : : done:
179 : :
180 [ + - ][ - + ]: 110 : if (cl == NULL || cl->buf == NULL) {
181 : 0 : return NGX_OK;
182 : : }
183 : :
184 [ - + ]: 110 : if (in_filter) {
185 : 0 : return ngx_http_echo_next_body_filter(r, cl);
186 : : }
187 : :
188 : 110 : return ngx_http_echo_send_chain_link(r, ctx, cl);
189 : : }
190 : :
191 : :
192 : : ngx_int_t
193 : 0 : ngx_http_echo_exec_echo_flush(ngx_http_request_t *r, ngx_http_echo_ctx_t *ctx)
194 : : {
195 : 0 : return ngx_http_send_special(r, NGX_HTTP_FLUSH);
196 : : }
197 : :
198 : :
199 : : ngx_int_t
200 : 4 : ngx_http_echo_exec_echo_request_body(ngx_http_request_t *r,
201 : : ngx_http_echo_ctx_t *ctx)
202 : : {
203 [ + - ][ + - ]: 4 : if (r->request_body && r->request_body->bufs) {
204 : 4 : return ngx_http_echo_send_chain_link(r, ctx, r->request_body->bufs);
205 : : }
206 : :
207 : 4 : return NGX_OK;
208 : : }
209 : :
210 : :
211 : : ngx_int_t
212 : 0 : ngx_http_echo_exec_echo_duplicate(ngx_http_request_t *r,
213 : : ngx_http_echo_ctx_t *ctx, ngx_array_t *computed_args)
214 : : {
215 : : ngx_str_t *computed_arg;
216 : : ngx_str_t *computed_arg_elts;
217 : : ssize_t i, count;
218 : : ngx_str_t *str;
219 : : u_char *p;
220 : : ngx_int_t rc;
221 : :
222 : : ngx_buf_t *buf;
223 : : ngx_chain_t *cl;
224 : :
225 : :
226 : : dd_enter();
227 : :
228 : 0 : computed_arg_elts = computed_args->elts;
229 : :
230 : 0 : computed_arg = &computed_arg_elts[0];
231 : :
232 : 0 : count = ngx_http_echo_atosz(computed_arg->data, computed_arg->len);
233 : :
234 [ # # ]: 0 : if (count == NGX_ERROR) {
235 [ # # ]: 0 : ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
236 : : "invalid size specified: \"%V\"", computed_arg);
237 : :
238 : 0 : return NGX_HTTP_INTERNAL_SERVER_ERROR;
239 : : }
240 : :
241 : 0 : str = &computed_arg_elts[1];
242 : :
243 [ # # ][ # # ]: 0 : if (count == 0 || str->len == 0) {
244 : 0 : rc = ngx_http_echo_send_header_if_needed(r, ctx);
245 [ # # ][ # # ]: 0 : if (r->header_only || rc >= NGX_HTTP_SPECIAL_RESPONSE) {
246 : 0 : return rc;
247 : : }
248 : 0 : return NGX_OK;
249 : : }
250 : :
251 : 0 : buf = ngx_create_temp_buf(r->pool, count * str->len);
252 [ # # ]: 0 : if (buf == NULL) {
253 : 0 : return NGX_HTTP_INTERNAL_SERVER_ERROR;
254 : : }
255 : :
256 : 0 : p = buf->pos;
257 [ # # ]: 0 : for (i = 0; i < count; i++) {
258 : 0 : p = ngx_copy(p, str->data, str->len);
259 : : }
260 : 0 : buf->last = p;
261 : :
262 : 0 : cl = ngx_alloc_chain_link(r->pool);
263 [ # # ]: 0 : if (cl == NULL) {
264 : 0 : return NGX_HTTP_INTERNAL_SERVER_ERROR;
265 : : }
266 : 0 : cl->next = NULL;
267 : 0 : cl->buf = buf;
268 : :
269 : 0 : return ngx_http_echo_send_chain_link(r, ctx, cl);
270 : : }
271 : :
|