mirror of
http://git.haproxy.org/git/haproxy.git/
synced 2024-12-22 20:32:12 +00:00
MINOR: httpclient/lua: handle the streaming into the lua applet
With this feature the lua implementation of the httpclient is now able to stream a payload larger than an haproxy buffer. The hlua_httpclient_send() function is now split into: hlua_httpclient_send() which initiate the httpclient and parse the lua parameters hlua_httpclient_snd_yield() which will send the request and be called again to stream the request if the body is larger than an haproxy buffer hlua_httpclient_rcv_yield() which will receive the response and store it in the lua buffer.
This commit is contained in:
parent
0da616ee18
commit
bd5739e93e
@ -195,6 +195,7 @@ struct hlua_concat {
|
||||
/* This struct is used to store the httpclient */
|
||||
struct hlua_httpclient {
|
||||
struct httpclient *hc; /* ptr to the httpclient instance */
|
||||
size_t sent; /* payload sent */
|
||||
luaL_Buffer b; /* buffer used to prepare strings. */
|
||||
};
|
||||
|
||||
|
177
src/hlua.c
177
src/hlua.c
@ -6972,7 +6972,7 @@ __LJMP static int hlua_httpclient_new(lua_State *L)
|
||||
*
|
||||
*/
|
||||
|
||||
static void hlua_httpclient_res_cb(struct httpclient *hc)
|
||||
static void hlua_httpclient_cb(struct httpclient *hc)
|
||||
{
|
||||
struct hlua *hlua = hc->caller;
|
||||
|
||||
@ -7036,54 +7036,6 @@ __LJMP static int hlua_httpclient_get_headers(lua_State *L, struct hlua_httpclie
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* For each yield, checks if there is some data in the httpclient and push them
|
||||
* in the lua buffer, once the httpclient finished its job, push the result on
|
||||
* the stack
|
||||
*/
|
||||
__LJMP static int hlua_httpclient_send_yield(lua_State *L, int status, lua_KContext ctx)
|
||||
{
|
||||
struct buffer *tr;
|
||||
int res;
|
||||
struct hlua *hlua = hlua_gethlua(L);
|
||||
struct hlua_httpclient *hlua_hc = hlua_checkhttpclient(L, 1);
|
||||
|
||||
|
||||
tr = get_trash_chunk();
|
||||
|
||||
res = httpclient_res_xfer(hlua_hc->hc, tr);
|
||||
luaL_addlstring(&hlua_hc->b, b_orig(tr), res);
|
||||
|
||||
if (!httpclient_data(hlua_hc->hc) && httpclient_ended(hlua_hc->hc)) {
|
||||
|
||||
luaL_pushresult(&hlua_hc->b);
|
||||
lua_settable(L, -3);
|
||||
|
||||
lua_pushstring(L, "status");
|
||||
lua_pushinteger(L, hlua_hc->hc->res.status);
|
||||
lua_settable(L, -3);
|
||||
|
||||
|
||||
lua_pushstring(L, "reason");
|
||||
lua_pushlstring(L, hlua_hc->hc->res.reason.ptr, hlua_hc->hc->res.reason.len);
|
||||
lua_settable(L, -3);
|
||||
|
||||
lua_pushstring(L, "headers");
|
||||
hlua_httpclient_get_headers(L, hlua_hc);
|
||||
lua_settable(L, -3);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (httpclient_data(hlua_hc->hc))
|
||||
task_wakeup(hlua->task, TASK_WOKEN_MSG);
|
||||
|
||||
|
||||
MAY_LJMP(hlua_yieldk(L, 0, 0, hlua_httpclient_send_yield, TICK_ETERNITY, 0));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Allocate and return an array of http_hdr ist extracted from the <headers> lua table
|
||||
*
|
||||
@ -7153,6 +7105,108 @@ skip_headers:
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* For each yield, checks if there is some data in the httpclient and push them
|
||||
* in the lua buffer, once the httpclient finished its job, push the result on
|
||||
* the stack
|
||||
*/
|
||||
__LJMP static int hlua_httpclient_rcv_yield(lua_State *L, int status, lua_KContext ctx)
|
||||
{
|
||||
struct buffer *tr;
|
||||
int res;
|
||||
struct hlua *hlua = hlua_gethlua(L);
|
||||
struct hlua_httpclient *hlua_hc = hlua_checkhttpclient(L, 1);
|
||||
|
||||
|
||||
tr = get_trash_chunk();
|
||||
|
||||
res = httpclient_res_xfer(hlua_hc->hc, tr);
|
||||
luaL_addlstring(&hlua_hc->b, b_orig(tr), res);
|
||||
|
||||
if (!httpclient_data(hlua_hc->hc) && httpclient_ended(hlua_hc->hc)) {
|
||||
|
||||
luaL_pushresult(&hlua_hc->b);
|
||||
lua_settable(L, -3);
|
||||
|
||||
lua_pushstring(L, "status");
|
||||
lua_pushinteger(L, hlua_hc->hc->res.status);
|
||||
lua_settable(L, -3);
|
||||
|
||||
|
||||
lua_pushstring(L, "reason");
|
||||
lua_pushlstring(L, hlua_hc->hc->res.reason.ptr, hlua_hc->hc->res.reason.len);
|
||||
lua_settable(L, -3);
|
||||
|
||||
lua_pushstring(L, "headers");
|
||||
hlua_httpclient_get_headers(L, hlua_hc);
|
||||
lua_settable(L, -3);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (httpclient_data(hlua_hc->hc))
|
||||
task_wakeup(hlua->task, TASK_WOKEN_MSG);
|
||||
|
||||
MAY_LJMP(hlua_yieldk(L, 0, 0, hlua_httpclient_rcv_yield, TICK_ETERNITY, 0));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Call this when trying to stream a body during a request
|
||||
*/
|
||||
__LJMP static int hlua_httpclient_snd_yield(lua_State *L, int status, lua_KContext ctx)
|
||||
{
|
||||
struct hlua *hlua;
|
||||
struct hlua_httpclient *hlua_hc = hlua_checkhttpclient(L, 1);
|
||||
const char *body_str = NULL;
|
||||
int ret;
|
||||
int end = 0;
|
||||
size_t buf_len;
|
||||
size_t to_send = 0;
|
||||
|
||||
hlua = hlua_gethlua(L);
|
||||
|
||||
if (!hlua || !hlua->task)
|
||||
WILL_LJMP(luaL_error(L, "The 'get' function is only allowed in "
|
||||
"'frontend', 'backend' or 'task'"));
|
||||
|
||||
ret = lua_getfield(L, -1, "body");
|
||||
if (ret != LUA_TSTRING)
|
||||
goto rcv;
|
||||
|
||||
body_str = lua_tolstring(L, -1, &buf_len);
|
||||
lua_pop(L, 1);
|
||||
|
||||
to_send = MIN(buf_len - hlua_hc->sent, 1024);
|
||||
|
||||
if ((hlua_hc->sent + to_send) >= buf_len)
|
||||
end = 1;
|
||||
|
||||
/* the end flag is always set since we are using the whole remaining size */
|
||||
hlua_hc->sent += httpclient_req_xfer(hlua_hc->hc, ist2(body_str + hlua_hc->sent, to_send), end);
|
||||
|
||||
if (buf_len > hlua_hc->sent) {
|
||||
/* still need to process the buffer */
|
||||
MAY_LJMP(hlua_yieldk(L, 0, 0, hlua_httpclient_snd_yield, TICK_ETERNITY, 0));
|
||||
} else {
|
||||
goto rcv;
|
||||
/* we sent the whole request buffer we can recv */
|
||||
}
|
||||
return 0;
|
||||
|
||||
rcv:
|
||||
|
||||
/* we return a "res" object */
|
||||
lua_newtable(L);
|
||||
|
||||
luaL_buffinit(L, &hlua_hc->b);
|
||||
lua_pushstring(L, "body");
|
||||
|
||||
MAY_LJMP(hlua_yieldk(L, 0, 0, hlua_httpclient_rcv_yield, TICK_ETERNITY, 0));
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Send an HTTP request and wait for a response
|
||||
@ -7166,6 +7220,7 @@ __LJMP static int hlua_httpclient_send(lua_State *L, enum http_meth_t meth)
|
||||
struct hlua *hlua;
|
||||
const char *url_str = NULL;
|
||||
const char *body_str = NULL;
|
||||
size_t buf_len;
|
||||
int ret;
|
||||
|
||||
hlua = hlua_gethlua(L);
|
||||
@ -7191,8 +7246,9 @@ __LJMP static int hlua_httpclient_send(lua_State *L, enum http_meth_t meth)
|
||||
|
||||
ret = lua_getfield(L, -1, "body");
|
||||
if (ret == LUA_TSTRING) {
|
||||
body_str = lua_tostring(L, -1);
|
||||
body_str = lua_tolstring(L, -1, &buf_len);
|
||||
}
|
||||
|
||||
lua_pop(L, 1);
|
||||
|
||||
if (!url_str) {
|
||||
@ -7206,13 +7262,16 @@ __LJMP static int hlua_httpclient_send(lua_State *L, enum http_meth_t meth)
|
||||
hlua_hc->hc->req.meth = meth;
|
||||
|
||||
/* update the httpclient callbacks */
|
||||
hlua_hc->hc->ops.res_stline = hlua_httpclient_res_cb;
|
||||
hlua_hc->hc->ops.res_headers = hlua_httpclient_res_cb;
|
||||
hlua_hc->hc->ops.res_payload = hlua_httpclient_res_cb;
|
||||
hlua_hc->hc->ops.res_end = hlua_httpclient_res_cb;
|
||||
hlua_hc->hc->ops.res_stline = hlua_httpclient_cb;
|
||||
hlua_hc->hc->ops.res_headers = hlua_httpclient_cb;
|
||||
hlua_hc->hc->ops.res_payload = hlua_httpclient_cb;
|
||||
|
||||
/* a body is available, it will use the request callback */
|
||||
if (body_str) {
|
||||
hlua_hc->hc->ops.req_payload = hlua_httpclient_cb;
|
||||
}
|
||||
|
||||
ret = httpclient_req_gen(hlua_hc->hc, hlua_hc->hc->req.url, meth, hdrs, ist(body_str));
|
||||
ret = httpclient_req_gen(hlua_hc->hc, hlua_hc->hc->req.url, meth, hdrs, IST_NULL);
|
||||
|
||||
/* free the temporary headers array */
|
||||
hdrs_i = hdrs;
|
||||
@ -7229,16 +7288,10 @@ __LJMP static int hlua_httpclient_send(lua_State *L, enum http_meth_t meth)
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
httpclient_start(hlua_hc->hc);
|
||||
|
||||
/* we return a "res" object */
|
||||
lua_newtable(L);
|
||||
MAY_LJMP(hlua_yieldk(L, 0, 0, hlua_httpclient_snd_yield, TICK_ETERNITY, 0));
|
||||
|
||||
luaL_buffinit(L, &hlua_hc->b);
|
||||
lua_pushstring(L, "body");
|
||||
|
||||
MAY_LJMP(hlua_yieldk(L, 0, 0, hlua_httpclient_send_yield, TICK_ETERNITY, 0));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user