# Add new cookie into headers\_in

**URL:** <https://www.ruby-forum.com/t/add-new-cookie-into-headers-in/202212>\
**Category:** NGINX\
**Created:** [January 24, 2011, 4:08pm UTC](https://www.ruby-forum.com/t/add-new-cookie-into-headers-in/202212 "2011-01-24T16:08:49Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![dubstep](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/d/cdc98d/32.png) [@dubstep](https://www.ruby-forum.com/u/dubstep)\
**Post date:** [January 24, 2011, 4:08pm UTC](https://www.ruby-forum.com/t/add-new-cookie-into-headers-in/202212/1 "2011-01-24T16:08:49Z")

</div>

Hello,  
I have a filter module in rewrite phase. The module tests if a cookie is  
in the request. If not the module generates one (if cookie is found the  
module modifies it) and then send it back to the client via  
headers\_out.  
But I need one more functionality. I want the generated/modified cookie  
to be sent to the proxy module. I have used the headers\_more\_module for  
this purpose so far and it worked perfectly. I generate an  
$ap\_filter\_cookie\_sid variable in my module that contains the cookie. I  
would like my module to be able to modify headers\_in on its own.  
I have managed to modify existing cookie in the headers\_in.headers. But  
when no cookie is in headers\_in.headers my module is not able to store  
newly generated cookie to headers\_in.headers. It seems OK in my module  
but before running proxy module the Nginx stops processing the request.  
When the first request contains a cookie the Nginx server processes it  
correctly and each next request (also withnou cookie) as well. This  
behaviour is a bit confusing and I have no idea how to fix it.

Can anybody help me?  
Thank you, Michal

Complete code:

typedef u\_char \*(\*ngx\_http\_ap\_filter\_op\_run\_pt) (ngx\_http\_request\_t \*r,  
u\_char \*buf,  
ngx\_http\_ap\_filter\_op\_t \*op);

typedef size\_t (\*ngx\_http\_ap\_filter\_op\_getlen\_pt) (ngx\_http\_request\_t  
\*r, uintptr\_t data);  
#define COOKIE\_EXPIRES\_TIME 2592000

typedef struct {  
ngx\_str\_t cookie\_sid;  
ngx\_str\_t sessionid;  
} ngx\_http\_ap\_filter\_ctx\_t;

typedef struct {  
ngx\_flag\_t enable;  
ngx\_str\_t sessionid;  
} ngx\_http\_ap\_filter\_loc\_conf\_t;

static ngx\_int\_t ngx\_http\_ap\_filter\_add\_variables(ngx\_conf\_t \*cf);  
static ngx\_int\_t  
ngx\_http\_ap\_filter\_cookie\_sid\_variable(ngx\_http\_request\_t \*r,  
ngx\_http\_variable\_value\_t _v, uintptr\_t data);  
static void_ ngx\_http\_ap\_filter\_create\_loc\_conf(ngx\_conf\_t \*cf);  
static ngx\_int\_t ngx\_http\_ap\_filter\_init(ngx\_conf\_t _cf);  
static char_ ngx\_http\_ap\_filter\_merge\_loc\_conf(ngx\_conf\_t \*cf, void  
\*parent, void \*child);  
static ngx\_int\_t ngx\_http\_ap\_filter(ngx\_http\_request\_t \*r,  
ngx\_http\_ap\_filter\_ctx\_t \*ctx);  
static ngx\_int\_t ngx\_http\_ap\_filter\_handler(ngx\_http\_request\_t \*r);

static ngx\_int\_t ngx\_http\_ap\_filter\_get\_cookie(ngx\_http\_request\_t \*r,  
ngx\_str\_t \*cookie\_value);  
static ngx\_int\_t ngx\_http\_ap\_filter\_set\_cookie(ngx\_http\_request\_t _r,  
ngx\_str\_t_ cookie\_value, ngx\_http\_ap\_filter\_ctx\_t \*ctx);

static ngx\_command\_t ngx\_http\_ap\_filter\_commands[] = {  
{ ngx\_string(“ap\_filter”),

NGX\_HTTP\_MAIN\_CONF|NGX\_HTTP\_SRV\_CONF|NGX\_HTTP\_LOC\_CONF|NGX\_HTTP\_LIF\_CONF|NGX\_CONF\_FLAG,  
ngx\_conf\_set\_flag\_slot,  
NGX\_HTTP\_LOC\_CONF\_OFFSET,  
offsetof(ngx\_http\_ap\_filter\_loc\_conf\_t, enable),  
NULL },  
{ ngx\_string(“ap\_filter\_sessionid”),

NGX\_HTTP\_MAIN\_CONF|NGX\_HTTP\_SRV\_CONF|NGX\_HTTP\_LOC\_CONF|NGX\_CONF\_TAKE1,  
ngx\_conf\_set\_str\_slot,  
NGX\_HTTP\_LOC\_CONF\_OFFSET,  
offsetof(ngx\_http\_ap\_filter\_loc\_conf\_t, sessionid),  
NULL },  
ngx\_null\_command  
};

static ngx\_http\_module\_t ngx\_http\_ap\_filter\_module\_ctx = {  
ngx\_http\_ap\_filter\_add\_variables, /\* preconfiguration _/  
ngx\_http\_ap\_filter\_init, /_ postconfiguration _/  
NULL, /_ create main configuration _/  
NULL, /_ init main configuration _/  
NULL, /_ create server configuration _/  
NULL, /_ merge server configuration _/  
ngx\_http\_ap\_filter\_create\_loc\_conf, /_ create location  
configuration _/  
ngx\_http\_ap\_filter\_merge\_loc\_conf /_ merge location configuration  
\*/  
};

ngx\_module\_t ngx\_http\_ap\_filter\_module = {  
NGX\_MODULE\_V1,  
&ngx\_http\_ap\_filter\_module\_ctx,/\* module context _/  
ngx\_http\_ap\_filter\_commands, /_ module directives _/  
NGX\_HTTP\_MODULE, /_ module type _/  
NULL, /_ init master _/  
NULL, /_ init module _/  
NULL, /_ init process _/  
NULL, /_ init thread _/  
NULL, /_ exit thread _/  
NULL, /_ exit process _/  
NULL, /_ exit master \*/  
NGX\_MODULE\_V1\_PADDING  
};

static ngx\_http\_variable\_t ngx\_http\_ap\_filter\_vars[] = {  
// $ap\_mod\_cookie\_sid - modified/generated cookie  
{ ngx\_string(“ap\_filter\_cookie\_sid”), NULL,  
ngx\_http\_ap\_filter\_cookie\_sid\_variable, 0,

NGX\_HTTP\_VAR\_CHANGEABLE|NGX\_HTTP\_VAR\_NOCACHEABLE|NGX\_HTTP\_VAR\_NOHASH, 0  
},

```
{ ngx_null_string, NULL, NULL, 0, 0, 0 }

```

};

static ngx\_int\_t ngx\_http\_ap\_filter\_add\_variables(ngx\_conf\_t \*cf) {  
ngx\_http\_variable\_t \*var, \*v;

```
for (v = ngx_http_ap_filter_vars; v->name.len; v++) {
    var = ngx_http_add_variable(cf, &v->name, v->flags);
    if (var == NULL) {
        return NGX_ERROR;
    }

    var->get_handler = v->get_handler;
    var->data = v->data;
}

return NGX_OK;

```

}

static ngx\_int\_t  
ngx\_http\_ap\_filter\_cookie\_sid\_variable(ngx\_http\_request\_t \*r,  
ngx\_http\_variable\_value\_t \*v, uintptr\_t data) {  
ngx\_http\_ap\_filter\_ctx\_t \*ctx;

```
ctx = reinterpret_cast(ngx_http_get_module_ctx(r,

```

ngx\_http\_ap\_filter\_module));

```
if (ctx == NULL) {
    v->not_found = 1;
    return NGX_OK;
}

v->len = ctx->cookie_sid.len;
v->valid = 1;
v->no_cacheable = 0;
v->not_found = 0;
v->data = ctx->cookie_sid.data;

return NGX_OK;

```

}

