Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion appveyor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
113 changes: 110 additions & 3 deletions src/lceasy.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand All @@ -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){
Expand Down Expand Up @@ -324,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;
}
Expand Down Expand Up @@ -566,6 +578,7 @@ static int lcurl_easy_set_CURLU(lua_State *L) {
}

#endif

//}

//{ unset
Expand Down Expand Up @@ -953,6 +966,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_TRAILERDATA, 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

//}

//}
Expand Down Expand Up @@ -1618,6 +1652,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){
Expand Down Expand Up @@ -1780,6 +1878,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 },
Expand Down Expand Up @@ -1808,6 +1909,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 },
Expand Down Expand Up @@ -1868,6 +1972,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

Expand Down
3 changes: 3 additions & 0 deletions src/lceasy.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
4 changes: 4 additions & 0 deletions src/lcopteasy.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
107 changes: 106 additions & 1 deletion test/test_easy.lua
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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()