/src/unit/src/nxt_http_variables.c
Line | Count | Source (jump to first uncovered line) |
1 | | |
2 | | /* |
3 | | * Copyright (C) NGINX, Inc. |
4 | | */ |
5 | | |
6 | | #include <nxt_router.h> |
7 | | #include <nxt_http.h> |
8 | | #include <nxt_h1proto.h> |
9 | | |
10 | | |
11 | | static nxt_int_t nxt_http_var_dollar(nxt_task_t *task, nxt_str_t *str, |
12 | | void *ctx, void *data); |
13 | | static nxt_int_t nxt_http_var_request_time(nxt_task_t *task, nxt_str_t *str, |
14 | | void *ctx, void *data); |
15 | | static nxt_int_t nxt_http_var_method(nxt_task_t *task, nxt_str_t *str, |
16 | | void *ctx, void *data); |
17 | | static nxt_int_t nxt_http_var_request_uri(nxt_task_t *task, nxt_str_t *str, |
18 | | void *ctx, void *data); |
19 | | static nxt_int_t nxt_http_var_uri(nxt_task_t *task, nxt_str_t *str, void *ctx, |
20 | | void *data); |
21 | | static nxt_int_t nxt_http_var_host(nxt_task_t *task, nxt_str_t *str, void *ctx, |
22 | | void *data); |
23 | | static nxt_int_t nxt_http_var_remote_addr(nxt_task_t *task, nxt_str_t *str, |
24 | | void *ctx, void *data); |
25 | | static nxt_int_t nxt_http_var_time_local(nxt_task_t *task, nxt_str_t *str, |
26 | | void *ctx, void *data); |
27 | | static u_char *nxt_http_log_date(u_char *buf, nxt_realtime_t *now, |
28 | | struct tm *tm, size_t size, const char *format); |
29 | | static nxt_int_t nxt_http_var_request_line(nxt_task_t *task, nxt_str_t *str, |
30 | | void *ctx, void *data); |
31 | | static nxt_int_t nxt_http_var_request_id(nxt_task_t *task, nxt_str_t *str, |
32 | | void *ctx, void *data); |
33 | | static nxt_int_t nxt_http_var_status(nxt_task_t *task, nxt_str_t *str, |
34 | | void *ctx, void *data); |
35 | | static nxt_int_t nxt_http_var_body_bytes_sent(nxt_task_t *task, nxt_str_t *str, |
36 | | void *ctx, void *data); |
37 | | static nxt_int_t nxt_http_var_referer(nxt_task_t *task, nxt_str_t *str, |
38 | | void *ctx, void *data); |
39 | | static nxt_int_t nxt_http_var_user_agent(nxt_task_t *task, nxt_str_t *str, |
40 | | void *ctx, void *data); |
41 | | static nxt_int_t nxt_http_var_response_connection(nxt_task_t *task, |
42 | | nxt_str_t *str, void *ctx, void *data); |
43 | | static nxt_int_t nxt_http_var_response_content_length(nxt_task_t *task, |
44 | | nxt_str_t *str, void *ctx, void *data); |
45 | | static nxt_int_t nxt_http_var_response_transfer_encoding(nxt_task_t *task, |
46 | | nxt_str_t *str, void *ctx, void *data); |
47 | | static nxt_int_t nxt_http_var_arg(nxt_task_t *task, nxt_str_t *str, void *ctx, |
48 | | void *data); |
49 | | static nxt_int_t nxt_http_var_header(nxt_task_t *task, nxt_str_t *str, |
50 | | void *ctx, void *data); |
51 | | static nxt_int_t nxt_http_var_cookie(nxt_task_t *task, nxt_str_t *str, |
52 | | void *ctx, void *data); |
53 | | static nxt_int_t nxt_http_var_response_header(nxt_task_t *task, nxt_str_t *str, |
54 | | void *ctx, void *data); |
55 | | |
56 | | |
57 | | static nxt_var_decl_t nxt_http_vars[] = { |
58 | | { |
59 | | .name = nxt_string("dollar"), |
60 | | .handler = nxt_http_var_dollar, |
61 | | .cacheable = 1, |
62 | | }, { |
63 | | .name = nxt_string("request_time"), |
64 | | .handler = nxt_http_var_request_time, |
65 | | .cacheable = 1, |
66 | | }, { |
67 | | .name = nxt_string("method"), |
68 | | .handler = nxt_http_var_method, |
69 | | .cacheable = 1, |
70 | | }, { |
71 | | .name = nxt_string("request_uri"), |
72 | | .handler = nxt_http_var_request_uri, |
73 | | .cacheable = 1, |
74 | | }, { |
75 | | .name = nxt_string("uri"), |
76 | | .handler = nxt_http_var_uri, |
77 | | .cacheable = 0, |
78 | | }, { |
79 | | .name = nxt_string("host"), |
80 | | .handler = nxt_http_var_host, |
81 | | .cacheable = 1, |
82 | | }, { |
83 | | .name = nxt_string("remote_addr"), |
84 | | .handler = nxt_http_var_remote_addr, |
85 | | .cacheable = 1, |
86 | | }, { |
87 | | .name = nxt_string("time_local"), |
88 | | .handler = nxt_http_var_time_local, |
89 | | .cacheable = 1, |
90 | | }, { |
91 | | .name = nxt_string("request_line"), |
92 | | .handler = nxt_http_var_request_line, |
93 | | .cacheable = 1, |
94 | | }, { |
95 | | .name = nxt_string("request_id"), |
96 | | .handler = nxt_http_var_request_id, |
97 | | .cacheable = 1, |
98 | | }, { |
99 | | .name = nxt_string("status"), |
100 | | .handler = nxt_http_var_status, |
101 | | .cacheable = 1, |
102 | | }, { |
103 | | .name = nxt_string("body_bytes_sent"), |
104 | | .handler = nxt_http_var_body_bytes_sent, |
105 | | .cacheable = 1, |
106 | | }, { |
107 | | .name = nxt_string("header_referer"), |
108 | | .handler = nxt_http_var_referer, |
109 | | .cacheable = 1, |
110 | | }, { |
111 | | .name = nxt_string("response_header_connection"), |
112 | | .handler = nxt_http_var_response_connection, |
113 | | .cacheable = 1, |
114 | | }, { |
115 | | .name = nxt_string("response_header_content_length"), |
116 | | .handler = nxt_http_var_response_content_length, |
117 | | .cacheable = 1, |
118 | | }, { |
119 | | .name = nxt_string("response_header_transfer_encoding"), |
120 | | .handler = nxt_http_var_response_transfer_encoding, |
121 | | .cacheable = 1, |
122 | | }, { |
123 | | .name = nxt_string("header_user_agent"), |
124 | | .handler = nxt_http_var_user_agent, |
125 | | .cacheable = 1, |
126 | | }, |
127 | | }; |
128 | | |
129 | | |
130 | | nxt_int_t |
131 | | nxt_http_register_variables(void) |
132 | 0 | { |
133 | 0 | return nxt_var_register(nxt_http_vars, nxt_nitems(nxt_http_vars)); |
134 | 0 | } |
135 | | |
136 | | |
137 | | nxt_int_t |
138 | | nxt_http_unknown_var_ref(nxt_mp_t *mp, nxt_var_ref_t *ref, nxt_str_t *name) |
139 | 3.08k | { |
140 | 3.08k | int64_t hash; |
141 | 3.08k | nxt_str_t str, *lower; |
142 | | |
143 | 3.08k | if (nxt_str_start(name, "response_header_", 16)) { |
144 | 80 | ref->handler = nxt_http_var_response_header; |
145 | 80 | ref->cacheable = 0; |
146 | | |
147 | 80 | str.start = name->start + 16; |
148 | 80 | str.length = name->length - 16; |
149 | | |
150 | 80 | if (str.length == 0) { |
151 | 2 | return NXT_ERROR; |
152 | 2 | } |
153 | | |
154 | 78 | lower = nxt_str_alloc(mp, str.length); |
155 | 78 | if (nxt_slow_path(lower == NULL)) { |
156 | 0 | return NXT_ERROR; |
157 | 0 | } |
158 | | |
159 | 78 | nxt_memcpy_lowcase(lower->start, str.start, str.length); |
160 | | |
161 | 78 | ref->data = lower; |
162 | | |
163 | 78 | return NXT_OK; |
164 | 78 | } |
165 | | |
166 | 3.00k | if (nxt_str_start(name, "header_", 7)) { |
167 | 165 | ref->handler = nxt_http_var_header; |
168 | 165 | ref->cacheable = 1; |
169 | | |
170 | 165 | str.start = name->start + 7; |
171 | 165 | str.length = name->length - 7; |
172 | | |
173 | 165 | if (str.length == 0) { |
174 | 1 | return NXT_ERROR; |
175 | 1 | } |
176 | | |
177 | 164 | hash = nxt_http_header_hash(mp, &str); |
178 | 164 | if (nxt_slow_path(hash == -1)) { |
179 | 0 | return NXT_ERROR; |
180 | 0 | } |
181 | | |
182 | 2.84k | } else if (nxt_str_start(name, "arg_", 4)) { |
183 | 2.55k | ref->handler = nxt_http_var_arg; |
184 | 2.55k | ref->cacheable = 1; |
185 | | |
186 | 2.55k | str.start = name->start + 4; |
187 | 2.55k | str.length = name->length - 4; |
188 | | |
189 | 2.55k | if (str.length == 0) { |
190 | 3 | return NXT_ERROR; |
191 | 3 | } |
192 | | |
193 | 2.54k | hash = nxt_http_argument_hash(mp, &str); |
194 | 2.54k | if (nxt_slow_path(hash == -1)) { |
195 | 0 | return NXT_ERROR; |
196 | 0 | } |
197 | | |
198 | 2.54k | } else if (nxt_str_start(name, "cookie_", 7)) { |
199 | 154 | ref->handler = nxt_http_var_cookie; |
200 | 154 | ref->cacheable = 1; |
201 | | |
202 | 154 | str.start = name->start + 7; |
203 | 154 | str.length = name->length - 7; |
204 | | |
205 | 154 | if (str.length == 0) { |
206 | 1 | return NXT_ERROR; |
207 | 1 | } |
208 | | |
209 | 153 | hash = nxt_http_cookie_hash(mp, &str); |
210 | 153 | if (nxt_slow_path(hash == -1)) { |
211 | 0 | return NXT_ERROR; |
212 | 0 | } |
213 | | |
214 | 153 | } else { |
215 | 136 | return NXT_ERROR; |
216 | 136 | } |
217 | | |
218 | 2.86k | ref->data = nxt_var_field_new(mp, &str, (uint32_t) hash); |
219 | 2.86k | if (nxt_slow_path(ref->data == NULL)) { |
220 | 0 | return NXT_ERROR; |
221 | 0 | } |
222 | | |
223 | 2.86k | return NXT_OK; |
224 | 2.86k | } |
225 | | |
226 | | |
227 | | static nxt_int_t |
228 | | nxt_http_var_dollar(nxt_task_t *task, nxt_str_t *str, void *ctx, void *data) |
229 | 0 | { |
230 | 0 | nxt_str_set(str, "$"); |
231 | |
|
232 | 0 | return NXT_OK; |
233 | 0 | } |
234 | | |
235 | | |
236 | | static nxt_int_t |
237 | | nxt_http_var_request_time(nxt_task_t *task, nxt_str_t *str, void *ctx, |
238 | | void *data) |
239 | 0 | { |
240 | 0 | u_char *p; |
241 | 0 | nxt_msec_t ms; |
242 | 0 | nxt_nsec_t now; |
243 | 0 | nxt_http_request_t *r; |
244 | |
|
245 | 0 | r = ctx; |
246 | |
|
247 | 0 | now = nxt_thread_monotonic_time(task->thread); |
248 | 0 | ms = (now - r->start_time) / 1000000; |
249 | |
|
250 | 0 | str->start = nxt_mp_nget(r->mem_pool, NXT_TIME_T_LEN + 4); |
251 | 0 | if (nxt_slow_path(str->start == NULL)) { |
252 | 0 | return NXT_ERROR; |
253 | 0 | } |
254 | | |
255 | 0 | p = nxt_sprintf(str->start, str->start + NXT_TIME_T_LEN, "%T.%03M", |
256 | 0 | (nxt_time_t) ms / 1000, ms % 1000); |
257 | |
|
258 | 0 | str->length = p - str->start; |
259 | |
|
260 | 0 | return NXT_OK; |
261 | 0 | } |
262 | | |
263 | | |
264 | | static nxt_int_t |
265 | | nxt_http_var_method(nxt_task_t *task, nxt_str_t *str, void *ctx, void *data) |
266 | 0 | { |
267 | 0 | nxt_http_request_t *r; |
268 | |
|
269 | 0 | r = ctx; |
270 | |
|
271 | 0 | *str = *r->method; |
272 | |
|
273 | 0 | return NXT_OK; |
274 | 0 | } |
275 | | |
276 | | |
277 | | static nxt_int_t |
278 | | nxt_http_var_request_uri(nxt_task_t *task, nxt_str_t *str, void *ctx, |
279 | | void *data) |
280 | 0 | { |
281 | 0 | nxt_http_request_t *r; |
282 | |
|
283 | 0 | r = ctx; |
284 | |
|
285 | 0 | *str = r->target; |
286 | |
|
287 | 0 | return NXT_OK; |
288 | 0 | } |
289 | | |
290 | | |
291 | | static nxt_int_t |
292 | | nxt_http_var_uri(nxt_task_t *task, nxt_str_t *str, void *ctx, void *data) |
293 | 0 | { |
294 | 0 | nxt_http_request_t *r; |
295 | |
|
296 | 0 | r = ctx; |
297 | |
|
298 | 0 | *str = *r->path; |
299 | |
|
300 | 0 | return NXT_OK; |
301 | 0 | } |
302 | | |
303 | | |
304 | | static nxt_int_t |
305 | | nxt_http_var_host(nxt_task_t *task, nxt_str_t *str, void *ctx, void *data) |
306 | 0 | { |
307 | 0 | nxt_http_request_t *r; |
308 | |
|
309 | 0 | r = ctx; |
310 | |
|
311 | 0 | *str = r->host; |
312 | |
|
313 | 0 | return NXT_OK; |
314 | 0 | } |
315 | | |
316 | | |
317 | | static nxt_int_t |
318 | | nxt_http_var_remote_addr(nxt_task_t *task, nxt_str_t *str, void *ctx, |
319 | | void *data) |
320 | 0 | { |
321 | 0 | nxt_http_request_t *r; |
322 | |
|
323 | 0 | r = ctx; |
324 | |
|
325 | 0 | str->length = r->remote->address_length; |
326 | 0 | str->start = nxt_sockaddr_address(r->remote); |
327 | |
|
328 | 0 | return NXT_OK; |
329 | 0 | } |
330 | | |
331 | | |
332 | | static nxt_int_t |
333 | | nxt_http_var_time_local(nxt_task_t *task, nxt_str_t *str, void *ctx, void *data) |
334 | 0 | { |
335 | 0 | nxt_http_request_t *r; |
336 | |
|
337 | 0 | static nxt_time_string_t date_cache = { |
338 | 0 | (nxt_atomic_uint_t) -1, |
339 | 0 | nxt_http_log_date, |
340 | 0 | "%02d/%s/%4d:%02d:%02d:%02d %c%02d%02d", |
341 | 0 | nxt_length("31/Dec/1986:19:40:00 +0300"), |
342 | 0 | NXT_THREAD_TIME_LOCAL, |
343 | 0 | NXT_THREAD_TIME_SEC, |
344 | 0 | }; |
345 | |
|
346 | 0 | r = ctx; |
347 | |
|
348 | 0 | str->length = date_cache.size; |
349 | |
|
350 | 0 | str->start = nxt_mp_nget(r->mem_pool, str->length); |
351 | 0 | if (nxt_slow_path(str->start == NULL)) { |
352 | 0 | return NXT_ERROR; |
353 | 0 | } |
354 | | |
355 | 0 | str->length = nxt_thread_time_string(task->thread, &date_cache, str->start) |
356 | 0 | - str->start; |
357 | |
|
358 | 0 | return NXT_OK; |
359 | 0 | } |
360 | | |
361 | | |
362 | | static u_char * |
363 | | nxt_http_log_date(u_char *buf, nxt_realtime_t *now, struct tm *tm, |
364 | | size_t size, const char *format) |
365 | 0 | { |
366 | 0 | u_char sign; |
367 | 0 | time_t gmtoff; |
368 | |
|
369 | 0 | static const char * const month[] = { "Jan", "Feb", "Mar", "Apr", "May", |
370 | 0 | "Jun", "Jul", "Aug", "Sep", "Oct", |
371 | 0 | "Nov", "Dec" }; |
372 | |
|
373 | 0 | gmtoff = nxt_timezone(tm) / 60; |
374 | |
|
375 | 0 | if (gmtoff < 0) { |
376 | 0 | gmtoff = -gmtoff; |
377 | 0 | sign = '-'; |
378 | |
|
379 | 0 | } else { |
380 | 0 | sign = '+'; |
381 | 0 | } |
382 | |
|
383 | 0 | return nxt_sprintf(buf, buf + size, format, |
384 | 0 | tm->tm_mday, month[tm->tm_mon], tm->tm_year + 1900, |
385 | 0 | tm->tm_hour, tm->tm_min, tm->tm_sec, |
386 | 0 | sign, gmtoff / 60, gmtoff % 60); |
387 | 0 | } |
388 | | |
389 | | |
390 | | static nxt_int_t |
391 | | nxt_http_var_request_line(nxt_task_t *task, nxt_str_t *str, void *ctx, |
392 | | void *data) |
393 | 0 | { |
394 | 0 | nxt_http_request_t *r; |
395 | |
|
396 | 0 | r = ctx; |
397 | |
|
398 | 0 | *str = r->request_line; |
399 | |
|
400 | 0 | return NXT_OK; |
401 | 0 | } |
402 | | |
403 | | |
404 | | static nxt_int_t |
405 | | nxt_http_var_request_id(nxt_task_t *task, nxt_str_t *str, void *ctx, |
406 | | void *data) |
407 | 0 | { |
408 | 0 | nxt_random_t *rand; |
409 | 0 | nxt_http_request_t *r; |
410 | |
|
411 | 0 | r = ctx; |
412 | |
|
413 | 0 | str->start = nxt_mp_nget(r->mem_pool, 32); |
414 | 0 | if (nxt_slow_path(str->start == NULL)) { |
415 | 0 | return NXT_ERROR; |
416 | 0 | } |
417 | | |
418 | 0 | str->length = 32; |
419 | |
|
420 | 0 | rand = &task->thread->random; |
421 | |
|
422 | 0 | (void) nxt_sprintf(str->start, str->start + 32, "%08xD%08xD%08xD%08xD", |
423 | 0 | nxt_random(rand), nxt_random(rand), |
424 | 0 | nxt_random(rand), nxt_random(rand)); |
425 | |
|
426 | 0 | return NXT_OK; |
427 | 0 | } |
428 | | |
429 | | |
430 | | static nxt_int_t |
431 | | nxt_http_var_body_bytes_sent(nxt_task_t *task, nxt_str_t *str, void *ctx, |
432 | | void *data) |
433 | 0 | { |
434 | 0 | u_char *p; |
435 | 0 | nxt_off_t bytes; |
436 | 0 | nxt_http_request_t *r; |
437 | |
|
438 | 0 | r = ctx; |
439 | |
|
440 | 0 | str->start = nxt_mp_nget(r->mem_pool, NXT_OFF_T_LEN); |
441 | 0 | if (nxt_slow_path(str->start == NULL)) { |
442 | 0 | return NXT_ERROR; |
443 | 0 | } |
444 | | |
445 | 0 | bytes = nxt_http_proto[r->protocol].body_bytes_sent(task, r->proto); |
446 | |
|
447 | 0 | p = nxt_sprintf(str->start, str->start + NXT_OFF_T_LEN, "%O", bytes); |
448 | |
|
449 | 0 | str->length = p - str->start; |
450 | |
|
451 | 0 | return NXT_OK; |
452 | 0 | } |
453 | | |
454 | | |
455 | | static nxt_int_t |
456 | | nxt_http_var_status(nxt_task_t *task, nxt_str_t *str, void *ctx, void *data) |
457 | 0 | { |
458 | 0 | nxt_http_request_t *r; |
459 | |
|
460 | 0 | r = ctx; |
461 | |
|
462 | 0 | str->start = nxt_mp_nget(r->mem_pool, 3); |
463 | 0 | if (nxt_slow_path(str->start == NULL)) { |
464 | 0 | return NXT_ERROR; |
465 | 0 | } |
466 | | |
467 | 0 | (void) nxt_sprintf(str->start, str->start + 3, "%03d", r->status); |
468 | |
|
469 | 0 | str->length = 3; |
470 | |
|
471 | 0 | return NXT_OK; |
472 | 0 | } |
473 | | |
474 | | |
475 | | static nxt_int_t |
476 | | nxt_http_var_referer(nxt_task_t *task, nxt_str_t *str, void *ctx, void *data) |
477 | 0 | { |
478 | 0 | nxt_http_request_t *r; |
479 | |
|
480 | 0 | r = ctx; |
481 | |
|
482 | 0 | if (r->referer != NULL) { |
483 | 0 | str->start = r->referer->value; |
484 | 0 | str->length = r->referer->value_length; |
485 | |
|
486 | 0 | } else { |
487 | 0 | nxt_str_null(str); |
488 | 0 | } |
489 | |
|
490 | 0 | return NXT_OK; |
491 | 0 | } |
492 | | |
493 | | |
494 | | static nxt_int_t |
495 | | nxt_http_var_user_agent(nxt_task_t *task, nxt_str_t *str, void *ctx, void *data) |
496 | 0 | { |
497 | 0 | nxt_http_request_t *r; |
498 | |
|
499 | 0 | r = ctx; |
500 | |
|
501 | 0 | if (r->user_agent != NULL) { |
502 | 0 | str->start = r->user_agent->value; |
503 | 0 | str->length = r->user_agent->value_length; |
504 | |
|
505 | 0 | } else { |
506 | 0 | nxt_str_null(str); |
507 | 0 | } |
508 | |
|
509 | 0 | return NXT_OK; |
510 | 0 | } |
511 | | |
512 | | |
513 | | static nxt_int_t |
514 | | nxt_http_var_response_connection(nxt_task_t *task, nxt_str_t *str, void *ctx, |
515 | | void *data) |
516 | 0 | { |
517 | 0 | nxt_int_t conn; |
518 | 0 | nxt_bool_t http11; |
519 | 0 | nxt_h1proto_t *h1p; |
520 | 0 | nxt_http_request_t *r; |
521 | |
|
522 | 0 | static const nxt_str_t connection[3] = { |
523 | 0 | nxt_string("close"), |
524 | 0 | nxt_string("keep-alive"), |
525 | 0 | nxt_string("Upgrade"), |
526 | 0 | }; |
527 | |
|
528 | 0 | r = ctx; |
529 | 0 | h1p = r->proto.h1; |
530 | |
|
531 | 0 | conn = -1; |
532 | |
|
533 | 0 | if (r->websocket_handshake && r->status == NXT_HTTP_SWITCHING_PROTOCOLS) { |
534 | 0 | conn = 2; |
535 | |
|
536 | 0 | } else { |
537 | 0 | http11 = nxt_h1p_is_http11(h1p); |
538 | |
|
539 | 0 | if (http11 ^ h1p->keepalive) { |
540 | 0 | conn = h1p->keepalive; |
541 | 0 | } |
542 | 0 | } |
543 | |
|
544 | 0 | if (conn >= 0) { |
545 | 0 | *str = connection[conn]; |
546 | |
|
547 | 0 | } else { |
548 | 0 | nxt_str_null(str); |
549 | 0 | } |
550 | |
|
551 | 0 | return NXT_OK; |
552 | 0 | } |
553 | | |
554 | | |
555 | | static nxt_int_t |
556 | | nxt_http_var_response_content_length(nxt_task_t *task, nxt_str_t *str, |
557 | | void *ctx, void *data) |
558 | 0 | { |
559 | 0 | u_char *p; |
560 | 0 | nxt_http_request_t *r; |
561 | |
|
562 | 0 | r = ctx; |
563 | |
|
564 | 0 | if (r->resp.content_length != NULL) { |
565 | 0 | str->length = r->resp.content_length->value_length; |
566 | 0 | str->start = r->resp.content_length->value; |
567 | |
|
568 | 0 | return NXT_OK; |
569 | 0 | } |
570 | | |
571 | 0 | if (r->resp.content_length_n >= 0) { |
572 | 0 | str->start = nxt_mp_nget(r->mem_pool, NXT_OFF_T_LEN); |
573 | 0 | if (str->start == NULL) { |
574 | 0 | return NXT_ERROR; |
575 | 0 | } |
576 | | |
577 | 0 | p = nxt_sprintf(str->start, str->start + NXT_OFF_T_LEN, |
578 | 0 | "%O", r->resp.content_length_n); |
579 | |
|
580 | 0 | str->length = p - str->start; |
581 | |
|
582 | 0 | return NXT_OK; |
583 | 0 | } |
584 | | |
585 | 0 | nxt_str_null(str); |
586 | |
|
587 | 0 | return NXT_OK; |
588 | 0 | } |
589 | | |
590 | | |
591 | | static nxt_int_t |
592 | | nxt_http_var_response_transfer_encoding(nxt_task_t *task, nxt_str_t *str, |
593 | | void *ctx, void *data) |
594 | 0 | { |
595 | 0 | nxt_http_request_t *r; |
596 | |
|
597 | 0 | r = ctx; |
598 | |
|
599 | 0 | if (r->proto.h1->chunked) { |
600 | 0 | nxt_str_set(str, "chunked"); |
601 | |
|
602 | 0 | } else { |
603 | 0 | nxt_str_null(str); |
604 | 0 | } |
605 | |
|
606 | 0 | return NXT_OK; |
607 | 0 | } |
608 | | |
609 | | |
610 | | static nxt_int_t |
611 | | nxt_http_var_arg(nxt_task_t *task, nxt_str_t *str, void *ctx, void *data) |
612 | 0 | { |
613 | 0 | nxt_array_t *args; |
614 | 0 | nxt_var_field_t *vf; |
615 | 0 | nxt_http_request_t *r; |
616 | 0 | nxt_http_name_value_t *nv, *start; |
617 | |
|
618 | 0 | r = ctx; |
619 | 0 | vf = data; |
620 | |
|
621 | 0 | args = nxt_http_arguments_parse(r); |
622 | 0 | if (nxt_slow_path(args == NULL)) { |
623 | 0 | return NXT_ERROR; |
624 | 0 | } |
625 | | |
626 | 0 | start = args->elts; |
627 | 0 | nv = start + args->nelts - 1; |
628 | |
|
629 | 0 | while (nv >= start) { |
630 | |
|
631 | 0 | if (vf->hash == nv->hash |
632 | 0 | && vf->name.length == nv->name_length |
633 | 0 | && memcmp(vf->name.start, nv->name, nv->name_length) == 0) |
634 | 0 | { |
635 | 0 | str->start = nv->value; |
636 | 0 | str->length = nv->value_length; |
637 | |
|
638 | 0 | return NXT_OK; |
639 | 0 | } |
640 | | |
641 | 0 | nv--; |
642 | 0 | } |
643 | | |
644 | 0 | nxt_str_null(str); |
645 | |
|
646 | 0 | return NXT_OK; |
647 | 0 | } |
648 | | |
649 | | |
650 | | static nxt_int_t |
651 | | nxt_http_var_header(nxt_task_t *task, nxt_str_t *str, void *ctx, void *data) |
652 | 0 | { |
653 | 0 | nxt_var_field_t *vf; |
654 | 0 | nxt_http_field_t *f; |
655 | 0 | nxt_http_request_t *r; |
656 | |
|
657 | 0 | r = ctx; |
658 | 0 | vf = data; |
659 | |
|
660 | 0 | nxt_list_each(f, r->fields) { |
661 | |
|
662 | 0 | if (vf->hash == f->hash |
663 | 0 | && vf->name.length == f->name_length |
664 | 0 | && nxt_strncasecmp(vf->name.start, f->name, f->name_length) == 0) |
665 | 0 | { |
666 | 0 | str->start = f->value; |
667 | 0 | str->length = f->value_length; |
668 | |
|
669 | 0 | return NXT_OK; |
670 | 0 | } |
671 | |
|
672 | 0 | } nxt_list_loop; |
673 | | |
674 | 0 | nxt_str_null(str); |
675 | |
|
676 | 0 | return NXT_OK; |
677 | 0 | } |
678 | | |
679 | | |
680 | | static nxt_int_t |
681 | | nxt_http_var_cookie(nxt_task_t *task, nxt_str_t *str, void *ctx, void *data) |
682 | 0 | { |
683 | 0 | nxt_array_t *cookies; |
684 | 0 | nxt_var_field_t *vf; |
685 | 0 | nxt_http_request_t *r; |
686 | 0 | nxt_http_name_value_t *nv, *end; |
687 | |
|
688 | 0 | r = ctx; |
689 | 0 | vf = data; |
690 | |
|
691 | 0 | cookies = nxt_http_cookies_parse(r); |
692 | 0 | if (nxt_slow_path(cookies == NULL)) { |
693 | 0 | return NXT_ERROR; |
694 | 0 | } |
695 | | |
696 | 0 | nv = cookies->elts; |
697 | 0 | end = nv + cookies->nelts; |
698 | |
|
699 | 0 | while (nv < end) { |
700 | |
|
701 | 0 | if (vf->hash == nv->hash |
702 | 0 | && vf->name.length == nv->name_length |
703 | 0 | && memcmp(vf->name.start, nv->name, nv->name_length) == 0) |
704 | 0 | { |
705 | 0 | str->start = nv->value; |
706 | 0 | str->length = nv->value_length; |
707 | |
|
708 | 0 | return NXT_OK; |
709 | 0 | } |
710 | | |
711 | 0 | nv++; |
712 | 0 | } |
713 | | |
714 | 0 | nxt_str_null(str); |
715 | |
|
716 | 0 | return NXT_OK; |
717 | 0 | } |
718 | | |
719 | | |
720 | | static int |
721 | | nxt_http_field_name_cmp(nxt_str_t *name, nxt_http_field_t *field) |
722 | 0 | { |
723 | 0 | size_t i; |
724 | 0 | u_char c1, c2; |
725 | |
|
726 | 0 | if (name->length != field->name_length) { |
727 | 0 | return 1; |
728 | 0 | } |
729 | | |
730 | 0 | for (i = 0; i < name->length; i++) { |
731 | 0 | c1 = name->start[i]; |
732 | 0 | c2 = field->name[i]; |
733 | |
|
734 | 0 | if (c2 >= 'A' && c2 <= 'Z') { |
735 | 0 | c2 |= 0x20; |
736 | |
|
737 | 0 | } else if (c2 == '-') { |
738 | 0 | c2 = '_'; |
739 | 0 | } |
740 | |
|
741 | 0 | if (c1 != c2) { |
742 | 0 | return 1; |
743 | 0 | } |
744 | 0 | } |
745 | | |
746 | 0 | return 0; |
747 | 0 | } |
748 | | |
749 | | |
750 | | static nxt_int_t |
751 | | nxt_http_var_response_header(nxt_task_t *task, nxt_str_t *str, void *ctx, |
752 | | void *data) |
753 | 0 | { |
754 | 0 | nxt_str_t *name; |
755 | 0 | nxt_http_field_t *f; |
756 | 0 | nxt_http_request_t *r; |
757 | |
|
758 | 0 | r = ctx; |
759 | 0 | name = data; |
760 | |
|
761 | 0 | nxt_list_each(f, r->resp.fields) { |
762 | |
|
763 | 0 | if (f->skip) { |
764 | 0 | continue; |
765 | 0 | } |
766 | | |
767 | 0 | if (nxt_http_field_name_cmp(name, f) == 0) { |
768 | 0 | str->start = f->value; |
769 | 0 | str->length = f->value_length; |
770 | |
|
771 | 0 | return NXT_OK; |
772 | 0 | } |
773 | |
|
774 | 0 | } nxt_list_loop; |
775 | | |
776 | 0 | nxt_str_null(str); |
777 | |
|
778 | 0 | return NXT_OK; |
779 | 0 | } |