Initial Commit
This commit is contained in:
380
headers-more-nginx-module-0.32/ngx_http_headers_more_util.c
Normal file
380
headers-more-nginx-module-0.32/ngx_http_headers_more_util.c
Normal file
@@ -0,0 +1,380 @@
|
||||
|
||||
/*
|
||||
* Copyright (C) Yichun Zhang (agentzh)
|
||||
*/
|
||||
|
||||
|
||||
#ifndef DDEBUG
|
||||
#define DDEBUG 0
|
||||
#endif
|
||||
#include "ddebug.h"
|
||||
|
||||
|
||||
#include "ngx_http_headers_more_util.h"
|
||||
#include <ctype.h>
|
||||
|
||||
|
||||
ngx_int_t
|
||||
ngx_http_headers_more_parse_header(ngx_conf_t *cf, ngx_str_t *cmd_name,
|
||||
ngx_str_t *raw_header, ngx_array_t *headers,
|
||||
ngx_http_headers_more_opcode_t opcode,
|
||||
ngx_http_headers_more_set_header_t *handlers)
|
||||
{
|
||||
ngx_http_headers_more_header_val_t *hv;
|
||||
|
||||
ngx_uint_t i;
|
||||
ngx_str_t key = ngx_null_string;
|
||||
ngx_str_t value = ngx_null_string;
|
||||
ngx_flag_t seen_end_of_key;
|
||||
ngx_http_compile_complex_value_t ccv;
|
||||
u_char *p;
|
||||
|
||||
hv = ngx_array_push(headers);
|
||||
if (hv == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
seen_end_of_key = 0;
|
||||
for (i = 0; i < raw_header->len; i++) {
|
||||
if (key.len == 0) {
|
||||
if (isspace(raw_header->data[i])) {
|
||||
continue;
|
||||
}
|
||||
|
||||
key.data = raw_header->data;
|
||||
key.len = 1;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!seen_end_of_key) {
|
||||
if (raw_header->data[i] == ':'
|
||||
|| isspace(raw_header->data[i]))
|
||||
{
|
||||
seen_end_of_key = 1;
|
||||
continue;
|
||||
}
|
||||
|
||||
key.len++;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (value.len == 0) {
|
||||
if (raw_header->data[i] == ':'
|
||||
|| isspace(raw_header->data[i]))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
value.data = &raw_header->data[i];
|
||||
value.len = 1;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
value.len++;
|
||||
}
|
||||
|
||||
if (key.len == 0) {
|
||||
ngx_log_error(NGX_LOG_ERR, cf->log, 0,
|
||||
"%V: no key found in the header argument: %V",
|
||||
cmd_name, raw_header);
|
||||
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
hv->wildcard = (key.data[key.len - 1] == '*');
|
||||
if (hv->wildcard && key.len<2){
|
||||
ngx_log_error(NGX_LOG_ERR, cf->log, 0,
|
||||
"%V: wildcard key too short: %V",
|
||||
cmd_name, raw_header);
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
hv->hash = ngx_hash_key_lc(key.data, key.len);
|
||||
hv->key = key;
|
||||
|
||||
hv->offset = 0;
|
||||
|
||||
for (i = 0; handlers[i].name.len; i++) {
|
||||
if (hv->key.len != handlers[i].name.len
|
||||
|| ngx_strncasecmp(hv->key.data, handlers[i].name.data,
|
||||
handlers[i].name.len) != 0)
|
||||
{
|
||||
dd("hv key comparison: %s <> %s", handlers[i].name.data,
|
||||
hv->key.data);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
hv->offset = handlers[i].offset;
|
||||
hv->handler = handlers[i].handler;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
if (handlers[i].name.len == 0 && handlers[i].handler) {
|
||||
hv->offset = handlers[i].offset;
|
||||
hv->handler = handlers[i].handler;
|
||||
}
|
||||
|
||||
if (opcode == ngx_http_headers_more_opcode_clear) {
|
||||
value.len = 0;
|
||||
}
|
||||
|
||||
if (value.len == 0) {
|
||||
ngx_memzero(&hv->value, sizeof(ngx_http_complex_value_t));
|
||||
return NGX_OK;
|
||||
|
||||
}
|
||||
|
||||
/* Nginx request header value requires to be a null-terminated
|
||||
* C string */
|
||||
|
||||
p = ngx_palloc(cf->pool, value.len + 1);
|
||||
if (p == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
ngx_memcpy(p, value.data, value.len);
|
||||
p[value.len] = '\0';
|
||||
value.data = p;
|
||||
value.len++; /* we should also compile the trailing '\0' */
|
||||
|
||||
/* compile the header value as a complex value */
|
||||
|
||||
ngx_memzero(&ccv, sizeof(ngx_http_compile_complex_value_t));
|
||||
|
||||
ccv.cf = cf;
|
||||
ccv.value = &value;
|
||||
ccv.complex_value = &hv->value;
|
||||
|
||||
if (ngx_http_compile_complex_value(&ccv) != NGX_OK) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
|
||||
ngx_int_t
|
||||
ngx_http_headers_more_parse_statuses(ngx_log_t *log, ngx_str_t *cmd_name,
|
||||
ngx_str_t *value, ngx_array_t *statuses)
|
||||
{
|
||||
u_char *p, *last;
|
||||
ngx_uint_t *s = NULL;
|
||||
|
||||
p = value->data;
|
||||
last = p + value->len;
|
||||
|
||||
for (; p != last; p++) {
|
||||
if (s == NULL) {
|
||||
if (isspace(*p)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
s = ngx_array_push(statuses);
|
||||
if (s == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
if (*p >= '0' && *p <= '9') {
|
||||
*s = *p - '0';
|
||||
|
||||
} else {
|
||||
ngx_log_error(NGX_LOG_ERR, log, 0,
|
||||
"%V: invalid digit \"%c\" found in "
|
||||
"the status code list \"%V\"",
|
||||
cmd_name, *p, value);
|
||||
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (isspace(*p)) {
|
||||
dd("Parsed status %d", (int) *s);
|
||||
|
||||
s = NULL;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (*p >= '0' && *p <= '9') {
|
||||
*s *= 10;
|
||||
*s += *p - '0';
|
||||
|
||||
} else {
|
||||
ngx_log_error(NGX_LOG_ERR, log, 0,
|
||||
"%V: invalid digit \"%c\" found in "
|
||||
"the status code list \"%V\"",
|
||||
cmd_name, *p, value);
|
||||
|
||||
return NGX_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
if (s) {
|
||||
dd("Parsed status %d", (int) *s);
|
||||
}
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
|
||||
ngx_int_t
|
||||
ngx_http_headers_more_parse_types(ngx_log_t *log, ngx_str_t *cmd_name,
|
||||
ngx_str_t *value, ngx_array_t *types)
|
||||
{
|
||||
u_char *p, *last;
|
||||
ngx_str_t *t = NULL;
|
||||
|
||||
p = value->data;
|
||||
last = p + value->len;
|
||||
|
||||
for (; p != last; p++) {
|
||||
if (t == NULL) {
|
||||
if (isspace(*p) || *p == ';') {
|
||||
continue;
|
||||
}
|
||||
|
||||
t = ngx_array_push(types);
|
||||
if (t == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
t->len = 1;
|
||||
t->data = p;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
if (isspace(*p) || *p == ';') {
|
||||
t = NULL;
|
||||
continue;
|
||||
}
|
||||
|
||||
t->len++;
|
||||
}
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
|
||||
ngx_int_t
|
||||
ngx_http_headers_more_rm_header_helper(ngx_list_t *l, ngx_list_part_t *cur,
|
||||
ngx_uint_t i)
|
||||
{
|
||||
ngx_table_elt_t *data;
|
||||
ngx_list_part_t *new, *part;
|
||||
|
||||
dd("list rm item: part %p, i %d, nalloc %d", cur, (int) i,
|
||||
(int) l->nalloc);
|
||||
|
||||
data = cur->elts;
|
||||
|
||||
dd("cur: nelts %d, nalloc %d", (int) cur->nelts,
|
||||
(int) l->nalloc);
|
||||
|
||||
if (i == 0) {
|
||||
cur->elts = (char *) cur->elts + l->size;
|
||||
cur->nelts--;
|
||||
|
||||
if (cur == l->last) {
|
||||
if (cur->nelts == 0) {
|
||||
#if 1
|
||||
part = &l->part;
|
||||
|
||||
if (part == cur) {
|
||||
cur->elts = (char *) cur->elts - l->size;
|
||||
/* do nothing */
|
||||
|
||||
} else {
|
||||
while (part->next != cur) {
|
||||
if (part->next == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
part = part->next;
|
||||
}
|
||||
|
||||
l->last = part;
|
||||
part->next = NULL;
|
||||
dd("part nelts: %d", (int) part->nelts);
|
||||
l->nalloc = part->nelts;
|
||||
}
|
||||
#endif
|
||||
|
||||
} else {
|
||||
l->nalloc--;
|
||||
}
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
if (cur->nelts == 0) {
|
||||
part = &l->part;
|
||||
|
||||
if (part == cur) {
|
||||
ngx_http_headers_more_assert(cur->next != NULL);
|
||||
|
||||
dd("remove 'cur' from the list by rewriting 'cur': "
|
||||
"l->last: %p, cur: %p, cur->next: %p, part: %p",
|
||||
l->last, cur, cur->next, part);
|
||||
|
||||
if (l->last == cur->next) {
|
||||
dd("last is cur->next");
|
||||
l->part = *(cur->next);
|
||||
l->last = part;
|
||||
l->nalloc = part->nelts;
|
||||
|
||||
} else {
|
||||
l->part = *(cur->next);
|
||||
}
|
||||
|
||||
} else {
|
||||
dd("remove 'cur' from the list");
|
||||
while (part->next != cur) {
|
||||
if (part->next == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
part = part->next;
|
||||
}
|
||||
|
||||
part->next = cur->next;
|
||||
}
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
if (i == cur->nelts - 1) {
|
||||
cur->nelts--;
|
||||
|
||||
if (cur == l->last) {
|
||||
l->nalloc = cur->nelts;
|
||||
}
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
|
||||
new = ngx_palloc(l->pool, sizeof(ngx_list_part_t));
|
||||
if (new == NULL) {
|
||||
return NGX_ERROR;
|
||||
}
|
||||
|
||||
new->elts = &data[i + 1];
|
||||
new->nelts = cur->nelts - i - 1;
|
||||
new->next = cur->next;
|
||||
|
||||
cur->nelts = i;
|
||||
cur->next = new;
|
||||
if (cur == l->last) {
|
||||
l->last = new;
|
||||
l->nalloc = new->nelts;
|
||||
}
|
||||
|
||||
return NGX_OK;
|
||||
}
|
||||
Reference in New Issue
Block a user