diff options
Diffstat (limited to 'src/nxt_http_variables.c')
-rw-r--r-- | src/nxt_http_variables.c | 446 |
1 files changed, 415 insertions, 31 deletions
diff --git a/src/nxt_http_variables.c b/src/nxt_http_variables.c index b765e177..5a632b24 100644 --- a/src/nxt_http_variables.c +++ b/src/nxt_http_variables.c @@ -7,32 +7,90 @@ #include <nxt_http.h> -static nxt_int_t nxt_http_var_method(nxt_task_t *task, nxt_var_query_t *query, - nxt_str_t *str, void *ctx); -static nxt_int_t nxt_http_var_request_uri(nxt_task_t *task, - nxt_var_query_t *query, nxt_str_t *str, void *ctx); -static nxt_int_t nxt_http_var_uri(nxt_task_t *task, nxt_var_query_t *query, - nxt_str_t *str, void *ctx); -static nxt_int_t nxt_http_var_host(nxt_task_t *task, nxt_var_query_t *query, - nxt_str_t *str, void *ctx); +static nxt_int_t nxt_http_var_dollar(nxt_task_t *task, nxt_str_t *str, + void *ctx, uint16_t field); +static nxt_int_t nxt_http_var_method(nxt_task_t *task, nxt_str_t *str, + void *ctx, uint16_t field); +static nxt_int_t nxt_http_var_request_uri(nxt_task_t *task, nxt_str_t *str, + void *ctx, uint16_t field); +static nxt_int_t nxt_http_var_uri(nxt_task_t *task, nxt_str_t *str, void *ctx, + uint16_t field); +static nxt_int_t nxt_http_var_host(nxt_task_t *task, nxt_str_t *str, void *ctx, + uint16_t field); +static nxt_int_t nxt_http_var_remote_addr(nxt_task_t *task, nxt_str_t *str, + void *ctx, uint16_t field); +static nxt_int_t nxt_http_var_time_local(nxt_task_t *task, nxt_str_t *str, + void *ctx, uint16_t field); +static u_char *nxt_http_log_date(u_char *buf, nxt_realtime_t *now, + struct tm *tm, size_t size, const char *format); +static nxt_int_t nxt_http_var_request_line(nxt_task_t *task, nxt_str_t *str, + void *ctx, uint16_t field); +static nxt_int_t nxt_http_var_status(nxt_task_t *task, nxt_str_t *str, + void *ctx, uint16_t field); +static nxt_int_t nxt_http_var_body_bytes_sent(nxt_task_t *task, nxt_str_t *str, + void *ctx, uint16_t field); +static nxt_int_t nxt_http_var_referer(nxt_task_t *task, nxt_str_t *str, + void *ctx, uint16_t field); +static nxt_int_t nxt_http_var_user_agent(nxt_task_t *task, nxt_str_t *str, + void *ctx, uint16_t field); +static nxt_int_t nxt_http_var_arg(nxt_task_t *task, nxt_str_t *str, void *ctx, + uint16_t field); +static nxt_int_t nxt_http_var_header(nxt_task_t *task, nxt_str_t *str, + void *ctx, uint16_t field); +static nxt_int_t nxt_http_var_cookie(nxt_task_t *task, nxt_str_t *str, + void *ctx, uint16_t field); static nxt_var_decl_t nxt_http_vars[] = { - { nxt_string("method"), - &nxt_http_var_method, - 0 }, - - { nxt_string("request_uri"), - &nxt_http_var_request_uri, - 0 }, - - { nxt_string("uri"), - &nxt_http_var_uri, - 0 }, - - { nxt_string("host"), - &nxt_http_var_host, - 0 }, + { + .name = nxt_string("dollar"), + .handler = nxt_http_var_dollar, + }, { + .name = nxt_string("method"), + .handler = nxt_http_var_method, + }, { + .name = nxt_string("request_uri"), + .handler = nxt_http_var_request_uri, + }, { + .name = nxt_string("uri"), + .handler = nxt_http_var_uri, + }, { + .name = nxt_string("host"), + .handler = nxt_http_var_host, + }, { + .name = nxt_string("remote_addr"), + .handler = nxt_http_var_remote_addr, + }, { + .name = nxt_string("time_local"), + .handler = nxt_http_var_time_local, + }, { + .name = nxt_string("request_line"), + .handler = nxt_http_var_request_line, + }, { + .name = nxt_string("status"), + .handler = nxt_http_var_status, + }, { + .name = nxt_string("body_bytes_sent"), + .handler = nxt_http_var_body_bytes_sent, + }, { + .name = nxt_string("header_referer"), + .handler = nxt_http_var_referer, + }, { + .name = nxt_string("header_user_agent"), + .handler = nxt_http_var_user_agent, + }, { + .name = nxt_string("arg"), + .handler = nxt_http_var_arg, + .field_hash = nxt_http_argument_hash, + }, { + .name = nxt_string("header"), + .handler = nxt_http_var_header, + .field_hash = nxt_http_header_hash, + }, { + .name = nxt_string("cookie"), + .handler = nxt_http_var_cookie, + .field_hash = nxt_http_cookie_hash, + }, }; @@ -44,8 +102,16 @@ nxt_http_register_variables(void) static nxt_int_t -nxt_http_var_method(nxt_task_t *task, nxt_var_query_t *query, nxt_str_t *str, - void *ctx) +nxt_http_var_dollar(nxt_task_t *task, nxt_str_t *str, void *ctx, uint16_t field) +{ + nxt_str_set(str, "$"); + + return NXT_OK; +} + + +static nxt_int_t +nxt_http_var_method(nxt_task_t *task, nxt_str_t *str, void *ctx, uint16_t field) { nxt_http_request_t *r; @@ -58,8 +124,8 @@ nxt_http_var_method(nxt_task_t *task, nxt_var_query_t *query, nxt_str_t *str, static nxt_int_t -nxt_http_var_request_uri(nxt_task_t *task, nxt_var_query_t *query, - nxt_str_t *str, void *ctx) +nxt_http_var_request_uri(nxt_task_t *task, nxt_str_t *str, void *ctx, + uint16_t field) { nxt_http_request_t *r; @@ -72,8 +138,7 @@ nxt_http_var_request_uri(nxt_task_t *task, nxt_var_query_t *query, static nxt_int_t -nxt_http_var_uri(nxt_task_t *task, nxt_var_query_t *query, nxt_str_t *str, - void *ctx) +nxt_http_var_uri(nxt_task_t *task, nxt_str_t *str, void *ctx, uint16_t field) { nxt_http_request_t *r; @@ -86,8 +151,7 @@ nxt_http_var_uri(nxt_task_t *task, nxt_var_query_t *query, nxt_str_t *str, static nxt_int_t -nxt_http_var_host(nxt_task_t *task, nxt_var_query_t *query, nxt_str_t *str, - void *ctx) +nxt_http_var_host(nxt_task_t *task, nxt_str_t *str, void *ctx, uint16_t field) { nxt_http_request_t *r; @@ -97,3 +161,323 @@ nxt_http_var_host(nxt_task_t *task, nxt_var_query_t *query, nxt_str_t *str, return NXT_OK; } + + +static nxt_int_t +nxt_http_var_remote_addr(nxt_task_t *task, nxt_str_t *str, void *ctx, + uint16_t field) +{ + nxt_http_request_t *r; + + r = ctx; + + str->length = r->remote->address_length; + str->start = nxt_sockaddr_address(r->remote); + + return NXT_OK; +} + + +static nxt_int_t +nxt_http_var_time_local(nxt_task_t *task, nxt_str_t *str, void *ctx, + uint16_t field) +{ + nxt_http_request_t *r; + + static nxt_time_string_t date_cache = { + (nxt_atomic_uint_t) -1, + nxt_http_log_date, + "%02d/%s/%4d:%02d:%02d:%02d %c%02d%02d", + nxt_length("31/Dec/1986:19:40:00 +0300"), + NXT_THREAD_TIME_LOCAL, + NXT_THREAD_TIME_SEC, + }; + + r = ctx; + + str->length = date_cache.size; + + str->start = nxt_mp_nget(r->mem_pool, str->length); + if (nxt_slow_path(str->start == NULL)) { + return NXT_ERROR; + } + + str->length = nxt_thread_time_string(task->thread, &date_cache, str->start) + - str->start; + + return NXT_OK; +} + + +static u_char * +nxt_http_log_date(u_char *buf, nxt_realtime_t *now, struct tm *tm, + size_t size, const char *format) +{ + u_char sign; + time_t gmtoff; + + static const char *month[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; + + gmtoff = nxt_timezone(tm) / 60; + + if (gmtoff < 0) { + gmtoff = -gmtoff; + sign = '-'; + + } else { + sign = '+'; + } + + return nxt_sprintf(buf, buf + size, format, + tm->tm_mday, month[tm->tm_mon], tm->tm_year + 1900, + tm->tm_hour, tm->tm_min, tm->tm_sec, + sign, gmtoff / 60, gmtoff % 60); +} + + +static nxt_int_t +nxt_http_var_request_line(nxt_task_t *task, nxt_str_t *str, void *ctx, + uint16_t field) +{ + size_t length; + u_char *p, *start; + nxt_http_request_t *r; + + r = ctx; + + length = r->method->length + 1 + r->target.length + 1 + r->version.length; + + start = nxt_mp_nget(r->mem_pool, length); + if (nxt_slow_path(start == NULL)) { + return NXT_ERROR; + } + + p = start; + + if (r->method->length != 0) { + p = nxt_cpymem(p, r->method->start, r->method->length); + + if (r->target.length != 0) { + *p++ = ' '; + p = nxt_cpymem(p, r->target.start, r->target.length); + + if (r->version.length != 0) { + *p++ = ' '; + p = nxt_cpymem(p, r->version.start, r->version.length); + } + } + + } else { + *p++ = '-'; + } + + str->start = start; + str->length = p - start; + + return NXT_OK; +} + + +static nxt_int_t +nxt_http_var_body_bytes_sent(nxt_task_t *task, nxt_str_t *str, void *ctx, + uint16_t field) +{ + nxt_off_t bytes; + nxt_http_request_t *r; + + r = ctx; + + str->start = nxt_mp_nget(r->mem_pool, NXT_OFF_T_LEN); + if (nxt_slow_path(str->start == NULL)) { + return NXT_ERROR; + } + + bytes = nxt_http_proto[r->protocol].body_bytes_sent(task, r->proto); + + str->length = nxt_sprintf(str->start, str->start + NXT_OFF_T_LEN, "%O", + bytes) - str->start; + + return NXT_OK; +} + + +static nxt_int_t +nxt_http_var_status(nxt_task_t *task, nxt_str_t *str, void *ctx, uint16_t field) +{ + nxt_http_request_t *r; + + r = ctx; + + str->start = nxt_mp_nget(r->mem_pool, 3); + if (nxt_slow_path(str->start == NULL)) { + return NXT_ERROR; + } + + str->length = nxt_sprintf(str->start, str->start + 3, "%03d", r->status) + - str->start; + + return NXT_OK; +} + + +static nxt_int_t +nxt_http_var_referer(nxt_task_t *task, nxt_str_t *str, void *ctx, + uint16_t field) +{ + nxt_http_request_t *r; + + r = ctx; + + if (r->referer != NULL) { + str->start = r->referer->value; + str->length = r->referer->value_length; + + } else { + nxt_str_null(str); + } + + return NXT_OK; +} + + +static nxt_int_t +nxt_http_var_user_agent(nxt_task_t *task, nxt_str_t *str, void *ctx, + uint16_t field) +{ + nxt_http_request_t *r; + + r = ctx; + + if (r->user_agent != NULL) { + str->start = r->user_agent->value; + str->length = r->user_agent->value_length; + + } else { + nxt_str_null(str); + } + + return NXT_OK; +} + + +static nxt_int_t +nxt_http_var_arg(nxt_task_t *task, nxt_str_t *str, void *ctx, uint16_t field) +{ + nxt_array_t *args; + nxt_var_field_t *vf; + nxt_router_conf_t *rtcf; + nxt_http_request_t *r; + nxt_http_name_value_t *nv, *start; + + r = ctx; + + rtcf = r->conf->socket_conf->router_conf; + + vf = nxt_var_field_get(rtcf->var_fields, field); + + args = nxt_http_arguments_parse(r); + if (nxt_slow_path(args == NULL)) { + return NXT_ERROR; + } + + start = args->elts; + nv = start + args->nelts - 1; + + while (nv >= start) { + + if (vf->hash == nv->hash + && vf->name.length == nv->name_length + && nxt_memcmp(vf->name.start, nv->name, nv->name_length) == 0) + { + str->start = nv->value; + str->length = nv->value_length; + + return NXT_OK; + } + + nv--; + } + + nxt_str_null(str); + + return NXT_OK; +} + + +static nxt_int_t +nxt_http_var_header(nxt_task_t *task, nxt_str_t *str, void *ctx, uint16_t field) +{ + nxt_var_field_t *vf; + nxt_http_field_t *f; + nxt_router_conf_t *rtcf; + nxt_http_request_t *r; + + r = ctx; + + rtcf = r->conf->socket_conf->router_conf; + + vf = nxt_var_field_get(rtcf->var_fields, field); + + nxt_list_each(f, r->fields) { + + if (vf->hash == f->hash + && vf->name.length == f->name_length + && nxt_strncasecmp(vf->name.start, f->name, f->name_length) == 0) + { + str->start = f->value; + str->length = f->value_length; + + return NXT_OK; + } + + } nxt_list_loop; + + nxt_str_null(str); + + return NXT_OK; +} + + +static nxt_int_t +nxt_http_var_cookie(nxt_task_t *task, nxt_str_t *str, void *ctx, uint16_t field) +{ + nxt_array_t *cookies; + nxt_var_field_t *vf; + nxt_router_conf_t *rtcf; + nxt_http_request_t *r; + nxt_http_name_value_t *nv, *end; + + r = ctx; + + rtcf = r->conf->socket_conf->router_conf; + + vf = nxt_var_field_get(rtcf->var_fields, field); + + cookies = nxt_http_cookies_parse(r); + if (nxt_slow_path(cookies == NULL)) { + return NXT_ERROR; + } + + nv = cookies->elts; + end = nv + cookies->nelts; + + while (nv < end) { + + if (vf->hash == nv->hash + && vf->name.length == nv->name_length + && nxt_memcmp(vf->name.start, nv->name, nv->name_length) == 0) + { + str->start = nv->value; + str->length = nv->value_length; + + return NXT_OK; + } + + nv++; + } + + nxt_str_null(str); + + return NXT_OK; +} |