static void \*ngx\_http\_ap\_filter\_create\_loc\_conf(ngx\_conf\_t \*cf) {  
ngx\_http\_ap\_filter\_loc\_conf\_t \*conf;

```
conf = reinterpret_cast(ngx_pcalloc(cf->pool,

```

sizeof(ngx\_http\_ap\_filter\_loc\_conf\_t)));  
if (conf == NULL) {  
return NGX\_CONF\_ERROR;  
}  
conf-\>enable = NGX\_CONF\_UNSET\_UINT;  
return conf;  
}

static char \*ngx\_http\_ap\_filter\_merge\_loc\_conf(ngx\_conf\_t \*cf, void  
\*parent, void \*child) {  
ngx\_http\_ap\_filter\_loc\_conf\_t \*prev = reinterpret\_cast(parent);  
ngx\_http\_ap\_filter\_loc\_conf\_t \*conf = reinterpret\_cast(child);

```
ngx_conf_merge_value(conf->enable, prev->enable, 0);
ngx_conf_merge_str_value(conf->sessionid, prev->sessionid, "url");
return NGX_CONF_OK;

```

}

static ngx\_int\_t ngx\_http\_ap\_filter\_init(ngx\_conf\_t \*cf) {  
ngx\_http\_handler\_pt \*h;  
ngx\_http\_core\_main\_conf\_t \*cmcf;

```
cmcf = reinterpret_cast(ngx_http_conf_get_module_main_conf(cf,

```

ngx\_http\_core\_module));  
h =  
reinterpret\_cast(ngx\_array\_push(&cmcf-\>phases[NGX\_HTTP\_REWRITE\_PHASE].handlers));  
if (h == NULL) {  
return NGX\_ERROR;  
}  
\*h = ngx\_http\_ap\_filter\_handler;

