LCOV - code coverage report
Current view: top level - home/build/openresty-1.13.6.1/build/ngx_lua-0.10.11/src - ngx_http_lua_headers_in.c (source / functions) Hit Total Coverage
Test: coverage ngix Lines: 0 275 0.0 %
Date: 2020-03-03 04:25:50 Functions: 0 13 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : 
       2             : /*
       3             :  * Copyright (C) Yichun Zhang (agentzh)
       4             :  */
       5             : 
       6             : 
       7             : #ifndef DDEBUG
       8             : #define DDEBUG 0
       9             : #endif
      10             : #include "ddebug.h"
      11             : 
      12             : 
      13             : #include <nginx.h>
      14             : #include "ngx_http_lua_headers_in.h"
      15             : #include "ngx_http_lua_util.h"
      16             : #include <ctype.h>
      17             : 
      18             : 
      19             : static ngx_int_t ngx_http_set_header(ngx_http_request_t *r,
      20             :     ngx_http_lua_header_val_t *hv, ngx_str_t *value);
      21             : static ngx_int_t ngx_http_set_header_helper(ngx_http_request_t *r,
      22             :     ngx_http_lua_header_val_t *hv, ngx_str_t *value,
      23             :     ngx_table_elt_t **output_header);
      24             : static ngx_int_t ngx_http_set_builtin_header(ngx_http_request_t *r,
      25             :     ngx_http_lua_header_val_t *hv, ngx_str_t *value);
      26             : static ngx_int_t ngx_http_set_user_agent_header(ngx_http_request_t *r,
      27             :     ngx_http_lua_header_val_t *hv, ngx_str_t *value);
      28             : static ngx_int_t ngx_http_set_connection_header(ngx_http_request_t *r,
      29             :     ngx_http_lua_header_val_t *hv, ngx_str_t *value);
      30             : static ngx_int_t ngx_http_set_content_length_header(ngx_http_request_t *r,
      31             :     ngx_http_lua_header_val_t *hv, ngx_str_t *value);
      32             : static ngx_int_t ngx_http_set_builtin_multi_header(ngx_http_request_t *r,
      33             :     ngx_http_lua_header_val_t *hv, ngx_str_t *value);
      34             : static ngx_int_t ngx_http_clear_builtin_header(ngx_http_request_t *r,
      35             :     ngx_http_lua_header_val_t *hv, ngx_str_t *value);
      36             : static ngx_int_t ngx_http_clear_content_length_header(ngx_http_request_t *r,
      37             :     ngx_http_lua_header_val_t *hv, ngx_str_t *value);
      38             : static ngx_int_t ngx_http_lua_validate_host(ngx_str_t *host, ngx_pool_t *pool,
      39             :     ngx_uint_t alloc);
      40             : static ngx_int_t ngx_http_set_host_header(ngx_http_request_t *r,
      41             :     ngx_http_lua_header_val_t *hv, ngx_str_t *value);
      42             : static ngx_int_t ngx_http_lua_rm_header_helper(ngx_list_t *l,
      43             :     ngx_list_part_t *cur, ngx_uint_t i);
      44             : 
      45             : 
      46             : static ngx_http_lua_set_header_t  ngx_http_lua_set_handlers[] = {
      47             :     { ngx_string("Host"),
      48             :                  offsetof(ngx_http_headers_in_t, host),
      49             :                  ngx_http_set_host_header },
      50             : 
      51             :     { ngx_string("Connection"),
      52             :                  offsetof(ngx_http_headers_in_t, connection),
      53             :                  ngx_http_set_connection_header },
      54             : 
      55             :     { ngx_string("If-Modified-Since"),
      56             :                  offsetof(ngx_http_headers_in_t, if_modified_since),
      57             :                  ngx_http_set_builtin_header },
      58             : 
      59             : #if defined(nginx_version) && nginx_version >= 9002
      60             :     { ngx_string("If-Unmodified-Since"),
      61             :                  offsetof(ngx_http_headers_in_t, if_unmodified_since),
      62             :                  ngx_http_set_builtin_header },
      63             : #endif
      64             : 
      65             : #if defined(nginx_version) && nginx_version >= 1003003
      66             :     { ngx_string("If-Match"),
      67             :                  offsetof(ngx_http_headers_in_t, if_match),
      68             :                  ngx_http_set_builtin_header },
      69             : 
      70             :     { ngx_string("If-None-Match"),
      71             :                  offsetof(ngx_http_headers_in_t, if_none_match),
      72             :                  ngx_http_set_builtin_header },
      73             : #endif
      74             : 
      75             :     { ngx_string("User-Agent"),
      76             :                  offsetof(ngx_http_headers_in_t, user_agent),
      77             :                  ngx_http_set_user_agent_header },
      78             : 
      79             :     { ngx_string("Referer"),
      80             :                  offsetof(ngx_http_headers_in_t, referer),
      81             :                  ngx_http_set_builtin_header },
      82             : 
      83             :     { ngx_string("Content-Length"),
      84             :                  offsetof(ngx_http_headers_in_t, content_length),
      85             :                  ngx_http_set_content_length_header },
      86             : 
      87             :     { ngx_string("Content-Type"),
      88             :                  offsetof(ngx_http_headers_in_t, content_type),
      89             :                  ngx_http_set_builtin_header },
      90             : 
      91             :     { ngx_string("Range"),
      92             :                  offsetof(ngx_http_headers_in_t, range),
      93             :                  ngx_http_set_builtin_header },
      94             : 
      95             :     { ngx_string("If-Range"),
      96             :                  offsetof(ngx_http_headers_in_t, if_range),
      97             :                  ngx_http_set_builtin_header },
      98             : 
      99             :     { ngx_string("Transfer-Encoding"),
     100             :                  offsetof(ngx_http_headers_in_t, transfer_encoding),
     101             :                  ngx_http_set_builtin_header },
     102             : 
     103             :     { ngx_string("Expect"),
     104             :                  offsetof(ngx_http_headers_in_t, expect),
     105             :                  ngx_http_set_builtin_header },
     106             : 
     107             : #if defined(nginx_version) && nginx_version >= 1003013
     108             :     { ngx_string("Upgrade"),
     109             :                  offsetof(ngx_http_headers_in_t, upgrade),
     110             :                  ngx_http_set_builtin_header },
     111             : #endif
     112             : 
     113             : #if (NGX_HTTP_GZIP)
     114             :     { ngx_string("Accept-Encoding"),
     115             :                  offsetof(ngx_http_headers_in_t, accept_encoding),
     116             :                  ngx_http_set_builtin_header },
     117             : 
     118             :     { ngx_string("Via"),
     119             :                  offsetof(ngx_http_headers_in_t, via),
     120             :                  ngx_http_set_builtin_header },
     121             : #endif
     122             : 
     123             :     { ngx_string("Authorization"),
     124             :                  offsetof(ngx_http_headers_in_t, authorization),
     125             :                  ngx_http_set_builtin_header },
     126             : 
     127             :     { ngx_string("Keep-Alive"),
     128             :                  offsetof(ngx_http_headers_in_t, keep_alive),
     129             :                  ngx_http_set_builtin_header },
     130             : 
     131             : #if (NGX_HTTP_X_FORWARDED_FOR)
     132             :     { ngx_string("X-Forwarded-For"),
     133             :                  offsetof(ngx_http_headers_in_t, x_forwarded_for),
     134             :                  ngx_http_set_builtin_multi_header },
     135             : 
     136             : #endif
     137             : 
     138             : #if (NGX_HTTP_REALIP)
     139             :     { ngx_string("X-Real-IP"),
     140             :                  offsetof(ngx_http_headers_in_t, x_real_ip),
     141             :                  ngx_http_set_builtin_header },
     142             : #endif
     143             : 
     144             : #if (NGX_HTTP_DAV)
     145             :     { ngx_string("Depth"),
     146             :                  offsetof(ngx_http_headers_in_t, depth),
     147             :                  ngx_http_set_builtin_header },
     148             : 
     149             :     { ngx_string("Destination"),
     150             :                  offsetof(ngx_http_headers_in_t, destination),
     151             :                  ngx_http_set_builtin_header },
     152             : 
     153             :     { ngx_string("Overwrite"),
     154             :                  offsetof(ngx_http_headers_in_t, overwrite),
     155             :                  ngx_http_set_builtin_header },
     156             : 
     157             :     { ngx_string("Date"), offsetof(ngx_http_headers_in_t, date),
     158             :                  ngx_http_set_builtin_header },
     159             : #endif
     160             : 
     161             :     { ngx_string("Cookie"),
     162             :                  offsetof(ngx_http_headers_in_t, cookies),
     163             :                  ngx_http_set_builtin_multi_header },
     164             : 
     165             :     { ngx_null_string, 0, ngx_http_set_header }
     166             : };
     167             : 
     168             : 
     169             : /* request time implementation */
     170             : 
     171             : static ngx_int_t
     172           0 : ngx_http_set_header(ngx_http_request_t *r, ngx_http_lua_header_val_t *hv,
     173             :     ngx_str_t *value)
     174             : {
     175           0 :     return ngx_http_set_header_helper(r, hv, value, NULL);
     176             : }
     177             : 
     178             : 
     179             : static ngx_int_t
     180           0 : ngx_http_set_header_helper(ngx_http_request_t *r, ngx_http_lua_header_val_t *hv,
     181             :     ngx_str_t *value, ngx_table_elt_t **output_header)
     182             : {
     183             :     ngx_table_elt_t             *h, *matched;
     184             :     ngx_list_part_t             *part;
     185             :     ngx_uint_t                   i;
     186             :     ngx_uint_t                   rc;
     187             : 
     188           0 :     if (hv->no_override) {
     189           0 :         goto new_header;
     190             :     }
     191             : 
     192           0 :     matched = NULL;
     193             : 
     194           0 : retry:
     195             : 
     196           0 :     part = &r->headers_in.headers.part;
     197           0 :     h = part->elts;
     198             : 
     199           0 :     for (i = 0; /* void */; i++) {
     200           0 :         if (i >= part->nelts) {
     201           0 :             if (part->next == NULL) {
     202           0 :                 break;
     203             :             }
     204             : 
     205           0 :             part = part->next;
     206           0 :             h = part->elts;
     207           0 :             i = 0;
     208             :         }
     209             : 
     210             :         dd("i: %d, part: %p", (int) i, part);
     211             : 
     212           0 :         if (h[i].key.len == hv->key.len
     213           0 :             && ngx_strncasecmp(h[i].key.data, hv->key.data, h[i].key.len)
     214             :                == 0)
     215             :         {
     216           0 :             if (value->len == 0 || (matched && matched != &h[i])) {
     217           0 :                 h[i].hash = 0;
     218             : 
     219             :                 dd("rm header %.*s: %.*s", (int) h[i].key.len, h[i].key.data,
     220             :                    (int) h[i].value.len, h[i].value.data);
     221             : 
     222           0 :                 rc = ngx_http_lua_rm_header_helper(&r->headers_in.headers,
     223             :                                                    part, i);
     224             : 
     225           0 :                 ngx_http_lua_assert(!(r->headers_in.headers.part.next == NULL
     226             :                                       && r->headers_in.headers.last
     227             :                                          != &r->headers_in.headers.part));
     228             : 
     229             :                 dd("rm header: rc=%d", (int) rc);
     230             : 
     231           0 :                 if (rc == NGX_OK) {
     232             : 
     233           0 :                     if (output_header) {
     234           0 :                         *output_header = NULL;
     235             :                     }
     236             : 
     237           0 :                     goto retry;
     238             :                 }
     239             : 
     240           0 :                 return NGX_ERROR;
     241             :             }
     242             : 
     243           0 :             h[i].value = *value;
     244             : 
     245           0 :             if (output_header) {
     246           0 :                 *output_header = &h[i];
     247             :                 dd("setting existing builtin input header");
     248             :             }
     249             : 
     250           0 :             if (matched == NULL) {
     251           0 :                 matched = &h[i];
     252             :             }
     253             :         }
     254             :     }
     255             : 
     256           0 :     if (matched){
     257           0 :         return NGX_OK;
     258             :     }
     259             : 
     260           0 :     if (value->len == 0) {
     261           0 :         return NGX_OK;
     262             :     }
     263             : 
     264           0 : new_header:
     265             : 
     266           0 :     h = ngx_list_push(&r->headers_in.headers);
     267             : 
     268           0 :     if (h == NULL) {
     269           0 :         return NGX_ERROR;
     270             :     }
     271             : 
     272             :     dd("created new header for %.*s", (int) hv->key.len, hv->key.data);
     273             : 
     274           0 :     if (value->len == 0) {
     275           0 :         h->hash = 0;
     276             : 
     277             :     } else {
     278           0 :         h->hash = hv->hash;
     279             :     }
     280             : 
     281           0 :     h->key = hv->key;
     282           0 :     h->value = *value;
     283             : 
     284           0 :     h->lowcase_key = ngx_pnalloc(r->pool, h->key.len);
     285           0 :     if (h->lowcase_key == NULL) {
     286           0 :         return NGX_ERROR;
     287             :     }
     288             : 
     289           0 :     ngx_strlow(h->lowcase_key, h->key.data, h->key.len);
     290             : 
     291           0 :     if (output_header) {
     292           0 :         *output_header = h;
     293             :     }
     294             : 
     295           0 :     return NGX_OK;
     296             : }
     297             : 
     298             : 
     299             : static ngx_int_t
     300           0 : ngx_http_set_builtin_header(ngx_http_request_t *r,
     301             :     ngx_http_lua_header_val_t *hv, ngx_str_t *value)
     302             : {
     303             :     ngx_table_elt_t             *h, **old;
     304             : 
     305             :     dd("entered set_builtin_header (input)");
     306             : 
     307           0 :     if (hv->offset) {
     308           0 :         old = (ngx_table_elt_t **) ((char *) &r->headers_in + hv->offset);
     309             : 
     310             :     } else {
     311           0 :         old = NULL;
     312             :     }
     313             : 
     314             :     dd("old builtin ptr ptr: %p", old);
     315             :     if (old) {
     316             :         dd("old builtin ptr: %p", *old);
     317             :     }
     318             : 
     319           0 :     if (old == NULL || *old == NULL) {
     320             :         dd("set normal header");
     321           0 :         return ngx_http_set_header_helper(r, hv, value, old);
     322             :     }
     323             : 
     324           0 :     h = *old;
     325             : 
     326           0 :     if (value->len == 0) {
     327           0 :         h->hash = 0;
     328           0 :         h->value = *value;
     329             : 
     330           0 :         return ngx_http_set_header_helper(r, hv, value, old);
     331             :     }
     332             : 
     333           0 :     h->hash = hv->hash;
     334           0 :     h->value = *value;
     335             : 
     336           0 :     return NGX_OK;
     337             : }
     338             : 
     339             : 
     340             : static ngx_int_t
     341           0 : ngx_http_lua_validate_host(ngx_str_t *host, ngx_pool_t *pool, ngx_uint_t alloc)
     342             : {
     343             :     u_char  *h, ch;
     344             :     size_t   i, dot_pos, host_len;
     345             : 
     346             :     enum {
     347             :         sw_usual = 0,
     348             :         sw_literal,
     349             :         sw_rest
     350             :     } state;
     351             : 
     352           0 :     dot_pos = host->len;
     353           0 :     host_len = host->len;
     354             : 
     355           0 :     h = host->data;
     356             : 
     357           0 :     state = sw_usual;
     358             : 
     359           0 :     for (i = 0; i < host->len; i++) {
     360           0 :         ch = h[i];
     361             : 
     362           0 :         switch (ch) {
     363             : 
     364           0 :         case '.':
     365           0 :             if (dot_pos == i - 1) {
     366           0 :                 return NGX_DECLINED;
     367             :             }
     368           0 :             dot_pos = i;
     369           0 :             break;
     370             : 
     371           0 :         case ':':
     372           0 :             if (state == sw_usual) {
     373           0 :                 host_len = i;
     374           0 :                 state = sw_rest;
     375             :             }
     376           0 :             break;
     377             : 
     378           0 :         case '[':
     379           0 :             if (i == 0) {
     380           0 :                 state = sw_literal;
     381             :             }
     382           0 :             break;
     383             : 
     384           0 :         case ']':
     385           0 :             if (state == sw_literal) {
     386           0 :                 host_len = i + 1;
     387           0 :                 state = sw_rest;
     388             :             }
     389           0 :             break;
     390             : 
     391           0 :         case '\0':
     392           0 :             return NGX_DECLINED;
     393             : 
     394           0 :         default:
     395             : 
     396           0 :             if (ngx_path_separator(ch)) {
     397           0 :                 return NGX_DECLINED;
     398             :             }
     399             : 
     400           0 :             if (ch >= 'A' && ch <= 'Z') {
     401           0 :                 alloc = 1;
     402             :             }
     403             : 
     404           0 :             break;
     405             :         }
     406             :     }
     407             : 
     408           0 :     if (dot_pos == host_len - 1) {
     409           0 :         host_len--;
     410             :     }
     411             : 
     412           0 :     if (host_len == 0) {
     413           0 :         return NGX_DECLINED;
     414             :     }
     415             : 
     416           0 :     if (alloc) {
     417           0 :         host->data = ngx_pnalloc(pool, host_len);
     418           0 :         if (host->data == NULL) {
     419           0 :             return NGX_ERROR;
     420             :         }
     421             : 
     422           0 :         ngx_strlow(host->data, h, host_len);
     423             :     }
     424             : 
     425           0 :     host->len = host_len;
     426             : 
     427           0 :     return NGX_OK;
     428             : }
     429             : 
     430             : 
     431             : static ngx_int_t
     432           0 : ngx_http_set_host_header(ngx_http_request_t *r, ngx_http_lua_header_val_t *hv,
     433             :     ngx_str_t *value)
     434             : {
     435             :     ngx_str_t host;
     436             : 
     437             :     dd("server new value len: %d", (int) value->len);
     438             : 
     439           0 :     if (value->len) {
     440           0 :         host= *value;
     441             : 
     442           0 :         if (ngx_http_lua_validate_host(&host, r->pool, 0) != NGX_OK) {
     443           0 :             return NGX_ERROR;
     444             :         }
     445             : 
     446           0 :         r->headers_in.server = host;
     447             : 
     448             :     } else {
     449           0 :         r->headers_in.server = *value;
     450             :     }
     451             : 
     452           0 :     return ngx_http_set_builtin_header(r, hv, value);
     453             : }
     454             : 
     455             : 
     456             : static ngx_int_t
     457           0 : ngx_http_set_connection_header(ngx_http_request_t *r,
     458             :     ngx_http_lua_header_val_t *hv, ngx_str_t *value)
     459             : {
     460           0 :     r->headers_in.connection_type = 0;
     461             : 
     462           0 :     if (value->len == 0) {
     463           0 :         return ngx_http_set_builtin_header(r, hv, value);
     464             :     }
     465             : 
     466           0 :     if (ngx_strcasestrn(value->data, "close", 5 - 1)) {
     467           0 :         r->headers_in.connection_type = NGX_HTTP_CONNECTION_CLOSE;
     468           0 :         r->headers_in.keep_alive_n = -1;
     469             : 
     470           0 :     } else if (ngx_strcasestrn(value->data, "keep-alive", 10 - 1)) {
     471           0 :         r->headers_in.connection_type = NGX_HTTP_CONNECTION_KEEP_ALIVE;
     472             :     }
     473             : 
     474           0 :     return ngx_http_set_builtin_header(r, hv, value);
     475             : }
     476             : 
     477             : 
     478             : /* borrowed the code from ngx_http_request.c:ngx_http_process_user_agent */
     479             : static ngx_int_t
     480           0 : ngx_http_set_user_agent_header(ngx_http_request_t *r,
     481             :     ngx_http_lua_header_val_t *hv, ngx_str_t *value)
     482             : {
     483             :     u_char  *user_agent, *msie;
     484             : 
     485             :     /* clear existing settings */
     486             : 
     487           0 :     r->headers_in.msie = 0;
     488           0 :     r->headers_in.msie6 = 0;
     489           0 :     r->headers_in.opera = 0;
     490           0 :     r->headers_in.gecko = 0;
     491           0 :     r->headers_in.chrome = 0;
     492           0 :     r->headers_in.safari = 0;
     493           0 :     r->headers_in.konqueror = 0;
     494             : 
     495           0 :     if (value->len == 0) {
     496           0 :         return ngx_http_set_builtin_header(r, hv, value);
     497             :     }
     498             : 
     499             :     /* check some widespread browsers */
     500             : 
     501           0 :     user_agent = value->data;
     502             : 
     503           0 :     msie = ngx_strstrn(user_agent, "MSIE ", 5 - 1);
     504             : 
     505           0 :     if (msie && msie + 7 < user_agent + value->len) {
     506             : 
     507           0 :         r->headers_in.msie = 1;
     508             : 
     509           0 :         if (msie[6] == '.') {
     510             : 
     511           0 :             switch (msie[5]) {
     512           0 :             case '4':
     513             :             case '5':
     514           0 :                 r->headers_in.msie6 = 1;
     515           0 :                 break;
     516           0 :             case '6':
     517           0 :                 if (ngx_strstrn(msie + 8, "SV1", 3 - 1) == NULL) {
     518           0 :                     r->headers_in.msie6 = 1;
     519             :                 }
     520           0 :                 break;
     521             :             }
     522             :         }
     523             :     }
     524             : 
     525           0 :     if (ngx_strstrn(user_agent, "Opera", 5 - 1)) {
     526           0 :         r->headers_in.opera = 1;
     527           0 :         r->headers_in.msie = 0;
     528           0 :         r->headers_in.msie6 = 0;
     529             :     }
     530             : 
     531           0 :     if (!r->headers_in.msie && !r->headers_in.opera) {
     532             : 
     533           0 :         if (ngx_strstrn(user_agent, "Gecko/", 6 - 1)) {
     534           0 :             r->headers_in.gecko = 1;
     535             : 
     536           0 :         } else if (ngx_strstrn(user_agent, "Chrome/", 7 - 1)) {
     537           0 :             r->headers_in.chrome = 1;
     538             : 
     539           0 :         } else if (ngx_strstrn(user_agent, "Safari/", 7 - 1)
     540           0 :                    && ngx_strstrn(user_agent, "Mac OS X", 8 - 1))
     541             :         {
     542           0 :             r->headers_in.safari = 1;
     543             : 
     544           0 :         } else if (ngx_strstrn(user_agent, "Konqueror", 9 - 1)) {
     545           0 :             r->headers_in.konqueror = 1;
     546             :         }
     547             :     }
     548             : 
     549           0 :     return ngx_http_set_builtin_header(r, hv, value);
     550             : }
     551             : 
     552             : 
     553             : static ngx_int_t
     554           0 : ngx_http_set_content_length_header(ngx_http_request_t *r,
     555             :     ngx_http_lua_header_val_t *hv, ngx_str_t *value)
     556             : {
     557             :     off_t           len;
     558             : 
     559           0 :     if (value->len == 0) {
     560           0 :         return ngx_http_clear_content_length_header(r, hv, value);
     561             :     }
     562             : 
     563           0 :     len = ngx_atosz(value->data, value->len);
     564           0 :     if (len == NGX_ERROR) {
     565           0 :         return NGX_ERROR;
     566             :     }
     567             : 
     568             :     dd("reset headers_in.content_length_n to %d", (int) len);
     569             : 
     570           0 :     r->headers_in.content_length_n = len;
     571             : 
     572           0 :     return ngx_http_set_builtin_header(r, hv, value);
     573             : }
     574             : 
     575             : 
     576             : static ngx_int_t
     577           0 : ngx_http_set_builtin_multi_header(ngx_http_request_t *r,
     578             :     ngx_http_lua_header_val_t *hv, ngx_str_t *value)
     579             : {
     580             :     ngx_array_t       *headers;
     581             :     ngx_table_elt_t  **v, *h;
     582             : 
     583           0 :     headers = (ngx_array_t *) ((char *) &r->headers_in + hv->offset);
     584             : 
     585           0 :     if (!hv->no_override && headers->nelts > 0) {
     586           0 :         ngx_array_destroy(headers);
     587             : 
     588           0 :         if (ngx_array_init(headers, r->pool, 2,
     589             :                            sizeof(ngx_table_elt_t *))
     590             :             != NGX_OK)
     591             :         {
     592           0 :             return NGX_ERROR;
     593             :         }
     594             : 
     595             :         dd("clear multi-value headers: %d", (int) headers->nelts);
     596             :     }
     597             : 
     598             : #if 1
     599           0 :     if (headers->nalloc == 0) {
     600           0 :         if (ngx_array_init(headers, r->pool, 2,
     601             :                            sizeof(ngx_table_elt_t *))
     602             :             != NGX_OK)
     603             :         {
     604           0 :             return NGX_ERROR;
     605             :         }
     606             :     }
     607             : #endif
     608             : 
     609           0 :     if (ngx_http_set_header_helper(r, hv, value, &h) == NGX_ERROR) {
     610           0 :         return NGX_ERROR;
     611             :     }
     612             : 
     613           0 :     if (value->len == 0) {
     614           0 :         return NGX_OK;
     615             :     }
     616             : 
     617             :     dd("new multi-value header: %p", h);
     618             : 
     619           0 :     v = ngx_array_push(headers);
     620           0 :     if (v == NULL) {
     621           0 :         return NGX_ERROR;
     622             :     }
     623             : 
     624           0 :     *v = h;
     625           0 :     return NGX_OK;
     626             : }
     627             : 
     628             : 
     629             : static ngx_int_t
     630           0 : ngx_http_clear_content_length_header(ngx_http_request_t *r,
     631             :     ngx_http_lua_header_val_t *hv, ngx_str_t *value)
     632             : {
     633           0 :     r->headers_in.content_length_n = -1;
     634             : 
     635           0 :     return ngx_http_clear_builtin_header(r, hv, value);
     636             : }
     637             : 
     638             : 
     639             : static ngx_int_t
     640           0 : ngx_http_clear_builtin_header(ngx_http_request_t *r,
     641             :     ngx_http_lua_header_val_t *hv, ngx_str_t *value)
     642             : {
     643           0 :     value->len = 0;
     644           0 :     return ngx_http_set_builtin_header(r, hv, value);
     645             : }
     646             : 
     647             : 
     648             : ngx_int_t
     649           0 : ngx_http_lua_set_input_header(ngx_http_request_t *r, ngx_str_t key,
     650             :     ngx_str_t value, unsigned override)
     651             : {
     652             :     ngx_http_lua_header_val_t         hv;
     653           0 :     ngx_http_lua_set_header_t        *handlers = ngx_http_lua_set_handlers;
     654             : 
     655             :     ngx_uint_t                        i;
     656             : 
     657             :     dd("set header value: %.*s", (int) value.len, value.data);
     658             : 
     659           0 :     hv.hash = ngx_hash_key_lc(key.data, key.len);
     660           0 :     hv.key = key;
     661             : 
     662           0 :     hv.offset = 0;
     663           0 :     hv.no_override = !override;
     664           0 :     hv.handler = NULL;
     665             : 
     666           0 :     for (i = 0; handlers[i].name.len; i++) {
     667           0 :         if (hv.key.len != handlers[i].name.len
     668           0 :             || ngx_strncasecmp(hv.key.data, handlers[i].name.data,
     669           0 :                                handlers[i].name.len) != 0)
     670             :         {
     671             :             dd("hv key comparison: %s <> %s", handlers[i].name.data,
     672             :                hv.key.data);
     673             : 
     674           0 :             continue;
     675             :         }
     676             : 
     677             :         dd("Matched handler: %s %s", handlers[i].name.data, hv.key.data);
     678             : 
     679           0 :         hv.offset = handlers[i].offset;
     680           0 :         hv.handler = handlers[i].handler;
     681             : 
     682           0 :         break;
     683             :     }
     684             : 
     685           0 :     if (handlers[i].name.len == 0 && handlers[i].handler) {
     686           0 :         hv.offset = handlers[i].offset;
     687           0 :         hv.handler = handlers[i].handler;
     688             :     }
     689             : 
     690             : #if 1
     691           0 :     if (hv.handler == NULL) {
     692           0 :         return NGX_ERROR;
     693             :     }
     694             : #endif
     695             : 
     696           0 :     if (r->headers_out.status == 400 || r->headers_in.headers.last == NULL) {
     697             :         /* must be a 400 Bad Request */
     698           0 :         return NGX_OK;
     699             :     }
     700             : 
     701           0 :     return hv.handler(r, &hv, &value);
     702             : }
     703             : 
     704             : 
     705             : static ngx_int_t
     706           0 : ngx_http_lua_rm_header_helper(ngx_list_t *l, ngx_list_part_t *cur,
     707             :     ngx_uint_t i)
     708             : {
     709             :     ngx_table_elt_t             *data;
     710             :     ngx_list_part_t             *new, *part;
     711             : 
     712             :     dd("list rm item: part %p, i %d, nalloc %d", cur, (int) i,
     713             :        (int) l->nalloc);
     714             : 
     715           0 :     data = cur->elts;
     716             : 
     717             :     dd("cur: nelts %d, nalloc %d", (int) cur->nelts,
     718             :        (int) l->nalloc);
     719             : 
     720             :     dd("removing: \"%.*s:%.*s\"", (int) data[i].key.len, data[i].key.data,
     721             :        (int) data[i].value.len, data[i].value.data);
     722             : 
     723           0 :     if (i == 0) {
     724             :         dd("first entry in the part");
     725           0 :         cur->elts = (char *) cur->elts + l->size;
     726           0 :         cur->nelts--;
     727             : 
     728           0 :         if (cur == l->last) {
     729             :             dd("being the last part");
     730           0 :             if (cur->nelts == 0) {
     731             : #if 1
     732           0 :                 part = &l->part;
     733             :                 dd("cur=%p, part=%p, part next=%p, last=%p",
     734             :                    cur, part, part->next, l->last);
     735             : 
     736           0 :                 if (part == cur) {
     737           0 :                     cur->elts = (char *) cur->elts - l->size;
     738             :                     /* do nothing */
     739             : 
     740             :                 } else {
     741           0 :                     while (part->next != cur) {
     742           0 :                         if (part->next == NULL) {
     743           0 :                             return NGX_ERROR;
     744             :                         }
     745           0 :                         part = part->next;
     746             :                     }
     747             : 
     748           0 :                     l->last = part;
     749           0 :                     part->next = NULL;
     750             :                     dd("part nelts: %d", (int) part->nelts);
     751           0 :                     l->nalloc = part->nelts;
     752             :                 }
     753             : #endif
     754             : 
     755             :             } else {
     756           0 :                 l->nalloc--;
     757             :                 dd("nalloc decreased: %d", (int) l->nalloc);
     758             :             }
     759             : 
     760           0 :             return NGX_OK;
     761             :         }
     762             : 
     763           0 :         if (cur->nelts == 0) {
     764             :             dd("current part is empty");
     765           0 :             part = &l->part;
     766           0 :             if (part == cur) {
     767           0 :                 ngx_http_lua_assert(cur->next != NULL);
     768             : 
     769             :                 dd("remove 'cur' from the list by rewriting 'cur': "
     770             :                    "l->last: %p, cur: %p, cur->next: %p, part: %p",
     771             :                    l->last, cur, cur->next, part);
     772             : 
     773           0 :                 if (l->last == cur->next) {
     774             :                     dd("last is cur->next");
     775           0 :                     l->part = *(cur->next);
     776           0 :                     l->last = part;
     777           0 :                     l->nalloc = part->nelts;
     778             : 
     779             :                 } else {
     780           0 :                     l->part = *(cur->next);
     781             :                 }
     782             : 
     783             :             } else {
     784             :                 dd("remove 'cur' from the list");
     785           0 :                 while (part->next != cur) {
     786           0 :                     if (part->next == NULL) {
     787           0 :                         return NGX_ERROR;
     788             :                     }
     789           0 :                     part = part->next;
     790             :                 }
     791             : 
     792           0 :                 part->next = cur->next;
     793             :             }
     794             : 
     795           0 :             return NGX_OK;
     796             :         }
     797             : 
     798           0 :         return NGX_OK;
     799             :     }
     800             : 
     801           0 :     if (i == cur->nelts - 1) {
     802             :         dd("last entry in the part");
     803             : 
     804           0 :         cur->nelts--;
     805             : 
     806           0 :         if (cur == l->last) {
     807           0 :             l->nalloc--;
     808             :         }
     809             : 
     810           0 :         return NGX_OK;
     811             :     }
     812             : 
     813             :     dd("the middle entry in the part");
     814             : 
     815           0 :     new = ngx_palloc(l->pool, sizeof(ngx_list_part_t));
     816           0 :     if (new == NULL) {
     817           0 :         return NGX_ERROR;
     818             :     }
     819             : 
     820           0 :     new->elts = &data[i + 1];
     821           0 :     new->nelts = cur->nelts - i - 1;
     822           0 :     new->next = cur->next;
     823             : 
     824           0 :     cur->nelts = i;
     825           0 :     cur->next = new;
     826             : 
     827           0 :     if (cur == l->last) {
     828           0 :         l->last = new;
     829           0 :         l->nalloc = new->nelts;
     830             :     }
     831             : 
     832           0 :     return NGX_OK;
     833             : }
     834             : 
     835             : /* vi:set ft=c ts=4 sw=4 et fdm=marker: */

Generated by: LCOV version 1.13