こんにちは。配信/インフラチームの佐々木です。
弊社では広告配信にLuaを利用しておりますが、LuaでCookieを扱う際lua-resty-httpというモジュールを利用すると、Cookieが複数の場合などに非常に便利です。 そこで今回はresty-httpを利用したCookieSyncの流れを、サンプルコードと共に説明したいと思います。 一言にCookieSyncと言っても色々な方式がありますが、今回はSSP(united.jp)側からDSP(example.net)のCookieを自ドメインで保存する形式で記載します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
function fetch(_v) local target_url = "http://example.net" local request_args = {"message": "abc"} local lua_resty_http = require('resty.http') local httpc = lua_resty_http.new() local request_cookies = {} for i in string.gmatch(ngx.var['http_cookie'], "[^%s]+") do if string.match(i, "_example_") then i = string.gsub(i, "%_example_", "") table.insert(request_cookies, i) end end end local res, err = httpc:request_uri(target_url, { method = "GET", query = request_args, timeout = 200, headers = ["Cookie"] = table.concat(request_cookies, ' ') } }) (略) |
resty-httpでCookieを付与する処理は上記のようなコードになります。 "http://example.net"というURLにアクセスする際、クライアントが保持しているCookieから該当するプレフィックス_example_が付いている物だけ抽出し、プレフィックスを取り除いた上でヘッダに付与してリクエストします。プレフィックスを入れる処理は後述します。
1 2 3 4 5 6 7 8 |
local client_cookies = {} local set_cookie = res.headers["Set-Cookie"] if type(set_cookie) == "string" then table.insert(client_cookies, set_cookie) elseif type(set_cookie) == "table" then client_cookies = set_cookie end |
上記の処理では"http://example.net"から付与されたCookieをTableに保存しています。resty-httpの仕様として、SetされるCookieが単数の場合は文字列、複数の場合はTableとして扱われますので、両方のケースが想定される場合は上記のような処理になります。
1 2 3 4 5 6 7 |
local put_cookies = {} for key, value in pairs(client_cookies) do example_cookie = ("_example_" ..value ) example_cookie = string.gsub(example_cookie, "domain=.example.net", "domain=.united.jp") table.insert(put_cookies, example_cookie) end ngx.header['Set-Cookie'] = put_cookies |
CookieSyncをする場合、どのドメインのCookieなのか区別する必要がありますので、プレフィックスに_example_を付与した上で、ドメインを書き換えます。 こうして書き換えたCookieを、クライアントに保存します。 再度クライアントがアクセスした際は、一番上の処理に戻り、保存されたCookieを付与してリクエストをします。
今回はCookieの処理のみになりますので非常に短いコードになりましたが、lua-resty-httpは非常にシンプルで扱いやすく、LuaでAPIを実装する際には非常に有効なモジュールとなっております。
今回は以上となります。