From 3497febbe72418af880d54e5c8b6cb6f79379f4f Mon Sep 17 00:00:00 2001 From: Alexey Melnichuk Date: Sat, 6 Apr 2019 13:36:43 +0300 Subject: [PATCH 1/4] Fix. Undef forward declaration in the lceasy.h file. --- src/lceasy.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/lceasy.h b/src/lceasy.h index 3c244ee..3cd4a47 100644 --- a/src/lceasy.h +++ b/src/lceasy.h @@ -111,6 +111,9 @@ size_t lcurl_read_callback(lua_State *L, #ifdef lcurl_mime_t #undef lcurl_mime_t #endif +#ifdef lcurl_url_t +#undef lcurl_url_t +#endif #endif #endif From e70f6ac9a3980027c0ec25712fa20f6f5adcc47a Mon Sep 17 00:00:00 2001 From: Alexey Melnichuk Date: Sat, 6 Apr 2019 19:20:38 +0300 Subject: [PATCH 2/4] Add. Support CURLOPT_TRAILERFUNCTION --- appveyor.yml | 2 +- src/lceasy.c | 107 ++++++++++++++++++++++++++++++++++++++++++++- src/lceasy.h | 3 ++ test/test_easy.lua | 107 ++++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 216 insertions(+), 3 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 07dbc35..de0aee5 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -7,7 +7,7 @@ shallow_clone: true environment: LR_EXTERNAL: c:\external - CURL_VER: 7.63.0 + CURL_VER: 7.64.0 matrix: - LUA: "lua 5.1" diff --git a/src/lceasy.c b/src/lceasy.c index 0b0fc4a..bccc1d0 100644 --- a/src/lceasy.c +++ b/src/lceasy.c @@ -97,6 +97,9 @@ int lcurl_easy_create(lua_State *L, int error_mode){ p->match.cb_ref = p->match.ud_ref = LUA_NOREF; p->chunk_bgn.cb_ref = p->chunk_bgn.ud_ref = LUA_NOREF; p->chunk_end.cb_ref = p->chunk_end.ud_ref = LUA_NOREF; +#if LCURL_CURL_VER_GE(7,64,0) + p->trailer.cb_ref = p->trailer.ud_ref = LUA_NOREF; +#endif p->rbuffer.ref = LUA_NOREF; for(i = 0; i < LCURL_LIST_COUNT; ++i){ p->lists[i] = LUA_NOREF; @@ -179,10 +182,14 @@ static int lcurl_easy_cleanup(lua_State *L){ luaL_unref(L, LCURL_LUA_REGISTRY, p->chunk_bgn.ud_ref); luaL_unref(L, LCURL_LUA_REGISTRY, p->chunk_end.cb_ref); luaL_unref(L, LCURL_LUA_REGISTRY, p->chunk_end.ud_ref); +#if LCURL_CURL_VER_GE(7,64,0) + luaL_unref(L, LCURL_LUA_REGISTRY, p->trailer.cb_ref); + luaL_unref(L, LCURL_LUA_REGISTRY, p->trailer.ud_ref); +#endif luaL_unref(L, LCURL_LUA_REGISTRY, p->hd.cb_ref); luaL_unref(L, LCURL_LUA_REGISTRY, p->hd.ud_ref); luaL_unref(L, LCURL_LUA_REGISTRY, p->rbuffer.ref); - + p->wr.cb_ref = p->wr.ud_ref = LUA_NOREF; p->rd.cb_ref = p->rd.ud_ref = LUA_NOREF; p->hd.cb_ref = p->hd.ud_ref = LUA_NOREF; @@ -192,6 +199,9 @@ static int lcurl_easy_cleanup(lua_State *L){ p->match.cb_ref = p->match.ud_ref = LUA_NOREF; p->chunk_bgn.cb_ref = p->chunk_bgn.ud_ref = LUA_NOREF; p->chunk_end.cb_ref = p->chunk_end.ud_ref = LUA_NOREF; +#if LCURL_CURL_VER_GE(7,64,0) + p->trailer.cb_ref = p->trailer.ud_ref = LUA_NOREF; +#endif p->rbuffer.ref = LUA_NOREF; for(i = 0; i < LCURL_LIST_COUNT; ++i){ @@ -566,6 +576,7 @@ static int lcurl_easy_set_CURLU(lua_State *L) { } #endif + //} //{ unset @@ -953,6 +964,27 @@ static int lcurl_easy_unset_CURLU(lua_State *L) { #endif +#if LCURL_CURL_VER_GE(7,64,0) + +static int lcurl_easy_unset_TRAILERFUNCTION(lua_State *L){ + lcurl_easy_t *p = lcurl_geteasy(L); + + CURLcode code = curl_easy_setopt(p->curl, CURLOPT_TRAILERFUNCTION, NULL); + if(code != CURLE_OK){ + return lcurl_fail_ex(L, p->err_mode, LCURL_ERROR_EASY, code); + } + curl_easy_setopt(p->curl, CURLOPT_TRAILERFUNCTION, NULL); + + luaL_unref(L, LCURL_LUA_REGISTRY, p->trailer.cb_ref); + luaL_unref(L, LCURL_LUA_REGISTRY, p->trailer.ud_ref); + p->trailer.cb_ref = p->trailer.ud_ref = LUA_NOREF; + + lua_settop(L, 1); + return 1; +} + +#endif + //} //} @@ -1618,6 +1650,70 @@ static int lcurl_easy_set_CHUNK_END_FUNCTION(lua_State *L){ //} +//{ Trailer + +#if LCURL_CURL_VER_GE(7,64,0) + +static int lcurl_trailer_callback(struct curl_slist **list, void *arg) { + lcurl_easy_t *p = arg; + lua_State *L = p->L; + int top = lua_gettop(L); + int n = lcurl_util_push_cb(L, &p->trailer); + + if (lua_pcall(L, n - 1, LUA_MULTRET, 0)) { + assert(lua_gettop(L) >= top); + lua_pushlightuserdata(L, (void*)LCURL_ERROR_TAG); + lua_insert(L, top + 1); + return CURL_TRAILERFUNC_ABORT; + } + + n = lua_gettop(L); + + if (n == top) { + return CURL_TRAILERFUNC_OK; + } + + /* libcurl will free the list */ + *list = lcurl_util_to_slist(L, top + 1); + if (*list) { + lua_settop(L, top); + return CURL_TRAILERFUNC_OK; + } + + // empty array or NULL + if (lua_istable(L, top + 1) || lutil_is_null(L, top + 1)) { + lua_settop(L, top); + return CURL_TRAILERFUNC_OK; + } + + // true + if((lua_type(L, top + 1) == LUA_TBOOLEAN) && (lua_toboolean(L, top + 1))){ + lua_settop(L, top); + return CURL_TRAILERFUNC_OK; + } + + // single nil + if((n == (top + 1)) && lua_isnil(L, top + 1)){ + lua_settop(L, top); + return CURL_TRAILERFUNC_OK; + } + + lua_settop(L, top); + return CURL_TRAILERFUNC_ABORT; +} + +static int lcurl_easy_set_TRAILERFUNCTION (lua_State *L){ + lcurl_easy_t *p = lcurl_geteasy(L); + return lcurl_easy_set_callback(L, p, &p->trailer, + CURLOPT_TRAILERFUNCTION, CURLOPT_TRAILERDATA, + "trailer", lcurl_trailer_callback + ); +} + +#endif + +//} + //} static int lcurl_easy_setopt(lua_State *L){ @@ -1780,6 +1876,9 @@ static const struct luaL_Reg lcurl_easy_methods[] = { #if LCURL_CURL_VER_GE(7,63,0) OPT_ENTRY(curlu, CURLU, TTT, 0, 0) #endif +#if LCURL_CURL_VER_GE(7,64,0) + OPT_ENTRY(trailerfunction, TRAILERFUNCTION, TTT, 0, 0) +#endif #undef OPT_ENTRY #define OPT_ENTRY(L, N, T, S, D) { "unsetopt_"#L, lcurl_easy_unset_##N }, @@ -1808,6 +1907,9 @@ static const struct luaL_Reg lcurl_easy_methods[] = { #if LCURL_CURL_VER_GE(7,63,0) OPT_ENTRY(curlu, CURLU, TTT, 0, 0) #endif +#if LCURL_CURL_VER_GE(7,64,0) + OPT_ENTRY(trailerfunction, TRAILERFUNCTION, TTT, 0, 0) +#endif #undef OPT_ENTRY #define OPT_ENTRY(L, N, T, S) { "getinfo_"#L, lcurl_easy_get_##N }, @@ -1868,6 +1970,9 @@ static const lcurl_const_t lcurl_easy_opt[] = { #if LCURL_CURL_VER_GE(7,63,0) OPT_ENTRY(curlu, CURLU, TTT, 0, 0) #endif +#if LCURL_CURL_VER_GE(7,64,0) + OPT_ENTRY(trailerfunction, TRAILERFUNCTION, TTT, 0, 0) +#endif #undef OPT_ENTRY #undef FLG_ENTRY diff --git a/src/lceasy.h b/src/lceasy.h index 3c244ee..4cafeea 100644 --- a/src/lceasy.h +++ b/src/lceasy.h @@ -89,6 +89,9 @@ typedef struct lcurl_easy_tag{ lcurl_callback_t match; lcurl_callback_t chunk_bgn; lcurl_callback_t chunk_end; +#if LCURL_CURL_VER_GE(7,64,0) + lcurl_callback_t trailer; +#endif }lcurl_easy_t; int lcurl_easy_create(lua_State *L, int error_mode); diff --git a/test/test_easy.lua b/test/test_easy.lua index be9e08f..92d7dcf 100644 --- a/test/test_easy.lua +++ b/test/test_easy.lua @@ -18,7 +18,6 @@ local json = require "dkjson" local path = require "path" local upath = require "path".new('/') local utils = require "utils" --- local url = "http://127.0.0.1:7090/get" local fname = "./test.download" -- local GET_URL = "http://example.com" @@ -1164,4 +1163,110 @@ end end +local _ENV = TEST_CASE'trailer_callback' if ENABLE and is_curl_ge(7,64,0) then + +local url = POST_URL + +local m, c, t + +local function json_data() + return json.decode(table.concat(t)) +end + +local treader = function(t) + local i = 0 + return function() + i = i + 1 + return t[i] + end +end + +function setup() + t = {} + c = assert(scurl.easy{ + url = url, + post = true, + httpheader = {"Transfer-Encoding: chunked"}, + readfunction = treader {'a=1&', 'b=2&'}, + timeout = 60, + }) + assert_equal(c, c:setopt_writefunction(table.insert, t)) +end + +function teardown() + if c then c:close() end + if m then m:close() end + t, c, m = nil +end + +local empty_responses = { + {'no_response', function() end}, + {'nil_response', function() return nil end}, + {'null_response', function() return curl.null end}, + {'true_response', function() return true end}, + {'empty_array', function() return {} end}, +} + +local abort_responses = { + {'false_response', function() return false end}, + {'nil_with_error_response', function() return nil, 'error message' end}, + {'numeric_response_0', function() return 0 end}, + {'numeric_response_1', function() return 1 end}, +} + +for _, response in ipairs(empty_responses) do + _ENV[ 'test_' .. response[1] ] = function() + local trailer_called = 0 + assert_equal(c, c:setopt_trailerfunction(function() + trailer_called = trailer_called + 1 + return response[2]() + end)) + + assert_equal(c, c:perform()) + + assert_equal(1, trailer_called) + + assert_equal(200, c:getinfo_response_code()) + local data = assert_table(json_data()) + + assert_equal('1', data.form.a) + assert_equal('2', data.form.b) + end +end + +for _, response in ipairs(abort_responses) do + _ENV[ 'test_' .. response[1] ] = function() + local trailer_called = 0 + assert_equal(c, c:setopt_trailerfunction(function() + trailer_called = trailer_called + 1 + return response[2]() + end)) + + local ok, err = assert_nil(c:perform()) + assert_equal(1, trailer_called) + assert_equal(curl.error(curl.ERROR_EASY, curl.E_ABORTED_BY_CALLBACK), err) + end +end + +function test_send_header() + local trailer_called = 0 + assert_equal(c, c:setopt_trailerfunction(function() + trailer_called = trailer_called + 1 + return {'x-trailer-header: value'} + end)) + + assert_equal(c, c:perform()) + + assert_equal(1, trailer_called) + + assert_equal(200, c:getinfo_response_code()) + local data = assert_table(json_data()) + + assert_equal('1', data.form.a) + assert_equal('2', data.form.b) + assert_equal('value', data.headers['x-trailer-header']) +end + +end + RUN() From 43c864ad9a11fad2bd5593979e542d809e93b91a Mon Sep 17 00:00:00 2001 From: Alexey Melnichuk Date: Sat, 6 Apr 2019 19:50:29 +0300 Subject: [PATCH 3/4] Add. Support CURLOPT_HTTP09_ALLOWED option. Fix. Set SSL_VERIFYHOST --- src/lceasy.c | 6 ++++-- src/lcopteasy.h | 4 ++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/lceasy.c b/src/lceasy.c index bccc1d0..69fb0dd 100644 --- a/src/lceasy.c +++ b/src/lceasy.c @@ -334,10 +334,12 @@ static int lcurl_opt_set_long_(lua_State *L, int opt){ if(lua_isboolean(L, 2)){ val = lua_toboolean(L, 2); if( val - && (opt == CURLOPT_SSL_VERIFYHOST) + && ( + (opt == CURLOPT_SSL_VERIFYHOST) #if LCURL_CURL_VER_GE(7,52,0) - && (opt == CURLOPT_PROXY_SSL_VERIFYHOST) + || (opt == CURLOPT_PROXY_SSL_VERIFYHOST) #endif + ) ){ val = 2; } diff --git a/src/lcopteasy.h b/src/lcopteasy.h index 166b07d..a213f23 100644 --- a/src/lcopteasy.h +++ b/src/lcopteasy.h @@ -457,6 +457,10 @@ OPT_ENTRY(doh_url, DOH_URL, STR, 0, LCURL_DEFA OPT_ENTRY(upload_buffersize, UPLOAD_BUFFERSIZE, LNG, 0, 64 * 1024) #endif +#if LCURL_CURL_VER_GE(7,64,0) +OPT_ENTRY(http09_allowed, HTTP09_ALLOWED, LNG, 0, 0) +#endif + //{ Restore system macros #ifdef LCURL__TCP_FASTOPEN From e9ac10f6e266c7d0588c7f2a8df8ea530215ef89 Mon Sep 17 00:00:00 2001 From: Alexey Melnichuk Date: Sat, 6 Apr 2019 20:33:52 +0300 Subject: [PATCH 4/4] Fix. Unset trailer data. --- src/lceasy.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lceasy.c b/src/lceasy.c index 69fb0dd..e543675 100644 --- a/src/lceasy.c +++ b/src/lceasy.c @@ -975,7 +975,7 @@ static int lcurl_easy_unset_TRAILERFUNCTION(lua_State *L){ if(code != CURLE_OK){ return lcurl_fail_ex(L, p->err_mode, LCURL_ERROR_EASY, code); } - curl_easy_setopt(p->curl, CURLOPT_TRAILERFUNCTION, NULL); + curl_easy_setopt(p->curl, CURLOPT_TRAILERDATA, NULL); luaL_unref(L, LCURL_LUA_REGISTRY, p->trailer.cb_ref); luaL_unref(L, LCURL_LUA_REGISTRY, p->trailer.ud_ref);