Tarantool development patches archive
 help / color / mirror / Atom feed
From: Roman <roman.habibov@tarantool.org>
To: tarantool-patches@freelists.org,
	Alexander Turenko <alexander.turenko@tarantool.org>
Cc: Vladislav Shpilevoy <v.shpilevoy@tarantool.org>
Subject: [tarantool-patches] Re: [PATCH] httpc: add checking of headers in httpc:request
Date: Thu, 24 Jan 2019 17:54:02 +0300	[thread overview]
Message-ID: <9c3f8039-7e92-fc5a-aeb0-0ea30fbea699@tarantool.org> (raw)
In-Reply-To: <72bbdfde-54d7-0e94-c5e7-ca84c2a6078d@tarantool.org>


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@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
>
>

  reply	other threads:[~2019-01-24 14:54 UTC|newest]

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2018-12-21 18:18 [tarantool-patches] " Roman Khabibov
2018-12-23  3:19 ` [tarantool-patches] " Alexander Turenko
2018-12-26 15:56   ` Roman
2018-12-29 10:30     ` Vladislav Shpilevoy
2019-01-09 13:29       ` Roman
2019-01-24 14:54         ` Roman [this message]
2019-01-29 19:44         ` Vladislav Shpilevoy
2019-01-29 20:32           ` Alexander Turenko
2019-01-31 23:47           ` Roman
2019-02-05 11:42             ` Vladislav Shpilevoy
2019-02-11 23:24               ` Roman
2019-02-15 21:17                 ` Vladislav Shpilevoy
2019-02-19 10:49                   ` Roman
2019-02-22 16:01                     ` Vladislav Shpilevoy
2019-02-23 21:38                       ` Roman Khabibov
2019-02-23 22:43                       ` Roman Khabibov
2019-02-25 13:04                         ` Vladislav Shpilevoy
2019-02-25 14:51 ` Kirill Yukhin

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=9c3f8039-7e92-fc5a-aeb0-0ea30fbea699@tarantool.org \
    --to=roman.habibov@tarantool.org \
    --cc=alexander.turenko@tarantool.org \
    --cc=tarantool-patches@freelists.org \
    --cc=v.shpilevoy@tarantool.org \
    --subject='[tarantool-patches] Re: [PATCH] httpc: add checking of headers in httpc:request' \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox