1
/* Copyright (C) agentzh */
7
#include "ngx_http_lua_headers.h"
8
#include "ngx_http_lua_util.h"
13
static ngx_int_t ngx_http_set_header(ngx_http_request_t *r,
14
ngx_http_lua_header_val_t *hv, ngx_str_t *value);
16
static ngx_int_t ngx_http_set_header_helper(ngx_http_request_t *r,
17
ngx_http_lua_header_val_t *hv, ngx_str_t *value,
18
ngx_table_elt_t **output_header, ngx_flag_t no_create);
20
static ngx_int_t ngx_http_set_builtin_header(ngx_http_request_t *r,
21
ngx_http_lua_header_val_t *hv, ngx_str_t *value);
23
static ngx_int_t ngx_http_set_content_length_header(ngx_http_request_t *r,
24
ngx_http_lua_header_val_t *hv, ngx_str_t *value);
26
static ngx_int_t ngx_http_set_content_type_header(ngx_http_request_t *r,
27
ngx_http_lua_header_val_t *hv, ngx_str_t *value);
29
static ngx_int_t ngx_http_clear_builtin_header(ngx_http_request_t *r,
30
ngx_http_lua_header_val_t *hv, ngx_str_t *value);
32
static ngx_int_t ngx_http_clear_content_length_header(ngx_http_request_t *r,
33
ngx_http_lua_header_val_t *hv, ngx_str_t *value);
36
static ngx_http_lua_set_header_t ngx_http_lua_set_handlers[] = {
38
{ ngx_string("Server"),
39
offsetof(ngx_http_headers_out_t, server),
40
ngx_http_set_builtin_header },
43
offsetof(ngx_http_headers_out_t, date),
44
ngx_http_set_builtin_header },
46
{ ngx_string("Content-Encoding"),
47
offsetof(ngx_http_headers_out_t, content_encoding),
48
ngx_http_set_builtin_header },
50
{ ngx_string("Location"),
51
offsetof(ngx_http_headers_out_t, location),
52
ngx_http_set_builtin_header },
54
{ ngx_string("Refresh"),
55
offsetof(ngx_http_headers_out_t, refresh),
56
ngx_http_set_builtin_header },
58
{ ngx_string("Last-Modified"),
59
offsetof(ngx_http_headers_out_t, last_modified),
60
ngx_http_set_builtin_header },
62
{ ngx_string("Content-Range"),
63
offsetof(ngx_http_headers_out_t, content_range),
64
ngx_http_set_builtin_header },
66
{ ngx_string("Accept-Ranges"),
67
offsetof(ngx_http_headers_out_t, accept_ranges),
68
ngx_http_set_builtin_header },
70
{ ngx_string("WWW-Authenticate"),
71
offsetof(ngx_http_headers_out_t, www_authenticate),
72
ngx_http_set_builtin_header },
74
{ ngx_string("Expires"),
75
offsetof(ngx_http_headers_out_t, expires),
76
ngx_http_set_builtin_header },
78
{ ngx_string("E-Tag"),
79
offsetof(ngx_http_headers_out_t, etag),
80
ngx_http_set_builtin_header },
82
{ ngx_string("Content-Length"),
83
offsetof(ngx_http_headers_out_t, content_length),
84
ngx_http_set_content_length_header },
86
{ ngx_string("Content-Type"),
88
ngx_http_set_content_type_header },
90
{ ngx_null_string, 0, ngx_http_set_header }
94
/* request time implementation */
97
ngx_http_set_header(ngx_http_request_t *r, ngx_http_lua_header_val_t *hv,
100
return ngx_http_set_header_helper(r, hv, value, NULL, 0);
105
ngx_http_set_header_helper(ngx_http_request_t *r, ngx_http_lua_header_val_t *hv,
106
ngx_str_t *value, ngx_table_elt_t **output_header,
107
ngx_flag_t no_create)
110
ngx_list_part_t *part;
112
ngx_flag_t matched = 0;
114
if (hv->no_override) {
118
part = &r->headers_out.headers.part;
121
for (i = 0; /* void */; i++) {
122
if (i >= part->nelts) {
123
if (part->next == NULL) {
132
(h[i].key.len == hv->key.len
133
&& ngx_strncasecmp(h[i].key.data,
137
(h[i].key.len >= hv->key.len-1
138
&& ngx_strncasecmp(h[i].key.data,
143
if (value->len == 0) {
144
dd("clearing normal header for %.*s", (int) hv->key.len,
153
*output_header = &h[i];
165
if (no_create && value->len == 0) {
170
h = ngx_list_push(&r->headers_out.headers);
173
return NGX_HTTP_INTERNAL_SERVER_ERROR;
176
if (value->len == 0) {
185
h->lowcase_key = ngx_pnalloc(r->pool, h->key.len);
186
if (h->lowcase_key == NULL) {
187
return NGX_HTTP_INTERNAL_SERVER_ERROR;
190
ngx_strlow(h->lowcase_key, h->key.data, h->key.len);
201
ngx_http_set_builtin_header(ngx_http_request_t *r, ngx_http_lua_header_val_t *hv,
204
ngx_table_elt_t *h, **old;
207
old = (ngx_table_elt_t **) ((char *) &r->headers_out + hv->offset);
213
if (old == NULL || *old == NULL) {
214
return ngx_http_set_header_helper(r, hv, value, old, 0);
219
if (value->len == 0) {
220
dd("clearing the builtin header");
237
ngx_http_set_content_type_header(ngx_http_request_t *r, ngx_http_lua_header_val_t *hv,
240
r->headers_out.content_type_len = value->len;
241
r->headers_out.content_type = *value;
242
r->headers_out.content_type_hash = hv->hash;
243
r->headers_out.content_type_lowcase = NULL;
247
return ngx_http_set_header_helper(r, hv, value, NULL, 1);
252
ngx_http_set_content_length_header(ngx_http_request_t *r, ngx_http_lua_header_val_t *hv,
257
if (value->len == 0) {
258
return ngx_http_clear_content_length_header(r, hv, value);
261
len = ngx_atosz(value->data, value->len);
262
if (len == NGX_ERROR) {
266
r->headers_out.content_length_n = len;
268
return ngx_http_set_builtin_header(r, hv, value);
273
ngx_http_clear_content_length_header(ngx_http_request_t *r, ngx_http_lua_header_val_t *hv,
276
r->headers_out.content_length_n = -1;
278
return ngx_http_clear_builtin_header(r, hv, value);
283
ngx_http_clear_builtin_header(ngx_http_request_t *r, ngx_http_lua_header_val_t *hv,
288
return ngx_http_set_builtin_header(r, hv, value);
293
ngx_http_lua_set_header(ngx_http_request_t *r, ngx_str_t key, ngx_str_t value,
296
ngx_http_lua_header_val_t hv;
297
ngx_http_lua_set_header_t *handlers = ngx_http_lua_set_handlers;
301
dd("set header value: %.*s", (int) value.len, value.data);
307
hv.no_override = ! override;
309
for (i = 0; handlers[i].name.len; i++) {
310
if (hv.key.len != handlers[i].name.len
311
|| ngx_strncasecmp(hv.key.data, handlers[i].name.data,
312
handlers[i].name.len) != 0)
314
dd("hv key comparison: %s <> %s", handlers[i].name.data, hv.key.data);
319
dd("Matched handler: %s %s", handlers[i].name.data, hv.key.data);
321
hv.offset = handlers[i].offset;
322
hv.handler = handlers[i].handler;
327
if (handlers[i].name.len == 0 && handlers[i].handler) {
328
hv.offset = handlers[i].offset;
329
hv.handler = handlers[i].handler;
332
return hv.handler(r, &hv, &value);