Coverage Report

Created: 2022-11-30 06:08

/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
9
10
static nxt_int_t nxt_http_var_dollar(nxt_task_t *task, nxt_str_t *str,
11
    void *ctx, uint16_t field);
12
static nxt_int_t nxt_http_var_request_time(nxt_task_t *task, nxt_str_t *str,
13
    void *ctx, uint16_t field);
14
static nxt_int_t nxt_http_var_method(nxt_task_t *task, nxt_str_t *str,
15
    void *ctx, uint16_t field);
16
static nxt_int_t nxt_http_var_request_uri(nxt_task_t *task, nxt_str_t *str,
17
    void *ctx, uint16_t field);
18
static nxt_int_t nxt_http_var_uri(nxt_task_t *task, nxt_str_t *str, void *ctx,
19
    uint16_t field);
20
static nxt_int_t nxt_http_var_host(nxt_task_t *task, nxt_str_t *str, void *ctx,
21
    uint16_t field);
22
static nxt_int_t nxt_http_var_remote_addr(nxt_task_t *task, nxt_str_t *str,
23
    void *ctx, uint16_t field);
24
static nxt_int_t nxt_http_var_time_local(nxt_task_t *task, nxt_str_t *str,
25
    void *ctx, uint16_t field);
26
static u_char *nxt_http_log_date(u_char *buf, nxt_realtime_t *now,
27
    struct tm *tm, size_t size, const char *format);
28
static nxt_int_t nxt_http_var_request_line(nxt_task_t *task, nxt_str_t *str,
29
    void *ctx, uint16_t field);
30
static nxt_int_t nxt_http_var_status(nxt_task_t *task, nxt_str_t *str,
31
    void *ctx, uint16_t field);
32
static nxt_int_t nxt_http_var_body_bytes_sent(nxt_task_t *task, nxt_str_t *str,
33
    void *ctx, uint16_t field);
34
static nxt_int_t nxt_http_var_referer(nxt_task_t *task, nxt_str_t *str,
35
    void *ctx, uint16_t field);
36
static nxt_int_t nxt_http_var_user_agent(nxt_task_t *task, nxt_str_t *str,
37
    void *ctx, uint16_t field);
38
static nxt_int_t nxt_http_var_arg(nxt_task_t *task, nxt_str_t *str, void *ctx,
39
    uint16_t field);
40
static nxt_int_t nxt_http_var_header(nxt_task_t *task, nxt_str_t *str,
41
    void *ctx, uint16_t field);
42
static nxt_int_t nxt_http_var_cookie(nxt_task_t *task, nxt_str_t *str,
43
    void *ctx, uint16_t field);
44
45
46
static nxt_var_decl_t  nxt_http_vars[] = {
47
    {
48
        .name = nxt_string("dollar"),
49
        .handler = nxt_http_var_dollar,
50
    }, {
51
        .name = nxt_string("request_time"),
52
        .handler = nxt_http_var_request_time,
53
    }, {
54
        .name = nxt_string("method"),
55
        .handler = nxt_http_var_method,
56
    }, {
57
        .name = nxt_string("request_uri"),
58
        .handler = nxt_http_var_request_uri,
59
    }, {
60
        .name = nxt_string("uri"),
61
        .handler = nxt_http_var_uri,
62
    }, {
63
        .name = nxt_string("host"),
64
        .handler = nxt_http_var_host,
65
    }, {
66
        .name = nxt_string("remote_addr"),
67
        .handler = nxt_http_var_remote_addr,
68
    }, {
69
        .name = nxt_string("time_local"),
70
        .handler = nxt_http_var_time_local,
71
    }, {
72
        .name = nxt_string("request_line"),
73
        .handler = nxt_http_var_request_line,
74
    }, {
75
        .name = nxt_string("status"),
76
        .handler = nxt_http_var_status,
77
    }, {
78
        .name = nxt_string("body_bytes_sent"),
79
        .handler = nxt_http_var_body_bytes_sent,
80
    }, {
81
        .name = nxt_string("header_referer"),
82
        .handler = nxt_http_var_referer,
83
    }, {
84
        .name = nxt_string("header_user_agent"),
85
        .handler = nxt_http_var_user_agent,
86
    }, {
87
        .name = nxt_string("arg"),
88
        .handler = nxt_http_var_arg,
89
        .field_hash = nxt_http_argument_hash,
90
    }, {
91
        .name = nxt_string("header"),
92
        .handler = nxt_http_var_header,
93
        .field_hash = nxt_http_header_hash,
94
    }, {
95
        .name = nxt_string("cookie"),
96
        .handler = nxt_http_var_cookie,
97
        .field_hash = nxt_http_cookie_hash,
98
    },
99
};
100
101
102
nxt_int_t
103
nxt_http_register_variables(void)
104
0
{
105
0
    return nxt_var_register(nxt_http_vars, nxt_nitems(nxt_http_vars));
106
0
}
107
108
109
static nxt_int_t
110
nxt_http_var_dollar(nxt_task_t *task, nxt_str_t *str, void *ctx, uint16_t field)
111
0
{
112
0
    nxt_str_set(str, "$");
113
114
0
    return NXT_OK;
115
0
}
116
117
118
static nxt_int_t
119
nxt_http_var_request_time(nxt_task_t *task, nxt_str_t *str, void *ctx,
120
    uint16_t field)
