From 0e425b2d83f80026e2344804e285851461d2e088 Mon Sep 17 00:00:00 2001 From: Sergey Bronnikov Date: Tue, 26 Oct 2021 22:07:26 +0300 Subject: [PATCH] Add option to get cookie without escaping Method req:cookie() implicitly unescapes cookie values. Commit adds ability to get cookie without unescaping: req:cookie('name', { raw = true }) This change was added as a part of http v2 support in commit 'Added ability to set and get cookie without escaping' (42e3002228a2e7c10ce45d34da39922d39cb5967) and later reverted in scope of ticket with discard v2. Follows up #126 Part of #134 --- CHANGELOG.md | 1 + README.md | 4 +- http/server.lua | 8 ++- .../integration/http_server_requests_test.lua | 52 ++++++++++--------- 4 files changed, 38 insertions(+), 27 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 861a89d..55966fb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - Add workflow that publish rockspec. - Add editorconfig to configure indentation. - Add luacheck integration. +- Add option to get cookie without escaping. ### Fixed diff --git a/README.md b/README.md index 0083dad..c896864 100644 --- a/README.md +++ b/README.md @@ -226,7 +226,9 @@ end * `req:query_param(name)` - returns a single GET request parameter value. If `name` is `nil`, returns a Lua table with all arguments. * `req:param(name)` - any request parameter, either GET or POST. -* `req:cookie(name)` - to get a cookie in the request. +* `req:cookie(name, {raw = true})` | to get a cookie in the request. if `raw` + option was set then cookie will not be unescaped, otherwise cookie's value + will be unescaped. * `req:stash(name[, value])` - get or set a variable "stashed" when dispatching a route. * `req:url_for(name, args, query)` - returns the route's exact URL. diff --git a/http/server.lua b/http/server.lua index 166d3c5..c02db0c 100644 --- a/http/server.lua +++ b/http/server.lua @@ -304,14 +304,18 @@ local function setcookie(resp, cookie) return resp end -local function cookie(tx, cookie) +local function cookie(tx, cookie, options) + options = options or {} if tx.headers.cookie == nil then return nil end for k, v in string.gmatch( tx.headers.cookie, "([^=,; \t]+)=([^,; \t]+)") do if k == cookie then - return uri_unescape(v) + if not options.raw then + v = uri_unescape(v) + end + return v end end return nil diff --git a/test/integration/http_server_requests_test.lua b/test/integration/http_server_requests_test.lua index 6aeb410..f0d3e85 100644 --- a/test/integration/http_server_requests_test.lua +++ b/test/integration/http_server_requests_test.lua @@ -203,49 +203,53 @@ g.test_chunked_encoding = function() t.assert_equals(r.body, 'chunkedencodingt\r\nest', 'chunked body') end --- Get cookie. +-- Get raw cookie value (Günter -> Günter). g.test_get_cookie = function() + local cookie = 'Günter' local httpd = g.httpd httpd:route({ path = '/receive_cookie' }, function(req) - local foo = req:cookie('foo') - local baz = req:cookie('baz') + local name = req:cookie('name', { + raw = true + }) return req:render({ - text = ('foo=%s; baz=%s'):format(foo, baz) + text = ('name=%s'):format(name) }) end) + local r = http_client.get(helpers.base_uri .. '/receive_cookie', { headers = { - cookie = 'foo=bar; baz=feez', + cookie = 'name=' .. cookie, } }) - t.assert_equals(r.status, 200, 'status') - t.assert_equals(r.body, 'foo=bar; baz=feez', 'body') + + t.assert_equals(r.status, 200, 'response status') + t.assert_equals(r.body, 'name=' .. cookie, 'body with raw cookie') end --- Cookie. -g.test_set_cookie = function() +-- Get escaped cookie (G%C3%BCnter -> Günter). +g.test_get_escaped_cookie = function() + local str_escaped = 'G%C3%BCnter' + local str_non_escaped = 'Günter' local httpd = g.httpd httpd:route({ - path = '/cookie' + path = '/receive_cookie' }, function(req) - local resp = req:render({text = ''}) - resp:setcookie({ - name = 'test', - value = 'tost', - expires = '+1y', - path = '/abc' - }) - resp:setcookie({ - name = 'xxx', - value = 'yyy' + local name = req:cookie('name') + return req:render({ + text = ('name=%s'):format(name) }) - return resp end) - local r = http_client.get(helpers.base_uri .. '/cookie') - t.assert_equals(r.status, 200, 'status') - t.assert(r.headers['set-cookie'] ~= nil, 'header') + + local r = http_client.get(helpers.base_uri .. '/receive_cookie', { + headers = { + cookie = 'name=' .. str_escaped, + } + }) + + t.assert_equals(r.status, 200, 'response status') + t.assert_equals(r.body, 'name=' .. str_non_escaped, 'body with escaped cookie') end -- Request object methods.