[PATCH 06 of 20] Reworked multi headers to use linked lists

Maxim Dounin mdounin at mdounin.ru
Thu May 12 23:42:20 UTC 2022


Hello!

On Wed, May 11, 2022 at 11:21:15PM +0400, Sergey Kandaurov wrote:

> On Thu, Apr 21, 2022 at 01:18:46AM +0300, Maxim Dounin wrote:
> > # HG changeset patch
> > # User Maxim Dounin <mdounin at mdounin.ru>
> > # Date 1650492323 -10800
> > #      Thu Apr 21 01:05:23 2022 +0300
> > # Node ID 50fe52f516ff9c148aa9e7dfcc1c31cc6a4929ae
> > # Parent  2ea48b5e4643a818cd81179f040f0b36be9050d6
> > Reworked multi headers to use linked lists.
> > 
> > Multi headers are now using linked lists instead of arrays.  Notably,
> > the following fields were changed: r->headers_in.cookies (renamed
> > to r->headers_in.cookie), r->headers_in.x_forwarded_for,
> > r->headers_out.cache_control, r->headers_out.link, u->headers_in.cache_control
> > u->headers_in.cookies (renamed to u->headers_in.set_cookie).
> 
> jftr, this implies updating a bunch of 3rd party modules, including njs, lua,
> naxsi, nginx-clojure, headers-more, geoip2_module, ngx_http_sticky_module

Sure.