121
0
{
122
0
    u_char              *p;
123
0
    nxt_msec_t          ms;
124
0
    nxt_nsec_t          now;
125
0
    nxt_http_request_t  *r;
126
127
0
    r = ctx;
128
129
0
    now = nxt_thread_monotonic_time(task->thread);
130
0
    ms = (now - r->start_time) / 1000000;
131
132
0
    str->start = nxt_mp_nget(r->mem_pool, NXT_TIME_T_LEN + 4);
133
0
    if (nxt_slow_path(str->start == NULL)) {
134
0
        return NXT_ERROR;
135
0
    }
136
137
0
    p = nxt_sprintf(str->start, str->start + NXT_TIME_T_LEN, "%T.%03M",
138
0
                    (nxt_time_t) ms / 1000, ms % 1000);
139
140
0
    str->length = p - str->start;
141
142
0
    return NXT_OK;
143
0
}
144
145
146
static nxt_int_t
147
nxt_http_var_method(nxt_task_t *task, nxt_str_t *str, void *ctx, uint16_t field)
148
0
{
149
0
    nxt_http_request_t  *r;
150
151
0
    r = ctx;
152
153
0
    *str = *r->method;
154
155
0
    return NXT_OK;
156
0
}
157
158
159
static nxt_int_t
160
nxt_http_var_request_uri(nxt_task_t *task, nxt_str_t *str, void *ctx,
161
    uint16_t field)
162
0
{
163
0
    nxt_http_request_t  *r;
164
165
0
    r = ctx;
166
167
0
    *str = r->target;
168
169
0
    return NXT_OK;
170
0
}
171
172
173
static nxt_int_t
174
nxt_http_var_uri(nxt_task_t *task, nxt_str_t *str, void *ctx, uint16_t field)
175
0
{
176
0
    nxt_http_request_t  *r;
177
178
0
    r = ctx;
179
180
0
    *str = *r->path;
181
182
0
    return NXT_OK;
183
0
}
184
185
186
static nxt_int_t
187
nxt_http_var_host(nxt_task_t *task, nxt_str_t *str, void *ctx, uint16_t field)
188
0
{
189
0
    nxt_http_request_t  *r;
190
191
0
    r = ctx;
192
193
0
    *str = r->host;
194
195
0
    return NXT_OK;
196
0
}
197
198
199
static nxt_int_t
200
nxt_http_var_remote_addr(nxt_task_t *task, nxt_str_t *str, void *ctx,
201
    uint16_t field)
202
0
{
203
0
    nxt_http_request_t  *r;
204
205
0
    r = ctx;
206
207
0
    str->length = r->remote->address_length;
208
0
    str->start = nxt_sockaddr_address(r->remote);
209
210
0
    return NXT_OK;
211
0
}
212
213
214
static nxt_int_t
215
nxt_http_var_time_local(nxt_task_t *task, nxt_str_t *str, void *ctx,
216
    uint16_t field)
217
0
{
218
0
    nxt_http_request_t  *r;
219
220
0
    static nxt_time_string_t  date_cache = {
221
0
        (nxt_atomic_uint_t) -1,
222
0
        nxt_http_log_date,
223
0
        "%02d/%s/%4d:%02d:%02d:%02d %c%02d%02d",
224
0
        nxt_length("31/Dec/1986:19:40:00 +0300"),
225
0
        NXT_THREAD_TIME_LOCAL,
226
0
        NXT_THREAD_TIME_SEC,
227
0
    };
228
229
0
    r = ctx;
230
231
0
    str->length = date_cache.size;
232
233
0
    str->start = nxt_mp_nget(r->mem_pool, str->length);
234
0
    if (nxt_slow_path(str->start == NULL)) {
235
0
        return NXT_ERROR;
236
0
    }
237
238
0
    str->length = nxt_thread_time_string(task->thread, &date_cache, str->start)
239
0
                  - str->start;
240
241
0
    return NXT_OK;
242
0
}
243
244
245
static u_char *
246
nxt_http_log_date(u_char *buf, nxt_realtime_t *now, struct tm *tm,
247
    size_t size, const char *format)