```
return NGX_OK;

```

}

static ngx\_int\_t ngx\_http\_ap\_filter\_handler(ngx\_http\_request\_t \*r) {  
ngx\_int\_t rc;  
ngx\_http\_ap\_filter\_ctx\_t \*ctx;  
ctx = reinterpret\_cast(ngx\_http\_get\_module\_ctx(r,  
ngx\_http\_ap\_filter\_module));  
if (ctx == NULL) {  
ctx = reinterpret\_cast(ngx\_pcalloc(r-\>pool,  
sizeof(ngx\_http\_ap\_filter\_module)));  
if (ctx == NULL) {  
return NGX\_HTTP\_INTERNAL\_SERVER\_ERROR;  
}

```
    ngx_http_set_ctx(r, ctx, ngx_http_ap_filter_module);
}
rc = ngx_http_ap_filter(r, ctx);
if (rc == NGX_ERROR || rc >= NGX_HTTP_SPECIAL_RESPONSE) {
    return rc;
}
if (rc == NGX_AGAIN) {
    return NGX_DONE;
}
if (rc != NGX_OK) {
    return rc;
}
return NGX_DECLINED;

```

}

static ngx\_int\_t ngx\_http\_ap\_filter\_get\_cookie(ngx\_http\_request\_t \*r,  
ngx\_str\_t \*cookie\_value) {  
ngx\_int\_t n;  
ngx\_str\_t cookie\_key;  
cookie\_key.len = sizeof(“sid”)-1;  
ngx\_str\_set(&cookie\_key, “sid”);  
n = ngx\_http\_parse\_multi\_header\_lines(&r-\>headers\_in.cookies,  
&cookie\_key, cookie\_value);  
if (n != NGX\_DECLINED) {  
// ziskal jsem cookie  
return NGX\_OK;  
} else {  
return NGX\_DECLINED;  
}  
}

static ngx\_int\_t ngx\_http\_ap\_filter\_set\_cookie(ngx\_http\_request\_t \*r,  
ngx\_str\_t \*cookie\_value,  
ngx\_http\_ap\_filter\_ctx\_t \*ctx) {  
u\_char \*cookie, \*p;  
size\_t len;  
ngx\_table\_elt\_t \*set\_cookie;

```
u_char expires[] = "; expires=Thu, 31-Dec-37 23:55:55

```

GMT";  
len = 250;  
cookie = reinterpret\_cast(ngx\_pnalloc(r-\>pool, len));  
// vlozime nazev cookie - sid  
p = ngx\_copy(cookie, “sid”, 3);  
\*p++ = ‘=’;  
p = ngx\_cpymem(p, cookie\_value-\>data, cookie\_value-\>len);  
p = ngx\_cpymem(p, expires, sizeof(“; expires=”) - 1);  
p = ngx\_http\_cookie\_time(p, ngx\_time() + COOKIE\_EXPIRES\_TIME);

```
set_cookie =

```

reinterpret\_cast(ngx\_list\_push(&r-\>headers\_out.headers));

```
 if (set_cookie == NULL) {
    return NGX_ERROR;
}
set_cookie->hash = 1;
ngx_str_set(&set_cookie->key, "Set-Cookie");
set_cookie->value.len = p - cookie;
set_cookie->value.data = cookie;
ctx->cookie_sid = set_cookie->value;

// HEADERS_IN SECTION:
const u_char cookie_key[] = "COOKIE";
ngx_table_elt_t *set_cookie_in;
u_char ch;
ngx_uint_t i,j;

ngx_list_part_t *part = &(r->headers_in.headers.part);
ngx_table_elt_t *header = reinterpret_cast(part->elts);
set_cookie_in = NULL;
// find cookies in headers_in.headers
for (i = 0; ; ++i) {
    if (i >= part->nelts) {
        if (part->next == NULL) {
            break;
        }
        part = part->next;
        header = reinterpret_cast(part->elts);
        i = 0;
    }
    if (header[i].key.len != (sizeof(cookie_key) - 1)) {
        continue;
    }

    for (j = 0; j < (sizeof(cookie_key) - 1); ++j) {
        ch = header[i].key.data[j];
        if (ch >= 'a' && ch <= 'z') ch &= ~0x20;
        if (ch != cookie_key[j]) break;
    }
    if (j == (sizeof(cookie_key) - 1)) {
        set_cookie_in = &header[i];
    }
}
// cookie not found !!!!!!!!!!
if (set_cookie_in == NULL) {

    set_cookie_in =

```

reinterpret\_cast(ngx\_list\_push(&(r-\>headers\_in.headers)));  
if (set\_cookie\_in == NULL) {  
return 0;  
}  
set\_cookie\_in-\>hash = 1;  
ngx\_str\_set(&set\_cookie\_in-\>key, “Cookie”);  
set\_cookie\_in-\>value.len = p - cookie;  
set\_cookie\_in-\>value.data = cookie;  
// cookie found - everything OK  
} else {  
set\_cookie\_in-\>value.len = p - cookie;  
set\_cookie\_in-\>value.data = cookie;  
}

```
ngx_pfree(r->pool, cookie);

return NGX_OK;

```

}

