How to change cookie header in a filter?

Hi,

What’s the right way to change incoming cookie header so that upstream
can get it just like it’s from user’s original request header? For
example, user’s browser sends:

Cookie: PHPSESSID=34406134e25e5e07727f5de6d5ff7aa3; __utmc=78548747

and I want it to be:

Cookie: PHPSESSID=34406134e25e5e07727f5de6d5ff7aa3; __utmc=78548747;
mycookie=something

when upstream processes the request.

I’m trying to migrate an Apache HTTPd module to nginx, it’s more or less
like mod_usertrack
(mod_usertrack - Apache HTTP Server Version 2.2) but I need to
implement my own logic to enforce compatibility among Apache, Nginx,
IIS, and Jetty.

The question is, for the first time visitor, the incoming request does
not have mycookie in the header, I can determine this and generate
cookie and Set-Cookie in response, however, I also need to change
incoming cookie header so that upstream (php-fpm now, but should be same
to all other upstreams as I’m guessing) can get this generated
“mycookie” as well.

I tried to add new entry to r->headers_in.cookies but it does not work,
also tried r->headers_in.headers but no luck either.

Thanks,

-C

Hello!

On Mon, Mar 18, 2013 at 04:24:05PM -0700, Cool wrote:

Cookie: PHPSESSID=34406134e25e5e07727f5de6d5ff7aa3; __utmc=78548747;
mycookie=something

when upstream processes the request.

I would recommend something like this:

proxy_set_header Cookie "$http_cookie; mycookie=something";

(Similar to what’s usually done with X-Forwarded-For using
the $proxy_add_x_forwarded_for variable.)

to all other upstreams as I’m guessing) can get this generated
“mycookie” as well.

I tried to add new entry to r->headers_in.cookies but it does not work,
also tried r->headers_in.headers but no luck either.

It’s usually not a good idea to change original request headers.
Instead, it is recommended to form appropriate request to an
upstream, see above.


Maxim D.
http://nginx.org/en/donation.html

Thanks Maxim, I got what you mean.

Since I’m using fastCGI so I put something like this:

fastcgi_param HTTP_COOKIE “$http_cookie; mycookie=$cookie_note”;

(I populated cookie_note in my filter already, this was done for logging
purpose thus it is just a reuse of existing facility)

More problems come with this solution:

  1. it seems fastcgi_param called before my filter so $cookie_note always
    got empty, and
  2. it seems fastcgi_param could not be used in a if directive so I end
    up with change the cookie header even the mycookie is presented in
    user’s request, thus
  3. all i got is a empty mycookie value

However, this is really a good start point as at least it changes
cookies sent to upstream, will look into codes to see how it works.

-C

PS, the expected behavior is:

  1. user sends request
  2. if mycookie presents and it is valid (some checksum function), it
    will not be touched and just pass through to upstream
  3. if mycookie does not present or it is invalid (i.e. faked)
  • a new mycookie will be generated based on user’s ip, port, time, etc,
    note that this means mycookies for different users are totally different
  • the new mycookie will be in Set-Cookie header
  • the new mycookie should be in the incoming cookie header as well, so
    that upstream can always have a mycookie
  1. either it’s a mycookie from request or populated, the cookie_note
    variable will be updated, mainly for logging purpose, but could be
    something else (like traffic routing).

于 13-3-19 上午6:04, Maxim D. 写道:

Hello!

On Tue, Mar 19, 2013 at 11:50:43AM -0700, Cool wrote:

  1. it seems fastcgi_param called before my filter so $cookie_note
    always got empty, and

You shouldn’t rely on your filter already executed, and should
instead register a variable handler which does the actual work.
This way it will work at any time.

  1. it seems fastcgi_param could not be used in a if directive so I
    end up with change the cookie header even the mycookie is presented
    in user’s request, thus

If there are conditions when you should not add a cookie I would
recommend you implementing a variable with full Cookie header you
want to pass, e.g.

fastcgi_param HTTP_COOKIE $my_new_cookie;

This way you may implement arbitrary conditions you want in your
module. (You may also construct the variable using if/set/map/etc, but
doing appropriate tests in your module would be less error prone.)


Maxim D.
http://nginx.org/en/donation.html

Got it, thanks, appreciate.

-C
于 13-3-20 上午1:38, Maxim D. 写道: