1
/* Copyright (C) agentzh */
7
#include "ngx_http_headers_more_headers_in.h"
8
#include "ngx_http_headers_more_util.h"
14
ngx_http_headers_more_parse_directive(ngx_conf_t *cf, ngx_command_t *ngx_cmd,
15
void *conf, ngx_http_headers_more_opcode_t opcode);
19
static ngx_flag_t ngx_http_headers_more_check_type(ngx_http_request_t *r,
22
static ngx_int_t ngx_http_set_header(ngx_http_request_t *r,
23
ngx_http_headers_more_header_val_t *hv, ngx_str_t *value);
25
static ngx_int_t ngx_http_set_header_helper(ngx_http_request_t *r,
26
ngx_http_headers_more_header_val_t *hv, ngx_str_t *value,
27
ngx_table_elt_t **output_header);
29
static ngx_int_t ngx_http_set_builtin_header(ngx_http_request_t *r,
30
ngx_http_headers_more_header_val_t *hv, ngx_str_t *value);
32
static ngx_int_t ngx_http_set_content_length_header(ngx_http_request_t *r,
33
ngx_http_headers_more_header_val_t *hv, ngx_str_t *value);
35
static ngx_int_t ngx_http_clear_builtin_header(ngx_http_request_t *r,
36
ngx_http_headers_more_header_val_t *hv, ngx_str_t *value);
38
static ngx_int_t ngx_http_clear_content_length_header(ngx_http_request_t *r,
39
ngx_http_headers_more_header_val_t *hv, ngx_str_t *value);
41
static ngx_int_t ngx_http_set_host_header(ngx_http_request_t *r,
42
ngx_http_headers_more_header_val_t *hv, ngx_str_t *value);
45
static ngx_http_headers_more_set_header_t ngx_http_headers_more_set_handlers[]
49
offsetof(ngx_http_headers_in_t, host),
50
ngx_http_set_host_header },
52
{ ngx_string("Connection"),
53
offsetof(ngx_http_headers_in_t, connection),
54
ngx_http_set_builtin_header },
56
{ ngx_string("If-Modified-Since"),
57
offsetof(ngx_http_headers_in_t, if_modified_since),
58
ngx_http_set_builtin_header },
60
{ ngx_string("User-Agent"),
61
offsetof(ngx_http_headers_in_t, user_agent),
62
ngx_http_set_builtin_header },
64
{ ngx_string("Referer"),
65
offsetof(ngx_http_headers_in_t, referer),
66
ngx_http_set_builtin_header },
68
{ ngx_string("Content-Type"),
69
offsetof(ngx_http_headers_in_t, content_type),
70
ngx_http_set_builtin_header },
72
{ ngx_string("Range"),
73
offsetof(ngx_http_headers_in_t, range),
74
ngx_http_set_builtin_header },
76
{ ngx_string("If-Range"),
77
offsetof(ngx_http_headers_in_t, if_range),
78
ngx_http_set_builtin_header },
80
{ ngx_string("Transfer-Encoding"),
81
offsetof(ngx_http_headers_in_t, transfer_encoding),
82
ngx_http_set_builtin_header },
84
{ ngx_string("Expect"),
85
offsetof(ngx_http_headers_in_t, expect),
86
ngx_http_set_builtin_header },
88
{ ngx_string("Authorization"),
89
offsetof(ngx_http_headers_in_t, authorization),
90
ngx_http_set_builtin_header },
92
{ ngx_string("Keep-Alive"),
93
offsetof(ngx_http_headers_in_t, keep_alive),
94
ngx_http_set_builtin_header },
96
{ ngx_string("Content-Length"),
97
offsetof(ngx_http_headers_in_t, content_length),
98
ngx_http_set_content_length_header },
100
{ ngx_null_string, 0, ngx_http_set_header }
104
/* request time implementation */
107
ngx_http_headers_more_exec_input_cmd(ngx_http_request_t *r,
108
ngx_http_headers_more_cmd_t *cmd)
111
ngx_http_headers_more_header_val_t *h;
119
if ( ! ngx_http_headers_more_check_type(r, cmd->types) ) {
124
h = cmd->headers->elts;
125
for (i = 0; i < cmd->headers->nelts; i++) {
127
if (ngx_http_complex_value(r, &h[i].value, &value) != NGX_OK) {
132
/* XXX nginx core's ngx_http_range_parse
133
* function requires null-terminated
134
* Range header values. so we have to
135
* work-around it here */
137
if (h[i].key.len == sizeof("Range") - 1 &&
138
ngx_strncasecmp(h[i].key.data, (u_char *) "Range",
139
sizeof("Range") - 1) == 0)
143
p = ngx_palloc(r->pool, value.len + 1);
148
ngx_memcpy(p, value.data, value.len);
155
if (h[i].handler(r, &h[i], &value) != NGX_OK) {
165
ngx_http_set_header(ngx_http_request_t *r,
166
ngx_http_headers_more_header_val_t *hv, ngx_str_t *value)
168
return ngx_http_set_header_helper(r, hv, value, NULL);
173
ngx_http_set_header_helper(ngx_http_request_t *r,
174
ngx_http_headers_more_header_val_t *hv, ngx_str_t *value,
175
ngx_table_elt_t **output_header)
178
ngx_list_part_t *part;
184
part = &r->headers_in.headers.part;
187
for (i = 0; /* void */; i++) {
188
dd("i: %d, part: %p", (int) i, part);
190
if (i >= part->nelts) {
191
if (part->next == NULL) {
200
if (h[i].key.len == hv->key.len
201
&& ngx_strncasecmp(h[i].key.data,
205
if (value->len == 0) {
208
rc = ngx_http_headers_more_rm_header_helper(
209
&r->headers_in.headers, part, i);
213
*output_header = NULL;
223
*output_header = &h[i];
224
dd("setting existing builtin input header");
231
if (value->len == 0 || hv->replace) {
235
h = ngx_list_push(&r->headers_in.headers);
238
return NGX_HTTP_INTERNAL_SERVER_ERROR;
241
dd("created new header for %.*s", (int) hv->key.len, hv->key.data);
243
if (value->len == 0) {
252
h->lowcase_key = ngx_pnalloc(r->pool, h->key.len);
253
if (h->lowcase_key == NULL) {
254
return NGX_HTTP_INTERNAL_SERVER_ERROR;
257
ngx_strlow(h->lowcase_key, h->key.data, h->key.len);
262
while (r != r->main) {
263
r->parent->headers_in = r->headers_in;
272
ngx_http_set_builtin_header(ngx_http_request_t *r,
273
ngx_http_headers_more_header_val_t *hv, ngx_str_t *value)
275
ngx_table_elt_t *h, **old;
278
dd("entered set_builtin_header (input)");
281
old = (ngx_table_elt_t **) ((char *) &r->headers_in + hv->offset);
287
dd("old builtin ptr ptr: %p", old);
289
dd("old builtin ptr: %p", *old);
292
if (old == NULL || *old == NULL) {
293
dd("set normal header");
294
return ngx_http_set_header_helper(r, hv, value, old);
299
if (value->len == 0) {
303
rc = ngx_http_headers_more_rm_header(&r->headers_in.headers, h);
305
dd("rm header: %d", (int) rc);
321
ngx_http_set_host_header(ngx_http_request_t *r,
322
ngx_http_headers_more_header_val_t *hv, ngx_str_t *value)
324
dd("server new value len: %d", (int) value->len);
326
r->headers_in.server = *value;
328
return ngx_http_set_builtin_header(r, hv, value);
332
ngx_http_set_content_length_header(ngx_http_request_t *r,
333
ngx_http_headers_more_header_val_t *hv, ngx_str_t *value)
337
if (value->len == 0) {
338
return ngx_http_clear_content_length_header(r, hv, value);
341
len = ngx_atosz(value->data, value->len);
342
if (len == NGX_ERROR) {
346
dd("reset headers_in.content_length_n to %d", (int)len);
348
r->headers_in.content_length_n = len;
350
return ngx_http_set_builtin_header(r, hv, value);
354
ngx_http_clear_content_length_header(ngx_http_request_t *r,
355
ngx_http_headers_more_header_val_t *hv, ngx_str_t *value)
357
r->headers_in.content_length_n = -1;
359
return ngx_http_clear_builtin_header(r, hv, value);
363
ngx_http_clear_builtin_header(ngx_http_request_t *r,
364
ngx_http_headers_more_header_val_t *hv, ngx_str_t *value)
367
return ngx_http_set_builtin_header(r, hv, value);
371
ngx_http_headers_more_set_input_headers(ngx_conf_t *cf,
372
ngx_command_t *cmd, void *conf)
374
return ngx_http_headers_more_parse_directive(cf, cmd, conf,
375
ngx_http_headers_more_opcode_set);
379
ngx_http_headers_more_clear_input_headers(ngx_conf_t *cf,
380
ngx_command_t *cmd, void *conf)
382
return ngx_http_headers_more_parse_directive(cf, cmd, conf,
383
ngx_http_headers_more_opcode_clear);
387
ngx_http_headers_more_check_type(ngx_http_request_t *r, ngx_array_t *types)
391
ngx_str_t actual_type;
393
if (r->headers_in.content_type == NULL) {
397
actual_type = r->headers_in.content_type->value;
398
if (actual_type.len == 0) {
402
dd("headers_in->content_type: %.*s",
403
(int) actual_type.len,
407
for (i = 0; i < types->nelts; i++) {
408
dd("...comparing with type [%.*s]", (int) t[i].len, t[i].data);
410
if (actual_type.len == t[i].len
411
&& ngx_strncmp(actual_type.data,
412
t[i].data, t[i].len) == 0)
421
/* config time implementation */
424
ngx_http_headers_more_parse_directive(ngx_conf_t *cf, ngx_command_t *ngx_cmd,
425
void *conf, ngx_http_headers_more_opcode_t opcode)
427
ngx_http_headers_more_loc_conf_t *hcf = conf;
430
ngx_http_headers_more_cmd_t *cmd;
432
ngx_flag_t ignore_next_arg;
435
ngx_flag_t replace = 0;
436
ngx_http_headers_more_header_val_t *h;
438
if (hcf->cmds == NULL) {
439
hcf->cmds = ngx_array_create(cf->pool, 1,
440
sizeof(ngx_http_headers_more_cmd_t));
442
if (hcf->cmds == NULL) {
443
return NGX_CONF_ERROR;
447
cmd = ngx_array_push(hcf->cmds);
450
return NGX_CONF_ERROR;
453
cmd->headers = ngx_array_create(cf->pool, 1,
454
sizeof(ngx_http_headers_more_header_val_t));
456
if (cmd->headers == NULL) {
457
return NGX_CONF_ERROR;
460
cmd->types = ngx_array_create(cf->pool, 1,
462
if (cmd->types == NULL) {
463
return NGX_CONF_ERROR;
466
cmd->statuses = NULL;
468
arg = cf->args->elts;
474
for (i = 1; i < cf->args->nelts; i++) {
475
if (ignore_next_arg) {
480
if (arg[i].len == 0) {
484
if (arg[i].data[0] != '-') {
485
rc = ngx_http_headers_more_parse_header(cf, cmd_name,
486
&arg[i], cmd->headers, opcode,
487
ngx_http_headers_more_set_handlers);
490
return NGX_CONF_ERROR;
496
if (arg[i].len == 2) {
497
if (arg[i].data[1] == 't') {
498
if (i == cf->args->nelts - 1) {
499
ngx_log_error(NGX_LOG_ERR, cf->log, 0,
500
"%V: option -t takes an argument.",
503
return NGX_CONF_ERROR;
506
rc = ngx_http_headers_more_parse_types(cf->log, cmd_name,
507
&arg[i + 1], cmd->types);
510
return NGX_CONF_ERROR;
516
} else if (arg[i].data[1] == 'r') {
517
dd("Found replace flag");
523
ngx_log_error(NGX_LOG_ERR, cf->log, 0,
524
"%V: invalid option name: \"%V\"",
527
return NGX_CONF_ERROR;
530
dd("Found %d types, and %d headers",
531
(int) cmd->types->nelts,
532
(int) cmd->headers->nelts);
534
if (cmd->headers->nelts == 0) {
535
ngx_pfree(cf->pool, cmd->headers);
538
h = cmd->headers->elts;
539
for (i = 0; i < cmd->headers->nelts; i++) {
540
h[i].replace = replace;
544
if (cmd->types->nelts == 0) {
545
ngx_pfree(cf->pool, cmd->types);
551
ngx_http_headers_more_handler_used = 1;