static ngx\_int\_t ngx\_http\_ap\_filter(ngx\_http\_request\_t \*r,  
ngx\_http\_ap\_filter\_ctx\_t \*ctx) {  
ngx\_http\_ap\_filter\_loc\_conf\_t \*cglcf;  
ngx\_str\_t cookie\_value;

```
cglcf = reinterpret_cast(ngx_http_get_module_loc_conf(r,

```

ngx\_http\_ap\_filter\_module));

```
if (cglcf->enable != 0) {
    ngx_log_debug(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,

```

“ap\_filter enable”);  
} else {  
ngx\_log\_debug(NGX\_LOG\_DEBUG\_HTTP, r-\>connection-\>log, 0,  
“ap\_filter disable”);  
return NGX\_OK;  
}

```
// a C++ object for processinf the cookie
ApCookie_t cookieSid;
if (ngx_http_ap_filter_get_cookie(r, &cookie_value) == NGX_DECLINED)

```

{  
cookieSid.createCookie(reinterpret\_cast(cglcf-\>salt.data),  
cglcf-\>salt.len,  
reinterpret\_cast(r-\>args.data), r-\>args.len);  
} else {  
cookieSid = ApCookie\_t(reinterpret\_cast(cookie\_value.data),  
cookie\_value.len,  
reinterpret\_cast(cglcf-\>salt.data), cglcf-\>salt.len,  
reinterpret\_cast(r-\>args.data), r-\>args.len);  
} // else

