2

I am trying to set a cookie with lua+nginx+redis. This is my idea: set cookie if cookie doesn't exist and then save to redis.

local redis = require "resty.redis"
local red = redis:new()
local md5 = require "md5"

local ip = ngx.var.remote_addr
local secs = ngx.time()
local uid_key = ip .. secs
local uid = md5.sumhexa(uid_key)
local cookie = ngx.var.cookie_uid
local red_cookie = red:hget("cookie:"..uid, uid)

local ok, err = red:connect("127.0.0.1", 6379)
if not ok then
    ngx.say("failed to connect to Redis: ", err)
    return
end

local args = ngx.req.get_headers()
local date_time = ngx.http_time(secs)

if cookie == nil or cookie ~= red_cookie then
    ngx.header['Set-Cookie'] = "path=/; uid=" .. uid
    local res, err = red:hmset("cookie:".. uid,
                               "uid", uid,
                               "date_time", date_time,
                               "user-agent", args["user-agent"]
                               )
    if not res then
        ngx.say("failed to set cookie: ", err)
    end
end

and my nginx conf

...

location /cookie {
    default_type "text/plain";
    lua_code_cache off;
    content_by_lua_file /lua/test.lua;
}

I am not seeing the cookie set however. I get [error] 63519#0: *408 attempt to set ngx.header.HEADER after sending out response headers, client: 127.0.0.1, server: localhost, request: "GET /cookie HTTP/1.1", host: "localhost"

I can't seem to figure out why this wouldn't work? I also thought I could set cookies with purely nginx. I need to track users who visit my page. Any thoughts?

Thanks!!

Update

I revised my idea to make redis requests from an upstream access point. Now I keep getting an invalid reply from redis.parser.

local redis = require "resty.redis"
local md5 = require "md5"
local parser = require "redis.parser"

local ip = ngx.var.remote_addr
local secs = ngx.time()
local uid_key = ip .. secs
local uid = md5.sumhexa(uid_key)

local args = ngx.req.get_headers()
local date_time = ngx.http_time(secs)

local test_cookie = ngx.location.capture("/redis_check_cookie", {args = {cookie_uid="cookie:"..uid}});
if test_cookie.status ~= 200 or not test_cookie.body then
    ngx.log(ngx.ERR, "failed to query redis")
    ngx.exit(500)
end

local reqs = {
    {"hmset", "cookie:"..uid, "path=/"}
}

local raw_reqs = {}
for i, req in ipairs(reqs) do
    table.insert(raw_reqs, parser.build_query(req))
end

local res = ngx.location.capture("/redis_set_cookie?" .. #reqs,
    { body = table.concat(raw_reqs, "")
    })

local replies = parser.parse_replies(res.body, #reqs)
for i, reply in ipairs(replies) do
    ngx.say(reply[1])
end

and my nginx conf now has:

upstream my_redis {
    server 127.0.0.1:6379;
    keepalive 1024 single;
}

and

    location /redis_check_cookie {
        internal;
        set_unescape_uri $cookie_uid $arg_cookie_uid;
        redis2_query hexists $cookie_uid uid;
        redis2_pass my_redis;
    }

    location /redis_set_cookie {
        internal;
        redis2_raw_queries $args $echo_request_body;
        redis2_pass my_redis;
    }

2 Answers 2

0

maybe u forget to display some other things;

i don't have openresty environment; but our environment is similar.

the code below is my test, and it run perfectly

this is nginx.conf

location /cookie {
    default_type "text/plain";
    lua_code_cache off;
    content_by_lua_file test.lua;
} 

this is lua script

local redis = require "redis"
local red = redis.connect('192.168.1.51',6379)

local ip = ngx.var.remote_addr
local secs = ngx.time()
local uid_key = ip .. secs
local uid = (uid_key)
local cookie = ngx.var.cookie_uid
local red_cookie = red:hget("cookie:"..uid, uid)


local args = ngx.req.get_headers()
local date_time = ngx.http_time(secs)

if cookie == nil or cookie ~= red_cookie then
    ngx.header['Set-Cookie'] = "path=/; uid=" .. uid 
    local res, err = red:hmset("cookie:".. uid,
    "uid", uid, "date_time", date_time,
    "user-agent", args["user-agent"])

    if not res then
        ngx.say("failed to set cookie: ", err)
    end 
end

will u display more about your code?

Sign up to request clarification or add additional context in comments.

5 Comments

There was a ngx.say that I thought was commented out that was causing the issue. Do you have any advice as to how to handle requests like this if I have a very high volume of http requests? I think that opening/closing the redis connection will not be ideal for each http request.
@Ptrkcon u can initialize a redis pool, which has many redis connections.Then, u can get a connection from the pool, and dont't need to open and close the connection.
am I using a redis pool in my updated code sample? I am also getting 2213#0: worker process 66823 exited on signal 11 when I leave in the ngx.var.cookie_uid.
@Ptrkcon Now, I'm a little confused about your question. 1: I don't think u use a redis pool, u can write another script which initialize some redis connections, and u can get one connection from the pool.2:You can provide more information about your error, this is not related to redis pool.
Sorry about the confusion. I'm a bit lost too. What I am ultimately trying to do is check is a user has a cookie that I set (query my redis hash) if not, set one and send the info to redis (new hash). So I want to check if ngx.var.cookie_uid exists. When I set nix.var.cookie_uid to a local var I get the segfault where a worker exists on signal 11. The thing is that I have thousands of http requests happening every second so I wanted to do the redis check upstream so I do not have to keep opening/closing my redis connection.
0

friends, yesterday i use my own environment and change some of your code, the program run ok.

But, u say your code is also bad.

Just now, i also use the resty.redis. But the code runs ok.

So, i use your environment and your code according to your post, but the result is ok.

I can't provide u help any more.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.