<html>
<head>
<meta http-equiv="Content-Type" content="text/html;
charset=ISO-8859-5">
</head>
<body text="#000000" bgcolor="#FFFFFF">
<pre>Hi! Thanks for review.
</pre>
<div class="moz-cite-prefix">
<pre>On 2/22/19 7:01 PM, Vladislav Shpilevoy wrote:</pre>
</div>
<blockquote type="cite"
cite="mid:dccea1b7-4f6f-78f7-446e-9ccf69b48fce@tarantool.org">
<pre>Hi! Thanks for the fixes! See 3 comments below.
</pre>
<pre>
</pre>
<pre>On 19/02/2019 13:49, Roman wrote:
</pre>
<blockquote type="cite">
<pre>
</pre>
<pre>Hi! Thanks for review.
</pre>
<pre>
</pre>
<pre>On ÁÑ, äÕÒ 16, 2019 at 12:17 AM, Vladislav Shpilevoy <a class="moz-txt-link-rfc2396E" href="mailto:v.shpilevoy@tarantool.org"><v.shpilevoy@tarantool.org></a> wrote:
</pre>
<blockquote type="cite">
<pre>Hi!
</pre>
<pre>
</pre>
<pre> 5. Out of 80 symbols. 2. Still out of 80.
</pre>
<pre> My text editor shows 70 symbols.
</pre>
<pre>Then there is something wrong with your editor, sorry. <a class="moz-txt-link-freetext" href="https://github.com/tarantool/tarantool/blob/romanhabibov/gh-3679-httpc-request/src/lua/httpc.c#L180">https://github.com/tarantool/tarantool/blob/romanhabibov/gh-3679-httpc-request/src/lua/httpc.c#L180</a> Lets count. Here you have 6 tabs - 6 * 8 = 48 symbols. Then you have 55 symbols of "headers must be string or table with \"__tostring\""); 48 + 55 = 103. Also, the error string is not aligned by opening parenthesis. In your email I see, that you have 4 symbols tab, what gives you 79 symbols, but tab width in this file should be 8. So probably you mistakenly set tab width to 4 and the editor shows you < 80 width. Please, fix.
</pre>
</blockquote>
<pre>Ok. Done.
</pre>
</blockquote>
<pre>
</pre>
<pre>1. Now you have leading whitespace on line 182. It is clearly visible in
</pre>
<pre>git diff as a bright red point. Please, do self-review before sending
</pre>
<pre>a patch.
</pre>
</blockquote>
<pre>I'm sorry to waste your time. I was in a hurry and did't notice.
</pre>
<blockquote type="cite"
cite="mid:dccea1b7-4f6f-78f7-446e-9ccf69b48fce@tarantool.org">
<blockquote type="cite">
<pre>
</pre>
<pre>commit c9802592b27cb6986e3e72eb948d8dbfb21baa7e
</pre>
<pre>Author: Roman Khabibov <a class="moz-txt-link-rfc2396E" href="mailto:roman.habibov@tarantool.org"><roman.habibov@tarantool.org></a>
</pre>
<pre>Date: Wed Dec 26 17:49:34 2018 +0300
</pre>
<pre>
</pre>
<pre>httpc: add checking of headers in httpc:request
</pre>
<pre>Add preprocessing of the request headers. Each header must be 'string' or 'table'
</pre>
<pre>with '__tostring' metamethod.
</pre>
<pre>Closes #3679
</pre>
<pre>
</pre>
<pre>diff --git a/src/lua/httpc.c b/src/lua/httpc.c
</pre>
<pre>index 5f4e2e912..fb012f58b 100644
</pre>
<pre>--- a/src/lua/httpc.c
</pre>
<pre>+++ b/src/lua/httpc.c
</pre>
<pre>@@ -173,6 +173,18 @@ luaT_httpc_request(lua_State *L)
</pre>
<pre>if (!lua_isnil(L, -1)) {
</pre>
<pre>lua_pushnil(L);
</pre>
<pre>while (lua_next(L, -2) != 0) {
</pre>
<pre>+ int header_type = lua_type(L, -1);
</pre>
<pre>+ if (header_type != LUA_TSTRING) {
</pre>
<pre>+ char *err_msg = "headers must be " \
</pre>
<pre>+ "string or table with \"__tostring\"";
</pre>
</blockquote>
<pre>
</pre>
<pre>2. Please, do not assign a const char string to
</pre>
<pre>a 'char *' variable. Use 'const char *'. Also,
</pre>
<pre>please, properly align strings. This part should
</pre>
<pre>look like this:
</pre>
<pre>
</pre>
<pre> if (header_type != LUA_TSTRING) {
</pre>
<pre> const char *err_msg =
</pre>
<pre> "headers must be string or table with "\
</pre>
<pre> "\"__tostring\"";
</pre>
<pre> if (header_type != LUA_TTABLE) {
</pre>
<pre>
</pre>
<pre>Wrapped string is aligned by the beginning.
</pre>
<pre>
</pre>
<blockquote type="cite">
<pre>+ if (header_type != LUA_TTABLE) {
</pre>
<pre>+ return luaL_error(L, err_msg);
</pre>
<pre>+ } else if (!luaL_getmetafield(L, -1,
</pre>
<pre>+ "__tostring")) {
</pre>
<pre>+ return luaL_error(L, err_msg);
</pre>
<pre>+ }
</pre>
<pre>+ lua_pop(L, 1);
</pre>
<pre>+ }
</pre>
</blockquote>
</blockquote>
<pre>Done.</pre>
<pre><pre>+ const char *err_msg =
+ "headers must be string or table "\
+ "with \"__tostring\"";
</pre>
<pre>commit 42d25f4d6eef69ae56db3841863afa3373fa9b67
Author: Roman Khabibov <a class="moz-txt-link-rfc2396E" href="mailto:roman.habibov@tarantool.org"><roman.habibov@tarantool.org></a>
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 'string' or 'table'
with '__tostring' metamethod.
Closes #3679
diff --git a/src/lua/httpc.c b/src/lua/httpc.c
index 5f4e2e912..db8634949 100644
--- a/src/lua/httpc.c
+++ b/src/lua/httpc.c
@@ -173,6 +173,19 @@ 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) {
+ const char *err_msg =
+ "headers must be string or table "\
+ "with \"__tostring\"";
+ if (header_type != LUA_TTABLE) {
+ return luaL_error(L, err_msg);
+ } else if (!luaL_getmetafield(L, -1,
+ "__tostring")) {
+ return luaL_error(L, err_msg);
+ }
+ 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..8a98d1e92 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 = 'headers must be string or table with "__tostring"'
+ 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
</pre></pre>
</body>
</html>