```
ngx_str_t cookieString;
ngx_str_set(&cookieString,

```

cookieSid.returnCookie(&(cookieString.len)));

```
ngx_int_t n = ngx_http_ap_filter_set_cookie(r, &cookieString, ctx);

if (n != NGX_OK) {
    return NGX_ERROR;

}

return NGX_OK;

```

}

Posted at Nginx Forum:

> **[Add new cookie into headers\_in](https://forum.nginx.org/read.php?2,169118,169118#msg-169118)**
>
> Hello, I have a filter module in rewrite phase. The module tests if a cookie is in the request. If not the module generates one (if cookie is found the module modifies it) and then send it back to the client via headers\_out. But I need one more...

---

<div class="post-metadata">

**Author:** ![michalkraus](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/aeb1de/32.png) [@michalkraus](https://www.ruby-forum.com/u/michalkraus)\
**Post date:** [January 24, 2011, 4:38pm UTC](https://www.ruby-forum.com/t/add-new-cookie-into-headers-in/202212/2 "2011-01-24T16:38:58Z")

</div>

Hello!

On Mon, Jan 24, 2011 at 10:07:04AM -0500, michalkraus wrote:

> I have managed to modify existing cookie in the headers\_in.headers. But  
> when no cookie is in headers\_in.headers my module is not able to store  
> newly generated cookie to headers\_in.headers. It seems OK in my module  
> but before running proxy module the Nginx stops processing the request.  
> When the first request contains a cookie the Nginx server processes it  
> correctly and each next request (also withnou cookie) as well. This  
> behaviour is a bit confusing and I have no idea how to fix it.

> From architecture point of view, you should never modify  
> r-\>headers\_in. Instead, you should provide module output as  
> variable and use proxy\_set\_header to pass it to backend.

More specifically, modification of r-\>headers\_in will fail and  
cause SIGSEGV at least for subrequests even if done perfectly  
correctly. Don’t do that.

Maxim D.

---

<div class="post-metadata">

**Author:** ![michalkraus](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/aeb1de/32.png) [@michalkraus](https://www.ruby-forum.com/u/michalkraus)\
**Post date:** [January 25, 2011, 9:35am UTC](https://www.ruby-forum.com/t/add-new-cookie-into-headers-in/202212/3 "2011-01-25T09:35:56Z")

</div>

Thanks,  
I have already read this recommendation in another topic. But  
headers\_more\_module can modify header\_in.headers and I wanted to do it  
as well. I will just modify headers\_out and I will provide the cookie as  
a variable and use proxy\_set\_header. So I will avoid SIGSEGV.  
One more question about reading value of a variable in my module. I have  
output as variable $ap\_filter\_gsid from my module and I need to get the  
value in another handler module.

Code in my module seems like:

{ ngx\_string(“ap\_filter\_sessionid”),  
NGX\_HTTP\_MAIN\_CONF|NGX\_HTTP\_SRV\_CONF|NGX\_HTTP\_LOC\_CONF|NGX\_CONF\_TAKE1,  
ngx\_conf\_set\_str\_slot,  
NGX\_HTTP\_LOC\_CONF\_OFFSET,  
offsetof(ngx\_http\_ap\_filter\_loc\_conf\_t, sessionid),  
NULL },

There is string “$ap\_filter\_gsid” in the variable sessionid in  
ngx\_http\_ap\_filter\_loc\_conf\_t struct and not the read value of the  
variable. I need the same for reading $arg\_u from query string. I went  
through some module codes and I found out that I should write my  
function instead of ngx\_conf\_set\_str\_slot directive. I tried to write  
it, but it has never worked. What should be in this function.

Thanks for your advice,  
Michal

Posted at Nginx Forum:

> **[Re: Add new cookie into headers\_in](https://forum.nginx.org/read.php?2,169118,169341#msg-169341)**
>
> Hello, I have a filter module in rewrite phase. The module tests if a cookie is in the request. If not the module generates one (if cookie is found the module modifies it) and then send it back to the client via headers\_out. But I need one more...

---

<div class="post-metadata">

**Author:** ![michalkraus](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/aeb1de/32.png) [@michalkraus](https://www.ruby-forum.com/u/michalkraus)\
**Post date:** [January 25, 2011, 1:56pm UTC](https://www.ruby-forum.com/t/add-new-cookie-into-headers-in/202212/4 "2011-01-25T13:56:08Z")

</div>

Hello!

On Tue, Jan 25, 2011 at 03:34:21AM -0500, michalkraus wrote:

> Thanks,  
> I have already read this recommendation in another topic. But  
> headers\_more\_module can modify header\_in.headers and I wanted to do it

The fact that some third-party module does this doesn’t mean that  
it’s correct.

> ngx\_conf\_set\_str\_slot,  
> NGX\_HTTP\_LOC\_CONF\_OFFSET,  
> offsetof(ngx\_http\_ap\_filter\_loc\_conf\_t, sessionid),  
> NULL },
> 
> There is string “$ap\_filter\_gsid” in the variable sessionid in  
> ngx\_http\_ap\_filter\_loc\_conf\_t struct and not the read value of the  
> variable. I need the same for reading $arg\_u from query string. I went  
> through some module codes and I found out that I should write my  
> function instead of ngx\_conf\_set\_str\_slot directive. I tried to write  
> it, but it has never worked. What should be in this function.

Yes, to allow variable expansion you should take care of it. For  
single variable you may use ngx\_http\_get\_variable\_index() during  
configuration and ngx\_http\_get\_indexed\_variable() at runtime.

If you want to allow arbitrary mix of static strings and variables -  
you may want to use complex values instead. It’s probably easiest  
interface, too, as there is generic configuration handler  
ngx\_http\_set\_complex\_value\_slot available. At runtime use  
ngx\_http\_complex\_value() to obtain expanded value.

Maxim D.

---

<div class="post-metadata">

**Author:** ![michalkraus](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/aeb1de/32.png) [@michalkraus](https://www.ruby-forum.com/u/michalkraus)\
**Post date:** [January 26, 2011, 5:48am UTC](https://www.ruby-forum.com/t/add-new-cookie-into-headers-in/202212/5 "2011-01-26T05:48:57Z")

</div>

On Wed, Jan 26, 2011 at 12:31 PM, agentzh [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid) wrote:

> a right way 🙂 I won’t say that my hack there is not flawless, but I’m  
> open to any concrete test cases that can make it fail 😉
> 
> Re michalkraus: if you want to do that, just check ngx\_headers\_more’s  
> source code. If it fails for you, just send a mail to me or file a bug  
> for my module 🙂

Sorry, it has nothing to do with ngx\_headers\_more, it’s only related  
to the ngx\_http\_subrequest() function in the nginx core. My hack was  
not in the ngx\_headers\_more module, but in ngx\_lua and ngx\_echo. These  
modules adjust the subrequest struct when issuing a subrequest. My  
current way is not perfectly correct:

```
/* XXX work-around a bug in ngx_http_subrequest */
if (r->headers_in.headers.last == &r->headers_in.headers.part) {
    sr->headers_in.headers.last = &sr->headers_in.headers.part;
}

```

I should have checked the implementation of ngx\_list more carefully  
and come up with a saner way to work around that bug. I haven’t met  
any issues yet but my gut feeling is that it’s still not perfect. I’ll  
look at this closer later.

In short, whether it is valid to modify the input headers depends only  
on how subrequests inherit their parents’ input headers, no?

Maxim D., you may not agree that it is a bug in  
ngx\_http\_subrequest, but I do. IMHO, saying flatly that something  
cannot be done just because how it _is_ implemented is boring and no  
fun.

Cheers,  
-agentzh

---

<div class="post-metadata">

**Author:** ![michalkraus](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/aeb1de/32.png) [@michalkraus](https://www.ruby-forum.com/u/michalkraus)\
**Post date:** [January 26, 2011, 5:33am UTC](https://www.ruby-forum.com/t/add-new-cookie-into-headers-in/202212/6 "2011-01-26T05:33:17Z")

</div>

On Tue, Jan 25, 2011 at 8:54 PM, Maxim D. [removed\_email\_address@domain.invalid](mailto:removed_email_address@domain.invalid)  
wrote:

> > I have already read this recommendation in another topic. But  
> > headers\_more\_module can modify header\_in.headers and I wanted to do it
> 
> The fact that some third-party module does this doesn’t mean that  
> it’s correct.

The ngx\_headers\_more module does use some tricks to get around the bug  
that nginx does not copy the input headers struct into subrequests’ in  
a right way 🙂 I won’t say that my hack there is not flawless, but I’m  
open to any concrete test cases that can make it fail 😉

Re michalkraus: if you want to do that, just check ngx\_headers\_more’s  
source code. If it fails for you, just send a mail to me or file a bug  
for my module 🙂

Cheers,  
-agentzh

---

<div class="post-metadata">

**Author:** ![michalkraus](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/aeb1de/32.png) [@michalkraus](https://www.ruby-forum.com/u/michalkraus)\
**Post date:** [January 26, 2011, 8:10am UTC](https://www.ruby-forum.com/t/add-new-cookie-into-headers-in/202212/7 "2011-01-26T08:10:28Z")

</div>

Thanks a lot for your time.  
Now, my module provides the data for cookie as a variable and  
proxy\_set\_header just sets the cookie. Sending a response to client via  
headers\_out is OK.  
I have managed to get the value of the cookie variable in my another  
module. I used ngx\_http\_get\_variable\_index() for getting the index of  
variable in configuration section and then at runtime  
ngx\_http\_get\_indexed\_variable() for getting the value.

Michal

Posted at Nginx Forum:

> **[Re: Add new cookie into headers\_in](https://forum.nginx.org/read.php?2,169118,169652#msg-169652)**
>
> Hello, I have a filter module in rewrite phase. The module tests if a cookie is in the request. If not the module generates one (if cookie is found the module modifies it) and then send it back to the client via headers\_out. But I need one more...

---

<div class="post-metadata">

**Author:** ![michalkraus](https://www.ruby-forum.com/letter_avatar_proxy/v4/letter/m/aeb1de/32.png) [@michalkraus](https://www.ruby-forum.com/u/michalkraus)\
**Post date:** [January 26, 2011, 5:55am UTC](https://www.ruby-forum.com/t/add-new-cookie-into-headers-in/202212/8 "2011-01-26T05:55:13Z")

</div>

> }

Another pitfall with ngx\_http\_subrequest is that subrequests _share_  
the whole variable value cache (i.e., r-\>variables) by default. That  
means, if a subrequest modifies a variable, it will also affects the  
parent, and vice versa. This often leads to very confusing  
side-effects and bad results (which is very similar to how evil global  
variables can be ;)). So I explicitly disable this behavior in the  
subrequests issued by ngx\_lua, ngx\_echo, and ngx\_srcache 🙂

Cheers,  
-agentzh