248
0
{
249
0
    u_char  sign;
250
0
    time_t  gmtoff;
251
252
0
    static const char  *month[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
253
0
                                    "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
254
255
0
    gmtoff = nxt_timezone(tm) / 60;
256
257
0
    if (gmtoff < 0) {
258
0
        gmtoff = -gmtoff;
259
0
        sign = '-';
260
261
0
    } else {
262
0
        sign = '+';
263
0
    }
264
265
0
    return nxt_sprintf(buf, buf + size, format,
266
0
                       tm->tm_mday, month[tm->tm_mon], tm->tm_year + 1900,
267
0
                       tm->tm_hour, tm->tm_min, tm->tm_sec,
268
0
                       sign, gmtoff / 60, gmtoff % 60);
269
0
}
270
271
272
static nxt_int_t
273
nxt_http_var_request_line(nxt_task_t *task, nxt_str_t *str, void *ctx,
274
    uint16_t field)
275
0
{
276
0
    size_t              length;
277
0
    u_char              *p, *start;
278
0
    nxt_http_request_t  *r;
279
280
0
    r = ctx;
281
282
0
    length = r->method->length + 1 + r->target.length + 1 + r->version.length;
283
284
0
    start = nxt_mp_nget(r->mem_pool, length);
285
0
    if (nxt_slow_path(start == NULL)) {
286
0
        return NXT_ERROR;
287
0
    }
288
289
0
    p = start;
290
291
0
    if (r->method->length != 0) {
292
0
        p = nxt_cpymem(p, r->method->start, r->method->length);
293
294
0
        if (r->target.length != 0) {
295
0
            *p++ = ' ';
296
0
            p = nxt_cpymem(p, r->target.start, r->target.length);
297
298
0
            if (r->version.length != 0) {
299
0
                *p++ = ' ';
300
0
                p = nxt_cpymem(p, r->version.start, r->version.length);
301
0
            }
302
0
        }
303
304
0
    } else {
305
0
        *p++ = '-';
306
0
    }
307
308
0
    str->start = start;
309
0
    str->length = p - start;
310
311
0
    return NXT_OK;
312
0
}
313
314
315
static nxt_int_t
316
nxt_http_var_body_bytes_sent(nxt_task_t *task, nxt_str_t *str, void *ctx,
317
    uint16_t field)
318
0
{
319
0
    nxt_off_t           bytes;
320
0
    nxt_http_request_t  *r;
321
322
0
    r = ctx;
323
324
0
    str->start = nxt_mp_nget(r->mem_pool, NXT_OFF_T_LEN);
325
0
    if (nxt_slow_path(str->start == NULL)) {
326
0
        return NXT_ERROR;
327
0
    }
328
329
0
    bytes = nxt_http_proto[r->protocol].body_bytes_sent(task, r->proto);
330
331
0
    str->length = nxt_sprintf(str->start, str->start + NXT_OFF_T_LEN, "%O",
332
0
                              bytes) - str->start;
333
334
0
    return NXT_OK;
335
0
}
336
337
338
static nxt_int_t
339
nxt_http_var_status(nxt_task_t *task, nxt_str_t *str, void *ctx, uint16_t field)
340
0
{
341
0
    nxt_http_request_t  *r;
342
343
0
    r = ctx;
344
345
0
    str->start = nxt_mp_nget(r->mem_pool, 3);
346
0
    if (nxt_slow_path(str->start == NULL)) {
347
0
        return NXT_ERROR;
348
0
    }
349
350
0
    str->length = nxt_sprintf(str->start, str->start + 3, "%03d", r->status)
351
0
                  - str->start;
352
353
0
    return NXT_OK;
354
0
}
355
356
357
static nxt_int_t
358
nxt_http_var_referer(nxt_task_t *task, nxt_str_t *str, void *ctx,
359
    uint16_t field)
360
0
{
361
0
    nxt_http_request_t  *r;
362
363
0
    r = ctx;
364
365
0
    if (r->referer != NULL) {
366
0
        str->start = r->referer->value;
367
0
        str->length = r->referer->value_length;
368
369
0
    } else {
370
0
        nxt_str_null(str);
371
0
    }
372
373
0
    return NXT_OK;
374
0
}
375
376
377
static nxt_int_t
378
nxt_http_var_user_agent(nxt_task_t *task, nxt_str_t *str, void *ctx,
379
    uint16_t field)
380
0
{
381
0
    nxt_http_request_t  *r;
382
383
0
    r = ctx;
384
385
0
    if (r->user_agent != NULL) {
386
0
        str->start = r->user_agent->value;
387
0
        str->length = r->user_agent->value_length;
388
389
0
    } else {
390
0
        nxt_str_null(str);
391
0
    }
392
393
0
    return NXT_OK;
394
0
}
395
396
397
static nxt_int_t
398
nxt_http_var_arg(nxt_task_t *task, nxt_str_t *str, void *ctx, uint16_t field)
399
0
{
400
0
    nxt_array_t            *args;
401
0
    nxt_var_field_t        *vf;
402
0
    nxt_router_conf_t      *rtcf;
403
0
    nxt_http_request_t     *r;
404
0
    nxt_http_name_value_t  *nv, *start;
405
406
0
    r = ctx;
407
408
0
    rtcf = r->conf->socket_conf->router_conf;
409
410
0
    vf = nxt_var_field_get(rtcf->tstr_state->var_fields, field);
411
412
0
    args = nxt_http_arguments_parse(r);
413
0
    if (nxt_slow_path(args == NULL)) {
414
0
        return NXT_ERROR;
415
0
    }
416
417
0
    start = args->elts;
418
0
    nv = start + args->nelts - 1;
419
420
0
    while (nv >= start) {
421
422
0
        if (vf->hash == nv->hash
423
0
            && vf->name.length == nv->name_length
424
0
            && memcmp(vf->name.start, nv->name, nv->name_length) == 0)
425
0
        {
426
0
            str->start = nv->value;
427
0
            str->length = nv->value_length;
428
429
0
            return NXT_OK;
430
0
        }
431
432
0
        nv--;
433
0
    }
434
435
0
    nxt_str_null(str);
436
437
0
    return NXT_OK;
438
0
}
439
440
441
static nxt_int_t
442
nxt_http_var_header(nxt_task_t *task, nxt_str_t *str, void *ctx, uint16_t field)
443
0
{
444
0
    nxt_var_field_t     *vf;
445
0
    nxt_http_field_t    *f;
446
0
    nxt_router_conf_t   *rtcf;
447
0
    nxt_http_request_t  *r;
448
449
0
    r = ctx;
450
451
0
    rtcf = r->conf->socket_conf->router_conf;
452
453
0
    vf = nxt_var_field_get(rtcf->tstr_state->var_fields, field);
454
455
0
    nxt_list_each(f, r->fields) {
456
457
0
        if (vf->hash == f->hash
458
0
            && vf->name.length == f->name_length
459
0
            && nxt_strncasecmp(vf->name.start, f->name, f->name_length) == 0)
460
0
        {
461
0
            str->start = f->value;
462
0
            str->length = f->value_length;
463
464
0
            return NXT_OK;
465
0
        }
466
467
0
    } nxt_list_loop;
468
469
0
    nxt_str_null(str);
470
471
0
    return NXT_OK;
472
0
}
473
474
475
static nxt_int_t
476
nxt_http_var_cookie(nxt_task_t *task, nxt_str_t *str, void *ctx, uint16_t field)
477
0
{
478
0
    nxt_array_t            *cookies;
479
0
    nxt_var_field_t        *vf;
480
0
    nxt_router_conf_t      *rtcf;
481
0
    nxt_http_request_t     *r;
482
0
    nxt_http_name_value_t  *nv, *end;
483
484
0
    r = ctx;
485
486
0
    rtcf = r->conf->socket_conf->router_conf;
487
488
0
    vf = nxt_var_field_get(rtcf->tstr_state->var_fields, field);
489
490
0
    cookies = nxt_http_cookies_parse(r);
491
0
    if (nxt_slow_path(cookies == NULL)) {
492
0
        return NXT_ERROR;
493
0
    }
494
495
0
    nv = cookies->elts;
496
0
    end = nv + cookies->nelts;
497
498
0
    while (nv < end) {
499
500
0
        if (vf->hash == nv->hash
501
0
            && vf->name.length == nv->name_length
502
0
            && memcmp(vf->name.start, nv->name, nv->name_length) == 0)
503
0
        {
504
0
            str->start = nv->value;
505
0
            str->length = nv->value_length;
506
507
0
            return NXT_OK;
508
0
        }
509
510
0
        nv++;
511
0
    }
512
513
0
    nxt_str_null(str);
514
515
0
    return NXT_OK;
516
0
}