Skip to content
Snippets Groups Projects
Commit a3b2056b authored by Sergey Bronnikov's avatar Sergey Bronnikov Committed by Igor Munkin
Browse files

uri: escape params

Commit "uri: encode table with http params to a string" (b31aec89)
introduced two functions `params()` and `encode_kv()` that encodes a
table with http key-value parameters to a http query string. However,
keys and values could be interpreted wrong by http server if they
contains reserved symbols that have special meaning for http server.

Patch adds escaping for key-values before encoding params to query
string.

Needed for #7931

NO_CHANGELOG=internal
NO_DOC=internal
parent dcd46244
No related branches found
No related tags found
No related merge requests found
......@@ -289,41 +289,45 @@ local function unescape(buf, opts)
return ffi.string(dst, dst_size)
end
local function encode_kv(key, values, res)
local function encode_kv(key, values, res, escape_opts)
local val = values
if type(val) ~= "table" then
val = { val }
end
local key_escaped= escape(tostring(key), escape_opts)
-- { a = {} } --> "a"
if next(val) == nil then
table.insert(res, key)
table.insert(res, key_escaped)
end
-- { a = { "b" } } --> "a=c"
for _, v in pairs(val) do
local kv = ("%s=%s"):format(key, v)
local val_escaped = escape(tostring(v), escape_opts)
local kv = ("%s=%s"):format(key_escaped, val_escaped)
table.insert(res, kv)
end
end
-- Encode map to a string.
local function params(opts)
-- Encode map to a string and perform escaping of keys and values in
-- parameters.
local function params(opts, escape_opts)
if opts == nil then
return ""
end
if type(opts) ~= "table" then
error("Usage: uri.params(table)")
error("Usage: uri.params(table[, escape_opts])")
end
if next(opts) == nil then
return ""
end
local res = {}
for key, value in pairs(opts) do
if type(key) ~= "string" then
error("uri.params: keys must have a type 'string'")
if type(key) ~= "string" and
type(key) ~= "number" then
error("uri.params: keys must have a type 'string' or 'number'")
end
encode_kv(key, value, res)
encode_kv(key, value, res, escape_opts)
end
return table.concat(res, '&')
......
......@@ -19,7 +19,7 @@ local uri_params_g = t.group("uri_params", {
{ params = { boolean_type = true }, query_string = "boolean_type=true" },
{ params = { integer_type = 50 }, query_string = "integer_type=50" },
{ params = { decimal_type = decimal.new(10) }, query_string = "decimal_type=10" },
{ params = { datetime_type = datetime.new() }, query_string = "datetime_type=1970-01-01T00:00:00Z" },
{ params = { datetime_type = datetime.new() }, query_string = "datetime_type=1970-01-01T00%3A00%3A00Z" },
{ params = { int64_type = tonumber64(-1LL) }, query_string = "int64_type=-1LL" },
{ params = { key = {""} }, query_string = "key=" },
{ params = { key = "test" }, query_string = "key=test" },
......@@ -32,6 +32,16 @@ uri_params_g.test_params = function(cg)
t.assert_equals(uri_params(cg.params.params), cg.params.query_string)
end
g.test_params_escaping = function(_)
local uri_params = uri._internal.params
local params = {
[1] = {"ы", "d&" },
["k%"] = "d%"
}
t.assert_equals(uri_params(params, uri.RFC3986),
"1=%D1%8B&1=d%26&k%25=d%25")
end
local uri_encode_kv_g = t.group("uri_encode_kv", {
{ key = "a", values = { }, res = {"a"} },
{ key = "a", values = "b", res = {"a=b"} },
......@@ -45,6 +55,13 @@ uri_encode_kv_g.test_encode_kv = function(cg)
t.assert_items_equals(res, cg.params.res)
end
g.test_encode_kv_escaping = function(_)
local encode_kv = uri._internal.encode_kv
local res = {}
encode_kv("т", { "б", "д" }, res, uri.RFC3986)
t.assert_items_equals(res, { "%D1%82=%D0%B1", "%D1%82=%D0%B4" })
end
local uri_values_g = t.group("uri_values", {
{ values = nil, encoded = {} },
{ values = "test", encoded = {"test"} },
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment