[tarantool-patches] Re: [PATCH] httpc: add checking of headers in httpc:request
Roman
roman.habibov at tarantool.org
Thu Jan 24 17:54:02 MSK 2019
On 09.01.2019 16:29, Roman wrote:
>
>> 1. Firstly, I think, that the patch should be in C in
>> lua/httpc.c and affect only function luaT_httpc_request. It
>> will prevent creation of additional table 'res', maybe
>> will look even shorter, and evidently will be more efficient.
>> It is not so complex logic so as to write it in Lua, IMO.
>>
> Done.
>
> commit beb0562425dd5062af5d18ae202f0f4434cb5108
> Author: Roman Khabibov <roman.habibov at tarantool.org>
> Date: Wed Dec 26 17:49:34 2018 +0300
>
> httpc: add checking of headers in httpc:request
>
> Add preprocessing of the request headers. Each header must be nil,
> 'string' or 'table'
> with '__tostring' metamethod.
>
> Closes #3679
>
> diff --git a/src/lua/httpc.c b/src/lua/httpc.c
> index 5f4e2e912..16a435ef1 100644
> --- a/src/lua/httpc.c
> +++ b/src/lua/httpc.c
> @@ -173,6 +173,15 @@ luaT_httpc_request(lua_State *L)
> if (!lua_isnil(L, -1)) {
> lua_pushnil(L);
> while (lua_next(L, -2) != 0) {
> + int header_type = lua_type(L, -1);
> + if (header_type != LUA_TSTRING) {
> + if (header_type != LUA_TTABLE) {
> + return luaL_error(L, "cannot convert header to a
> string");
> + } else if (luaL_getmetafield(L, -1, "__tostring") ==
> LUA_TNIL) {
> + return luaL_error(L, "cannot convert header to a
> string");
> + }
> + lua_pop(L, 1);
> + }
> if (httpc_set_header(req, "%s: %s",
> lua_tostring(L, -2),
> lua_tostring(L, -1)) < 0) {
> diff --git a/test/app-tap/http_client.test.lua
> b/test/app-tap/http_client.test.lua
> index 10a3728f8..d1fde5009 100755
> --- a/test/app-tap/http_client.test.lua
> +++ b/test/app-tap/http_client.test.lua
> @@ -205,6 +205,80 @@ local function test_errors(test)
> test:is(r.status, 595, "GET: response on bad url")
> end
>
> +-- gh-3679 allow only headers can be converted to string
> +local function test_request_headers(test, url, opts)
> + local exp_err = 'cannot convert header to a string'
> + local cases = {
> + {
> + 'string header',
> + opts = {headers = {aaa = 'aaa'}},
> + exp_err = nil,
> + },
> + {
> + 'header with __tostring() metamethod',
> + opts = {headers = {aaa = setmetatable({}, {
> + __tostring = function(self)
> + return 'aaa'
> + end})}},
> + exp_err = nil,
> + postrequest_check = function(opts)
> + assert(type(opts.headers.aaa) == 'table',
> + '"aaa" header was modified in http_client')
> + end,
> + },
> + {
> + 'boolean header',
> + opts = {headers = {aaa = true}},
> + exp_err = exp_err,
> + },
> + {
> + 'number header',
> + opts = {headers = {aaa = 10}},
> + exp_err = exp_err,
> + },
> + {
> + 'cdata header (box.NULL)',
> + opts = {headers = {aaa = box.NULL}},
> + exp_err = exp_err,
> + },
> + {
> + 'cdata<uint64_t> header',
> + opts = {headers = {aaa = 10ULL}},
> + exp_err = exp_err,
> + },
> + {
> + 'table header w/o metatable',
> + opts = {headers = {aaa = {}}},
> + exp_err = exp_err,
> + },
> + {
> + 'table header w/o __tostring() metamethod',
> + opts = {headers = {aaa = setmetatable({}, {})}},
> + exp_err = exp_err,
> + },
> + }
> + test:plan(#cases)
> +
> + local http = client:new()
> +
> + for _, case in ipairs(cases) do
> + local opts = merge(table.copy(opts), case.opts)
> + local ok, err = pcall(http.get, http, url, opts)
> + if case.postrequest_check ~= nil then
> + case.postrequest_check(opts)
> + end
> + if case.exp_err == nil then
> + -- expect success
> + test:ok(ok, case[1])
> + else
> + -- expect fail
> + assert(type(err) == 'string')
> + err = err:gsub('^builtin/[a-z._]+.lua:[0-9]+: ', '')
> + test:is_deeply({ok, err}, {false, case.exp_err}, case[1])
> + end
> + end
> +end
> +
> local function test_headers(test, url, opts)
> test:plan(19)
> local http = client:new()
> @@ -397,12 +471,13 @@ local function test_concurrent(test, url, opts)
> end
>
> function run_tests(test, sock_family, sock_addr)
> - test:plan(9)
> + test:plan(10)
> local server, url, opts = start_server(test, sock_family, sock_addr)
> test:test("http.client", test_http_client, url, opts)
> test:test("cancel and errinj", test_cancel_and_errinj, url ..
> 'long_query', opts)
> test:test("basic http post/get", test_post_and_get, url, opts)
> test:test("errors", test_errors)
> + test:test("request_headers", test_request_headers, url, opts)
> test:test("headers", test_headers, url, opts)
> test:test("special methods", test_special_methods, url, opts)
> if sock_family == 'AF_UNIX' and jit.os ~= "Linux" then
>
>
More information about the Tarantool-patches
mailing list