> > 
> > The r->headers_in.cookies and u->headers_in.cookies fields were renamed
> > to r->headers_in.cookie and u->headers_in.set_cookie to match header names.
> > 
> > The ngx_http_parse_multi_header_lines() and ngx_http_parse_set_cookie_lines()
> > functions were changed accordingly.
> > 
> > With this change, multi headers are now essentially equivalent to normal
> > headers, and following changes will further make them equivalent.
> > 
> > diff --git a/src/http/modules/ngx_http_geo_module.c b/src/http/modules/ngx_http_geo_module.c
> > --- a/src/http/modules/ngx_http_geo_module.c
> > +++ b/src/http/modules/ngx_http_geo_module.c
> > @@ -327,15 +327,15 @@ static ngx_int_t
> >  ngx_http_geo_addr(ngx_http_request_t *r, ngx_http_geo_ctx_t *ctx,
> >      ngx_addr_t *addr)
> >  {
> > -    ngx_array_t  *xfwd;
> > +    ngx_table_elt_t  *xfwd;
> >  
> >      if (ngx_http_geo_real_addr(r, ctx, addr) != NGX_OK) {
> >          return NGX_ERROR;
> >      }
> >  
> > -    xfwd = &r->headers_in.x_forwarded_for;
> > +    xfwd = r->headers_in.x_forwarded_for;
> >  
> > -    if (xfwd->nelts > 0 && ctx->proxies != NULL) {
> > +    if (xfwd != NULL && ctx->proxies != NULL) {
> >          (void) ngx_http_get_forwarded_addr(r, addr, xfwd, NULL,
> >                                             ctx->proxies, ctx->proxy_recursive);
> >      }
> > diff --git a/src/http/modules/ngx_http_geoip_module.c b/src/http/modules/ngx_http_geoip_module.c
> > --- a/src/http/modules/ngx_http_geoip_module.c
> > +++ b/src/http/modules/ngx_http_geoip_module.c
> > @@ -240,16 +240,16 @@ static u_long
> >  ngx_http_geoip_addr(ngx_http_request_t *r, ngx_http_geoip_conf_t *gcf)
> >  {
> >      ngx_addr_t           addr;
> > -    ngx_array_t         *xfwd;
> > +    ngx_table_elt_t     *xfwd;
> >      struct sockaddr_in  *sin;
> >  
> >      addr.sockaddr = r->connection->sockaddr;
> >      addr.socklen = r->connection->socklen;
> >      /* addr.name = r->connection->addr_text; */
> >  
> > -    xfwd = &r->headers_in.x_forwarded_for;
> > +    xfwd = r->headers_in.x_forwarded_for;
> >  
> > -    if (xfwd->nelts > 0 && gcf->proxies != NULL) {
> > +    if (xfwd != NULL && gcf->proxies != NULL) {
> >          (void) ngx_http_get_forwarded_addr(r, &addr, xfwd, NULL,
> >                                             gcf->proxies, gcf->proxy_recursive);
> >      }
> > @@ -292,7 +292,7 @@ static geoipv6_t
> >  ngx_http_geoip_addr_v6(ngx_http_request_t *r, ngx_http_geoip_conf_t *gcf)
> >  {
> >      ngx_addr_t            addr;
> > -    ngx_array_t          *xfwd;
> > +    ngx_table_elt_t      *xfwd;
> >      in_addr_t             addr4;
> >      struct in6_addr       addr6;
> >      struct sockaddr_in   *sin;
> > @@ -302,9 +302,9 @@ ngx_http_geoip_addr_v6(ngx_http_request_
> >      addr.socklen = r->connection->socklen;
> >      /* addr.name = r->connection->addr_text; */
> >  
> > -    xfwd = &r->headers_in.x_forwarded_for;
> > +    xfwd = r->headers_in.x_forwarded_for;
> >  
> > -    if (xfwd->nelts > 0 && gcf->proxies != NULL) {
> > +    if (xfwd != NULL && gcf->proxies != NULL) {
> >          (void) ngx_http_get_forwarded_addr(r, &addr, xfwd, NULL,
> >                                             gcf->proxies, gcf->proxy_recursive);
> >      }
> > diff --git a/src/http/modules/ngx_http_headers_filter_module.c b/src/http/modules/ngx_http_headers_filter_module.c
> > --- a/src/http/modules/ngx_http_headers_filter_module.c
> > +++ b/src/http/modules/ngx_http_headers_filter_module.c
> > @@ -329,8 +329,7 @@ ngx_http_set_expires(ngx_http_request_t 
> >      time_t               now, expires_time, max_age;
> >      ngx_str_t            value;
> >      ngx_int_t            rc;
> > -    ngx_uint_t           i;
> > -    ngx_table_elt_t     *e, *cc, **ccp;
> > +    ngx_table_elt_t     *e, *cc;
> >      ngx_http_expires_t   expires;
> >  
> >      expires = conf->expires;
> > @@ -371,38 +370,28 @@ ngx_http_set_expires(ngx_http_request_t 
> >      len = sizeof("Mon, 28 Sep 1970 06:00:00 GMT");
> >      e->value.len = len - 1;
> >  
> > -    ccp = r->headers_out.cache_control.elts;
> > -
> > -    if (ccp == NULL) {
> > +    cc = r->headers_out.cache_control;
> >  
> > -        if (ngx_array_init(&r->headers_out.cache_control, r->pool,
> > -                           1, sizeof(ngx_table_elt_t *))
> > -            != NGX_OK)
> > -        {
> > -            return NGX_ERROR;
> > -        }
> > +    if (cc == NULL) {
> >  
> >          cc = ngx_list_push(&r->headers_out.headers);
> >          if (cc == NULL) {
> >              return NGX_ERROR;
> >          }
> >  
> > +        r->headers_out.cache_control = cc;
> > +        cc->next = NULL;
> > +
> >          cc->hash = 1;
> >          ngx_str_set(&cc->key, "Cache-Control");
> >  
> > -        ccp = ngx_array_push(&r->headers_out.cache_control);
> > -        if (ccp == NULL) {
> > -            return NGX_ERROR;
> > +    } else {
> > +        for (cc = cc->next; cc; cc = cc->next) {
> > +            cc->hash = 0;
> >          }
> >  
> > -        *ccp = cc;
> > -
> > -    } else {
> > -        for (i = 1; i < r->headers_out.cache_control.nelts; i++) {
> > -            ccp[i]->hash = 0;
> > -        }
> > -
> > -        cc = ccp[0];
> > +        cc = r->headers_out.cache_control;
> > +        cc->next = NULL;
> >      }
> >  
> >      if (expires == NGX_HTTP_EXPIRES_EPOCH) {
> > @@ -564,22 +553,12 @@ static ngx_int_t
> >  ngx_http_add_multi_header_lines(ngx_http_request_t *r,
> >      ngx_http_header_val_t *hv, ngx_str_t *value)
> >  {
> > -    ngx_array_t      *pa;
> >      ngx_table_elt_t  *h, **ph;
> >  
> >      if (value->len == 0) {
> >          return NGX_OK;
> >      }
> >  
> > -    pa = (ngx_array_t *) ((char *) &r->headers_out + hv->offset);
> > -
> > -    if (pa->elts == NULL) {
> > -        if (ngx_array_init(pa, r->pool, 1, sizeof(ngx_table_elt_t *)) != NGX_OK)
> > -        {
> > -            return NGX_ERROR;
> > -        }
> > -    }
> > -
> >      h = ngx_list_push(&r->headers_out.headers);
> >      if (h == NULL) {
> >          return NGX_ERROR;
> > @@ -589,12 +568,12 @@ ngx_http_add_multi_header_lines(ngx_http
> >      h->key = hv->key;
> >      h->value = *value;
> >  
> > -    ph = ngx_array_push(pa);
> > -    if (ph == NULL) {
> > -        return NGX_ERROR;
> > -    }
> > +    ph = (ngx_table_elt_t **) ((char *) &r->headers_out + hv->offset);
> > +
> > +    while (*ph) { ph = &(*ph)->next; }
> >  
> >      *ph = h;
> > +    h->next = NULL;
> >  
> >      return NGX_OK;
> >  }
> > diff --git a/src/http/modules/ngx_http_proxy_module.c b/src/http/modules/ngx_http_proxy_module.c
> > --- a/src/http/modules/ngx_http_proxy_module.c
> > +++ b/src/http/modules/ngx_http_proxy_module.c
> > @@ -2559,22 +2559,20 @@ static ngx_int_t
> >  ngx_http_proxy_add_x_forwarded_for_variable(ngx_http_request_t *r,
> >      ngx_http_variable_value_t *v, uintptr_t data)
> >  {
> > -    size_t             len;
> > -    u_char            *p;
> > -    ngx_uint_t         i, n;
> > -    ngx_table_elt_t  **h;
> > +    size_t            len;
> > +    u_char           *p;
> > +    ngx_table_elt_t  *h, *xfwd;
> >  
> >      v->valid = 1;
> >      v->no_cacheable = 0;
> >      v->not_found = 0;
> >  
> > -    n = r->headers_in.x_forwarded_for.nelts;
> > -    h = r->headers_in.x_forwarded_for.elts;
> > +    xfwd = r->headers_in.x_forwarded_for;
> >  
> >      len = 0;
> >  
> > -    for (i = 0; i < n; i++) {
> > -        len += h[i]->value.len + sizeof(", ") - 1;
> > +    for (h = xfwd; h; h = h->next) {
> > +        len += h->value.len + sizeof(", ") - 1;
> >      }
> >  
> >      if (len == 0) {
> 
> The only minor point in a whole patch (which I won't insist):
> a special case for xfwd absense can be slightly reshuffled now
> to avoid a do-nothing loop.
> 
> diff --git a/src/http/modules/ngx_http_proxy_module.c b/src/http/modules/ngx_http_proxy_module.c
> --- a/src/http/modules/ngx_http_proxy_module.c
> +++ b/src/http/modules/ngx_http_proxy_module.c
> @@ -2569,18 +2569,18 @@ ngx_http_proxy_add_x_forwarded_for_varia
>  
>      xfwd = r->headers_in.x_forwarded_for;
>  
> +    if (xfwd == NULL) {
> +        v->len = r->connection->addr_text.len;
> +        v->data = r->connection->addr_text.data;
> +        return NGX_OK;
> +    }
> +
>      len = 0;
>  
>      for (h = xfwd; h; h = h->next) {
>          len += h->value.len + sizeof(", ") - 1;
>      }
>  
> -    if (len == 0) {
> -        v->len = r->connection->addr_text.len;
> -        v->data = r->connection->addr_text.data;
> -        return NGX_OK;
> -    }
> -
>      len += r->connection->addr_text.len;
>  
>      p = ngx_pnalloc(r->pool, len);
> 
> Otherwise, looks good.

Such an optimization (if at all) is completely orthogonal and 
available regardless of the r->headers_in.x_forwarded_for format 
(that is, nothing stops you from testing "n == 0" in the original 
code).

Either way, I don't think such a change belongs to this patch 
and/or this patch series.

-- 
Maxim Dounin
http://mdounin.ru/



More information about the nginx-devel mailing list