Add. Support streams to Lua-cURL interface. (See #1)

master
Alexey Melnichuk 2014-09-04 12:51:11 +05:00
parent bb4ed6d1fc
commit 955e6b7ece
6 changed files with 115 additions and 16 deletions

View File

@ -0,0 +1,47 @@
local cURL = require("lcurl.cURL")
c = cURL.easy_init()
c:setopt_url("http://posttestserver.com/post.php")
c:setopt_post(true)
c:post{-- post file from private read function
-- Lua-cURL compatiable
-- allows only one stream
name = {
file="stream.txt",
stream_length="5",
type="text/plain",
}
}
count = 0
c:perform{readfunction = function(n)
if count < 5 then
count = 5
return "stream"
end
return nil
end}
c:post{-- post file from private read function
-- define stream callback
name = {
file = "stream.txt",
type = "text/plain",
stream_length = 5,
stream = function()
if count < 5 then
count = 5
return "STREAM"
end
return nil
end,
}
}
count = 0
c:perform{}
print("Done")

View File

@ -593,9 +593,16 @@ static int lcurl_easy_set_callback(lua_State *L,
const char *method, void *func
)
{
CURLcode code;
lcurl_set_callback(L, c, 2, method);
curl_easy_setopt(p->curl, OPT_CB, (c->cb_ref == LUA_NOREF)?0:func);
code = curl_easy_setopt(p->curl, OPT_CB, (c->cb_ref == LUA_NOREF)?0:func);
if((code != CURLE_OK)&&(c->cb_ref != LUA_NOREF)){
luaL_unref(L, LCURL_LUA_REGISTRY, c->cb_ref);
luaL_unref(L, LCURL_LUA_REGISTRY, c->ud_ref);
c->cb_ref = c->ud_ref = LUA_NOREF;
return lcurl_fail_ex(L, p->err_mode, LCURL_ERROR_EASY, code);
}
curl_easy_setopt(p->curl, OPT_UD, (c->cb_ref == LUA_NOREF)?0:p);
return 1;
@ -605,7 +612,6 @@ static size_t lcurl_write_callback_(lua_State*L,
lcurl_easy_t *p, lcurl_callback_t *c,
char *ptr, size_t size, size_t nmemb
){
size_t ret = size * nmemb;
int top = lua_gettop(L);
int n = lcurl_util_push_cb(L, c);
@ -946,6 +952,14 @@ static const lcurl_const_t lcurl_easy_opt[] = {
};
void lcurl_easy_initlib(lua_State *L, int nup){
/* Hack. We ensure that lcurl_easy_t and lcurl_hpost_stream_t
compatiable for readfunction
*/
LCURL_STATIC_ASSERT(offsetof(lcurl_easy_t, L) == offsetof(lcurl_hpost_stream_t, L));
LCURL_STATIC_ASSERT(offsetof(lcurl_easy_t, rd) == offsetof(lcurl_hpost_stream_t, rd));
LCURL_STATIC_ASSERT(offsetof(lcurl_easy_t, rbuffer) == offsetof(lcurl_hpost_stream_t, rbuffer));
if(!lutil_createmetap(L, LCURL_EASY, lcurl_easy_methods, nup))
lua_pop(L, nup);
lua_pop(L, 1);

View File

@ -24,16 +24,16 @@ enum {
typedef struct lcurl_easy_tag{
lua_State *L;
lcurl_callback_t rd;
lcurl_read_buffer_t rbuffer;
CURL *curl;
int storage;
int lists[LCURL_LIST_COUNT];
int err_mode;
lcurl_callback_t wr;
lcurl_callback_t rd;
lcurl_callback_t hd;
lcurl_callback_t pr;
lcurl_read_buffer_t rbuffer;
}lcurl_easy_t;
int lcurl_easy_create(lua_State *L, int error_mode);

View File

@ -237,6 +237,10 @@ static int lcurl_hpost_add_stream(lua_State *L){
else if(!fname) fname = luaL_checkstring(L, i);
else if(!type) type = luaL_checkstring(L, i);
else{
if(lua_isnil(L, i) && (!ilist)){
++i; // empty headers
break;
}
lua_pushliteral(L, "stream size required");
lua_error(L);
}

View File

@ -6,6 +6,8 @@
#define LCURL_MAKE_VERSION(MIN, MAJ, PAT) ((MIN<<16) + (MAJ<<8) + PAT)
#define LCURL_CURL_VER_GE(MIN, MAJ, PAT) (LIBCURL_VERSION_NUM >= LCURL_MAKE_VERSION(MIN, MAJ, PAT))
#define LCURL_STATIC_ASSERT(A) {(int(*)[(A)?1:0])0;}
typedef struct lcurl_const_tag{
const char *name;
int value;

View File

@ -52,29 +52,57 @@ end
local perform = wrap_function("perform")
local setopt_share = wrap_function("setopt_share")
local setopt_readfunction = wrap_function("setopt_readfunction")
local NONE = {}
function Easy:_call_readfunction(...)
if self._rd_ud == NONE then
return self._rd_fn(...)
end
return self._rd_fn(self._rd_ud, ...)
end
function Easy:setopt_readfunction(fn, ...)
assert(fn)
if select('#', ...) == 0 then
if type(fn) == "function" then
self._rd_fn = fn
self._rd_ud = NONE
else
self._rd_fn = assert(fn.read)
self._rd_ud = fn
end
else
self._rd_fn = fn
self._ud_fn = ...
end
return setopt_readfunction(self, fn, ...)
end
function Easy:perform(opt)
local e = self:handle()
local oerror = opt.errorfunction or function(err) return nil, err end
if opt.readfunction then
local ok, err = e:setopt_readfunction(opt.readfunction)
local ok, err = self:setopt_readfunction(opt.readfunction)
if not ok then return oerror(err) end
end
if opt.writefunction then
local ok, err = e:setopt_writefunction(opt.writefunction)
local ok, err = self:setopt_writefunction(opt.writefunction)
if not ok then return oerror(err) end
end
if opt.headerfunction then
local ok, err = e:setopt_headerfunction(opt.headerfunction)
local ok, err = self:setopt_headerfunction(opt.headerfunction)
if not ok then return oerror(err) end
end
local ok, err = perform(self)
if ok then return oerror(err) end
if not ok then return oerror(err) end
return self
end
@ -89,13 +117,17 @@ function Easy:post(data)
else
assert(type(v) == "table")
if v.stream_length then
form:free()
error("Stream does not support")
end
if v.data then
local len = assert(tonumber(v.stream_length))
assert(v.file)
if v.stream then
ok, err = form:add_stream(k, v.file, v.type, v.headers, len, v.stream)
else
ok, err = form:add_stream(k, v.file, v.type, v.headers, len, self._call_readfunction, self)
end
elseif v.data then
ok, err = form:add_buffer(k, v.file, v.data, v.type, v.headers)
else
ok, err = form:add_file(k, v.file, v.data, v.type, v.filename, v.headers)
ok, err = form:add_file(k, v.file, v.type, v.filename, v.headers)
end
end
if not ok then break end
@ -106,7 +138,7 @@ function Easy:post(data)
return nil, err
end
ok, err = e:setopt_httppost(form)
ok, err = self:setopt_httppost(form)
if not ok then
form:free()
return nil, err