diff --git a/src/hlua.c b/src/hlua.c
index 0163b95de..c1cf83c45 100644
--- a/src/hlua.c
+++ b/src/hlua.c
@@ -156,8 +156,7 @@ static int hlua_panic_ljmp(lua_State *L) { longjmp(safe_ljmp_env, 1); }
#define APPLET_DONE 0x01 /* applet processing is done. */
/* unused: 0x02 */
#define APPLET_HDR_SENT 0x04 /* Response header sent. */
-#define APPLET_CHUNKED 0x08 /* Use transfer encoding chunked. */
-#define APPLET_LAST_CHK 0x10 /* Last chunk sent. */
+/* unused: 0x08, 0x10 */
#define APPLET_HTTP11 0x20 /* Last chunk sent. */
#define APPLET_RSP_SENT 0x40 /* The response was fully sent */
@@ -239,14 +238,6 @@ struct hlua_mem_allocator {
static struct hlua_mem_allocator hlua_global_allocator;
-static const char error_500[] =
- "HTTP/1.0 500 Internal Server Error\r\n"
- "Cache-Control: no-cache\r\n"
- "Connection: close\r\n"
- "Content-Type: text/html\r\n"
- "\r\n"
- "
500 Internal Server Error
\nAn internal server error occurred.\n\n";
-
/* These functions converts types between HAProxy internal args or
* sample and LUA types. Another function permits to check if the
* LUA stack contains arguments according with an required ARG_T
@@ -3899,6 +3890,12 @@ static int hlua_applet_http_new(lua_State *L, struct appctx *ctx)
struct stream_interface *si = ctx->owner;
struct stream *s = si_strm(si);
struct proxy *px = s->be;
+ struct htx *htx;
+ struct htx_blk *blk;
+ struct htx_sl *sl;
+ struct ist path;
+ unsigned long long len = 0;
+ int32_t pos;
/* Check stack size. */
if (!lua_checkstack(L, 3))
@@ -3941,134 +3938,71 @@ static int hlua_applet_http_new(lua_State *L, struct appctx *ctx)
return 0;
lua_settable(L, -3);
- if (IS_HTX_STRM(s)) {
- /* HTX version */
- struct htx *htx = htxbuf(&s->req.buf);
- struct htx_blk *blk;
- struct htx_sl *sl;
- struct ist path;
- unsigned long long len = 0;
- int32_t pos;
+ htx = htxbuf(&s->req.buf);
+ blk = htx_get_first_blk(htx);
+ BUG_ON(htx_get_blk_type(blk) != HTX_BLK_REQ_SL);
+ sl = htx_get_blk_ptr(htx, blk);
- blk = htx_get_first_blk(htx);
- BUG_ON(htx_get_blk_type(blk) != HTX_BLK_REQ_SL);
- sl = htx_get_blk_ptr(htx, blk);
+ /* Stores the request method. */
+ lua_pushstring(L, "method");
+ lua_pushlstring(L, HTX_SL_REQ_MPTR(sl), HTX_SL_REQ_MLEN(sl));
+ lua_settable(L, -3);
- /* Stores the request method. */
- lua_pushstring(L, "method");
- lua_pushlstring(L, HTX_SL_REQ_MPTR(sl), HTX_SL_REQ_MLEN(sl));
- lua_settable(L, -3);
+ /* Stores the http version. */
+ lua_pushstring(L, "version");
+ lua_pushlstring(L, HTX_SL_REQ_VPTR(sl), HTX_SL_REQ_VLEN(sl));
+ lua_settable(L, -3);
- /* Stores the http version. */
- lua_pushstring(L, "version");
- lua_pushlstring(L, HTX_SL_REQ_VPTR(sl), HTX_SL_REQ_VLEN(sl));
- lua_settable(L, -3);
+ /* creates an array of headers. hlua_http_get_headers() crates and push
+ * the array on the top of the stack.
+ */
+ lua_pushstring(L, "headers");
+ htxn.s = s;
+ htxn.p = px;
+ htxn.dir = SMP_OPT_DIR_REQ;
+ if (!hlua_http_get_headers(L, &htxn, &htxn.s->txn->req))
+ return 0;
+ lua_settable(L, -3);
- /* creates an array of headers. hlua_http_get_headers() crates and push
- * the array on the top of the stack.
- */
- lua_pushstring(L, "headers");
- htxn.s = s;
- htxn.p = px;
- htxn.dir = SMP_OPT_DIR_REQ;
- if (!hlua_http_get_headers(L, &htxn, &htxn.s->txn->req))
- return 0;
- lua_settable(L, -3);
+ path = http_get_path(htx_sl_req_uri(sl));
+ if (path.ptr) {
+ char *p, *q, *end;
- path = http_get_path(htx_sl_req_uri(sl));
- if (path.ptr) {
- char *p, *q, *end;
-
- p = path.ptr;
- end = path.ptr + path.len;
- q = p;
- while (q < end && *q != '?')
- q++;
-
- /* Stores the request path. */
- lua_pushstring(L, "path");
- lua_pushlstring(L, p, q - p);
- lua_settable(L, -3);
-
- /* Stores the query string. */
- lua_pushstring(L, "qs");
- if (*q == '?')
- q++;
- lua_pushlstring(L, q, end - q);
- lua_settable(L, -3);
- }
-
- for (pos = htx_get_first(htx); pos != -1; pos = htx_get_next(htx, pos)) {
- struct htx_blk *blk = htx_get_blk(htx, pos);
- enum htx_blk_type type = htx_get_blk_type(blk);
-
- if (type == HTX_BLK_EOM || type == HTX_BLK_TLR || type == HTX_BLK_EOT)
- break;
- if (type == HTX_BLK_DATA)
- len += htx_get_blksz(blk);
- }
- if (htx->extra != ULLONG_MAX)
- len += htx->extra;
+ p = path.ptr;
+ end = path.ptr + path.len;
+ q = p;
+ while (q < end && *q != '?')
+ q++;
/* Stores the request path. */
- lua_pushstring(L, "length");
- lua_pushinteger(L, len);
+ lua_pushstring(L, "path");
+ lua_pushlstring(L, p, q - p);
+ lua_settable(L, -3);
+
+ /* Stores the query string. */
+ lua_pushstring(L, "qs");
+ if (*q == '?')
+ q++;
+ lua_pushlstring(L, q, end - q);
lua_settable(L, -3);
}
- else {
- /* Legacy HTTP version */
- struct http_txn *txn = s->txn;
- const char *path;
- const char *end;
- const char *p;
- /* Stores the request method. */
- lua_pushstring(L, "method");
- lua_pushlstring(L, ci_head(txn->req.chn), txn->req.sl.rq.m_l);
- lua_settable(L, -3);
+ for (pos = htx_get_first(htx); pos != -1; pos = htx_get_next(htx, pos)) {
+ struct htx_blk *blk = htx_get_blk(htx, pos);
+ enum htx_blk_type type = htx_get_blk_type(blk);
- /* Stores the http version. */
- lua_pushstring(L, "version");
- lua_pushlstring(L, ci_head(txn->req.chn) + txn->req.sl.rq.v, txn->req.sl.rq.v_l);
- lua_settable(L, -3);
-
- /* creates an array of headers. hlua_http_get_headers() crates and push
- * the array on the top of the stack.
- */
- lua_pushstring(L, "headers");
- htxn.s = s;
- htxn.p = px;
- htxn.dir = SMP_OPT_DIR_REQ;
- if (!hlua_http_get_headers(L, &htxn, &htxn.s->txn->req))
- return 0;
- lua_settable(L, -3);
-
- /* Get path and qs */
- path = http_txn_get_path(txn);
- if (path) {
- end = ci_head(txn->req.chn) + txn->req.sl.rq.u + txn->req.sl.rq.u_l;
- p = path;
- while (p < end && *p != '?')
- p++;
-
- /* Stores the request path. */
- lua_pushstring(L, "path");
- lua_pushlstring(L, path, p - path);
- lua_settable(L, -3);
-
- /* Stores the query string. */
- lua_pushstring(L, "qs");
- if (*p == '?')
- p++;
- lua_pushlstring(L, p, end - p);
- lua_settable(L, -3);
- }
-
- /* Stores the request path. */
- lua_pushstring(L, "length");
- lua_pushinteger(L, txn->req.body_len);
- lua_settable(L, -3);
+ if (type == HTX_BLK_EOM || type == HTX_BLK_TLR || type == HTX_BLK_EOT)
+ break;
+ if (type == HTX_BLK_DATA)
+ len += htx_get_blksz(blk);
}
+ if (htx->extra != ULLONG_MAX)
+ len += htx->extra;
+
+ /* Stores the request path. */
+ lua_pushstring(L, "length");
+ lua_pushinteger(L, len);
+ lua_settable(L, -3);
/* Create an empty array of HTTP request headers. */
lua_pushstring(L, "response");
@@ -4203,7 +4137,7 @@ __LJMP static int hlua_applet_http_get_priv(lua_State *L)
* consumes the data in the buffer. It returns a string containing the
* data. This string can be empty.
*/
-__LJMP static int hlua_applet_htx_getline_yield(lua_State *L, int status, lua_KContext ctx)
+__LJMP static int hlua_applet_http_getline_yield(lua_State *L, int status, lua_KContext ctx)
{
struct hlua_appctx *appctx = MAY_LJMP(hlua_checkapplet_http(L, 1));
struct stream_interface *si = appctx->appctx->owner;
@@ -4273,7 +4207,7 @@ __LJMP static int hlua_applet_htx_getline_yield(lua_State *L, int status, lua_KC
htx_to_buf(htx, &req->buf);
if (!stop) {
si_cant_get(si);
- MAY_LJMP(hlua_yieldk(L, 0, 0, hlua_applet_htx_getline_yield, TICK_ETERNITY, 0));
+ MAY_LJMP(hlua_yieldk(L, 0, 0, hlua_applet_http_getline_yield, TICK_ETERNITY, 0));
}
/* return the result. */
@@ -4282,63 +4216,6 @@ __LJMP static int hlua_applet_htx_getline_yield(lua_State *L, int status, lua_KC
}
-/* If expected data not yet available, it returns a yield. This function
- * consumes the data in the buffer. It returns a string containing the
- * data. This string can be empty.
- */
-__LJMP static int hlua_applet_http_getline_yield(lua_State *L, int status, lua_KContext ctx)
-{
- struct hlua_appctx *appctx = MAY_LJMP(hlua_checkapplet_http(L, 1));
- struct stream_interface *si = appctx->appctx->owner;
- int ret;
- const char *blk1;
- size_t len1;
- const char *blk2;
- size_t len2;
-
- /* Check for the end of the data. */
- if (appctx->appctx->ctx.hlua_apphttp.left_bytes <= 0) {
- luaL_pushresult(&appctx->b);
- return 1;
- }
-
- /* Read the maximum amount of data available. */
- ret = co_getline_nc(si_oc(si), &blk1, &len1, &blk2, &len2);
-
- /* Data not yet available. return yield. */
- if (ret == 0) {
- si_cant_get(si);
- MAY_LJMP(hlua_yieldk(L, 0, 0, hlua_applet_http_getline_yield, TICK_ETERNITY, 0));
- }
-
- /* End of data: commit the total strings and return. */
- if (ret < 0) {
- luaL_pushresult(&appctx->b);
- return 1;
- }
-
- /* Ensure that the block 2 length is usable. */
- if (ret == 1)
- len2 = 0;
-
- /* Copy the fisrt block caping to the length required. */
- if (len1 > appctx->appctx->ctx.hlua_apphttp.left_bytes)
- len1 = appctx->appctx->ctx.hlua_apphttp.left_bytes;
- luaL_addlstring(&appctx->b, blk1, len1);
- appctx->appctx->ctx.hlua_apphttp.left_bytes -= len1;
-
- /* Copy the second block. */
- if (len2 > appctx->appctx->ctx.hlua_apphttp.left_bytes)
- len2 = appctx->appctx->ctx.hlua_apphttp.left_bytes;
- luaL_addlstring(&appctx->b, blk2, len2);
- appctx->appctx->ctx.hlua_apphttp.left_bytes -= len2;
-
- /* Consume input channel output buffer data. */
- co_skip(si_oc(si), len1 + len2);
- luaL_pushresult(&appctx->b);
- return 1;
-}
-
/* Check arguments for the function "hlua_channel_get_yield". */
__LJMP static int hlua_applet_http_getline(lua_State *L)
{
@@ -4347,17 +4224,14 @@ __LJMP static int hlua_applet_http_getline(lua_State *L)
/* Initialise the string catenation. */
luaL_buffinit(L, &appctx->b);
- if (IS_HTX_STRM(si_strm(appctx->appctx->owner)))
- return MAY_LJMP(hlua_applet_htx_getline_yield(L, 0, 0));
- else
- return MAY_LJMP(hlua_applet_http_getline_yield(L, 0, 0));
+ return MAY_LJMP(hlua_applet_http_getline_yield(L, 0, 0));
}
/* If expected data not yet available, it returns a yield. This function
* consumes the data in the buffer. It returns a string containing the
* data. This string can be empty.
*/
-__LJMP static int hlua_applet_htx_recv_yield(lua_State *L, int status, lua_KContext ctx)
+__LJMP static int hlua_applet_http_recv_yield(lua_State *L, int status, lua_KContext ctx)
{
struct hlua_appctx *appctx = MAY_LJMP(hlua_checkapplet_http(L, 1));
struct stream_interface *si = appctx->appctx->owner;
@@ -4430,70 +4304,6 @@ __LJMP static int hlua_applet_htx_recv_yield(lua_State *L, int status, lua_KCont
lua_replace(L, 2);
}
si_cant_get(si);
- MAY_LJMP(hlua_yieldk(L, 0, 0, hlua_applet_htx_recv_yield, TICK_ETERNITY, 0));
- }
-
- /* return the result. */
- luaL_pushresult(&appctx->b);
- return 1;
-}
-
-/* If expected data not yet available, it returns a yield. This function
- * consumes the data in the buffer. It returns a string containing the
- * data. This string can be empty.
- */
-__LJMP static int hlua_applet_http_recv_yield(lua_State *L, int status, lua_KContext ctx)
-{
- struct hlua_appctx *appctx = MAY_LJMP(hlua_checkapplet_http(L, 1));
- struct stream_interface *si = appctx->appctx->owner;
- int len = MAY_LJMP(luaL_checkinteger(L, 2));
- int ret;
- const char *blk1;
- size_t len1;
- const char *blk2;
- size_t len2;
-
- /* Read the maximum amount of data available. */
- ret = co_getblk_nc(si_oc(si), &blk1, &len1, &blk2, &len2);
-
- /* Data not yet available. return yield. */
- if (ret == 0) {
- si_cant_get(si);
- MAY_LJMP(hlua_yieldk(L, 0, 0, hlua_applet_http_recv_yield, TICK_ETERNITY, 0));
- }
-
- /* End of data: commit the total strings and return. */
- if (ret < 0) {
- luaL_pushresult(&appctx->b);
- return 1;
- }
-
- /* Ensure that the block 2 length is usable. */
- if (ret == 1)
- len2 = 0;
-
- /* Copy the fisrt block caping to the length required. */
- if (len1 > len)
- len1 = len;
- luaL_addlstring(&appctx->b, blk1, len1);
- len -= len1;
-
- /* Copy the second block. */
- if (len2 > len)
- len2 = len;
- luaL_addlstring(&appctx->b, blk2, len2);
- len -= len2;
-
- /* Consume input channel output buffer data. */
- co_skip(si_oc(si), len1 + len2);
- if (appctx->appctx->ctx.hlua_apphttp.left_bytes != -1)
- appctx->appctx->ctx.hlua_apphttp.left_bytes -= len;
-
- /* If we are no other data available, yield waiting for new data. */
- if (len > 0) {
- lua_pushinteger(L, len);
- lua_replace(L, 2);
- si_cant_get(si);
MAY_LJMP(hlua_yieldk(L, 0, 0, hlua_applet_http_recv_yield, TICK_ETERNITY, 0));
}
@@ -4516,27 +4326,12 @@ __LJMP static int hlua_applet_http_recv(lua_State *L)
lua_pop(L, 1);
}
- if (IS_HTX_STRM(si_strm(appctx->appctx->owner))) {
- /* HTX version */
- lua_pushinteger(L, len);
+ lua_pushinteger(L, len);
- /* Initialise the string catenation. */
- luaL_buffinit(L, &appctx->b);
+ /* Initialise the string catenation. */
+ luaL_buffinit(L, &appctx->b);
- return MAY_LJMP(hlua_applet_htx_recv_yield(L, 0, 0));
- }
- else {
- /* Legacy HTTP version */
- /* Check the required length */
- if (len == -1 || len > appctx->appctx->ctx.hlua_apphttp.left_bytes)
- len = appctx->appctx->ctx.hlua_apphttp.left_bytes;
- lua_pushinteger(L, len);
-
- /* Initialise the string catenation. */
- luaL_buffinit(L, &appctx->b);
-
- return MAY_LJMP(hlua_applet_http_recv_yield(L, 0, 0));
- }
+ return MAY_LJMP(hlua_applet_http_recv_yield(L, 0, 0));
}
/* Append data in the output side of the buffer. This data is immediately
@@ -4544,7 +4339,7 @@ __LJMP static int hlua_applet_http_recv(lua_State *L)
* cannot contain the data, the function yields. The function returns -1
* if the channel is closed.
*/
-__LJMP static int hlua_applet_htx_send_yield(lua_State *L, int status, lua_KContext ctx)
+__LJMP static int hlua_applet_http_send_yield(lua_State *L, int status, lua_KContext ctx)
{
struct hlua_appctx *appctx = MAY_LJMP(hlua_checkapplet_http(L, 1));
struct stream_interface *si = appctx->appctx->owner;
@@ -4580,50 +4375,11 @@ __LJMP static int hlua_applet_htx_send_yield(lua_State *L, int status, lua_KCont
if (l < len) {
snd_yield:
htx_to_buf(htx, &res->buf);
- si_rx_room_blk(si);
- MAY_LJMP(hlua_yieldk(L, 0, 0, hlua_applet_htx_send_yield, TICK_ETERNITY, 0));
- }
-
- htx_to_buf(htx, &res->buf);
- return 1;
-}
-
-/* Append data in the output side of the buffer. This data is immediately
- * sent. The function returns the amount of data written. If the buffer
- * cannot contain the data, the function yields. The function returns -1
- * if the channel is closed.
- */
-__LJMP static int hlua_applet_http_send_yield(lua_State *L, int status, lua_KContext ctx)
-{
- size_t len;
- struct hlua_appctx *appctx = MAY_LJMP(hlua_checkapplet_http(L, 1));
- const char *str = MAY_LJMP(luaL_checklstring(L, 2, &len));
- int l = MAY_LJMP(luaL_checkinteger(L, 3));
- struct stream_interface *si = appctx->appctx->owner;
- struct channel *chn = si_ic(si);
- int max;
-
- /* Get the max amount of data which can write as input in the channel. */
- max = channel_recv_max(chn);
- if (max > (len - l))
- max = len - l;
-
- /* Copy data. */
- ci_putblk(chn, str + l, max);
-
- /* update counters. */
- l += max;
- lua_pop(L, 1);
- lua_pushinteger(L, l);
-
- /* If some data is not send, declares the situation to the
- * applet, and returns a yield.
- */
- if (l < len) {
si_rx_room_blk(si);
MAY_LJMP(hlua_yieldk(L, 0, 0, hlua_applet_http_send_yield, TICK_ETERNITY, 0));
}
+ htx_to_buf(htx, &res->buf);
return 1;
}
@@ -4641,36 +4397,10 @@ __LJMP static int hlua_applet_http_send(lua_State *L)
WILL_LJMP(lua_error(L));
}
- if (IS_HTX_STRM(si_strm(appctx->appctx->owner))) {
- /* HTX version */
- /* This interger is used for followinf the amount of data sent. */
- lua_pushinteger(L, 0);
+ /* This interger is used for followinf the amount of data sent. */
+ lua_pushinteger(L, 0);
- return MAY_LJMP(hlua_applet_htx_send_yield(L, 0, 0));
- }
- else {
- /* Legacy HTTP version */
- size_t len;
- char hex[10];
-
- MAY_LJMP(luaL_checklstring(L, 2, &len));
-
- /* If transfer encoding chunked is selected, we surround the data
- * by chunk data.
- */
- if (appctx->appctx->ctx.hlua_apphttp.flags & APPLET_CHUNKED) {
- snprintf(hex, 9, "%x", (unsigned int)len);
- lua_pushfstring(L, "%s\r\n", hex);
- lua_insert(L, 2); /* swap the last 2 entries. */
- lua_pushstring(L, "\r\n");
- lua_concat(L, 3);
- }
-
- /* This interger is used for followinf the amount of data sent. */
- lua_pushinteger(L, 0);
-
- return MAY_LJMP(hlua_applet_http_send_yield(L, 0, 0));
- }
+ return MAY_LJMP(hlua_applet_http_send_yield(L, 0, 0));
}
__LJMP static int hlua_applet_http_addheader(lua_State *L)
@@ -4743,7 +4473,7 @@ __LJMP static int hlua_applet_http_status(lua_State *L)
}
-__LJMP static int hlua_applet_htx_send_response(lua_State *L)
+__LJMP static int hlua_applet_http_send_response(lua_State *L)
{
struct hlua_appctx *appctx = MAY_LJMP(hlua_checkapplet_http(L, 1));
struct stream_interface *si = appctx->appctx->owner;
@@ -4931,207 +4661,22 @@ __LJMP static int hlua_applet_htx_send_response(lua_State *L)
* We will try send at once if its not possible, we give back the hand
* waiting for more room.
*/
-__LJMP static int hlua_applet_htx_start_response_yield(lua_State *L, int status, lua_KContext ctx)
+__LJMP static int hlua_applet_http_start_response_yield(lua_State *L, int status, lua_KContext ctx)
{
struct hlua_appctx *appctx = MAY_LJMP(hlua_checkapplet_http(L, 1));
struct stream_interface *si = appctx->appctx->owner;
struct channel *res = si_ic(si);
if (co_data(res)) {
- si_rx_room_blk(si);
- MAY_LJMP(hlua_yieldk(L, 0, 0, hlua_applet_htx_start_response_yield, TICK_ETERNITY, 0));
- }
- return MAY_LJMP(hlua_applet_htx_send_response(L));
-}
-
-
-__LJMP static int hlua_applet_htx_start_response(lua_State *L)
-{
- return MAY_LJMP(hlua_applet_htx_start_response_yield(L, 0, 0));
-}
-
-/* We will build the status line and the headers of the HTTP response.
- * We will try send at once if its not possible, we give back the hand
- * waiting for more room.
- */
-__LJMP static int hlua_applet_http_start_response_yield(lua_State *L, int status, lua_KContext ctx)
-{
- struct hlua_appctx *appctx = MAY_LJMP(hlua_checkapplet_http(L, 1));
- struct stream_interface *si = appctx->appctx->owner;
- struct channel *chn = si_ic(si);
- int ret;
- size_t len;
- const char *msg;
-
- /* Get the message as the first argument on the stack. */
- msg = MAY_LJMP(luaL_checklstring(L, 2, &len));
-
- /* Send the message at once. */
- ret = ci_putblk(chn, msg, len);
-
- /* if ret == -2 or -3 the channel closed or the message si too
- * big for the buffers.
- */
- if (ret == -2 || ret == -3) {
- hlua_pusherror(L, "Lua: 'start_response': response header block too big");
- WILL_LJMP(lua_error(L));
- }
-
- /* If ret is -1, we dont have room in the buffer, so we yield. */
- if (ret == -1) {
si_rx_room_blk(si);
MAY_LJMP(hlua_yieldk(L, 0, 0, hlua_applet_http_start_response_yield, TICK_ETERNITY, 0));
}
-
- /* Headers sent, set the flag. */
- appctx->appctx->ctx.hlua_apphttp.flags |= APPLET_HDR_SENT;
- return 0;
+ return MAY_LJMP(hlua_applet_http_send_response(L));
}
+
__LJMP static int hlua_applet_http_start_response(lua_State *L)
{
- struct buffer *tmp;
- struct hlua_appctx *appctx = MAY_LJMP(hlua_checkapplet_http(L, 1));
- const char *name;
- size_t name_len;
- const char *value;
- size_t value_len;
- int id;
- long long hdr_contentlength = -1;
- int hdr_chunked = 0;
- const char *reason;
-
- if (IS_HTX_STRM(si_strm(appctx->appctx->owner)))
- return MAY_LJMP(hlua_applet_htx_start_response(L));
-
- reason = appctx->appctx->ctx.hlua_apphttp.reason;
- if (reason == NULL)
- reason = http_get_reason(appctx->appctx->ctx.hlua_apphttp.status);
-
- tmp = get_trash_chunk();
-
- /* Use the same http version than the request. */
- chunk_appendf(tmp, "HTTP/1.%c %d %s\r\n",
- appctx->appctx->ctx.hlua_apphttp.flags & APPLET_HTTP11 ? '1' : '0',
- appctx->appctx->ctx.hlua_apphttp.status,
- reason);
-
- /* Get the array associated to the field "response" in the object AppletHTTP. */
- lua_pushvalue(L, 0);
- if (lua_getfield(L, 1, "response") != LUA_TTABLE) {
- hlua_pusherror(L, "Lua applet http '%s': AppletHTTP['response'] missing.\n",
- appctx->appctx->rule->arg.hlua_rule->fcn.name);
- WILL_LJMP(lua_error(L));
- }
-
- /* Browse the list of headers. */
- lua_pushnil(L);
- while(lua_next(L, -2) != 0) {
-
- /* We expect a string as -2. */
- if (lua_type(L, -2) != LUA_TSTRING) {
- hlua_pusherror(L, "Lua applet http '%s': AppletHTTP['response'][] element must be a string. got %s.\n",
- appctx->appctx->rule->arg.hlua_rule->fcn.name,
- lua_typename(L, lua_type(L, -2)));
- WILL_LJMP(lua_error(L));
- }
- name = lua_tolstring(L, -2, &name_len);
-
- /* We expect an array as -1. */
- if (lua_type(L, -1) != LUA_TTABLE) {
- hlua_pusherror(L, "Lua applet http '%s': AppletHTTP['response']['%s'] element must be an table. got %s.\n",
- appctx->appctx->rule->arg.hlua_rule->fcn.name,
- name,
- lua_typename(L, lua_type(L, -1)));
- WILL_LJMP(lua_error(L));
- }
-
- /* Browse the table who is on the top of the stack. */
- lua_pushnil(L);
- while(lua_next(L, -2) != 0) {
-
- /* We expect a number as -2. */
- if (lua_type(L, -2) != LUA_TNUMBER) {
- hlua_pusherror(L, "Lua applet http '%s': AppletHTTP['response']['%s'][] element must be a number. got %s.\n",
- appctx->appctx->rule->arg.hlua_rule->fcn.name,
- name,
- lua_typename(L, lua_type(L, -2)));
- WILL_LJMP(lua_error(L));
- }
- id = lua_tointeger(L, -2);
-
- /* We expect a string as -2. */
- if (lua_type(L, -1) != LUA_TSTRING) {
- hlua_pusherror(L, "Lua applet http '%s': AppletHTTP['response']['%s'][%d] element must be a string. got %s.\n",
- appctx->appctx->rule->arg.hlua_rule->fcn.name,
- name, id,
- lua_typename(L, lua_type(L, -1)));
- WILL_LJMP(lua_error(L));
- }
- value = lua_tolstring(L, -1, &value_len);
-
- /* Catenate a new header. */
- if (tmp->data + name_len + 2 + value_len + 2 < tmp->size) {
- memcpy(tmp->area + tmp->data, name, name_len);
- tmp->data += name_len;
- tmp->area[tmp->data++] = ':';
- tmp->area[tmp->data++] = ' ';
-
- memcpy(tmp->area + tmp->data, value,
- value_len);
- tmp->data += value_len;
- tmp->area[tmp->data++] = '\r';
- tmp->area[tmp->data++] = '\n';
- }
-
- /* Protocol checks. */
-
- /* Copy the header content length. The length conversion
- * is done without control. If it contains a bad value,
- * the content-length remains negative so that we can
- * switch to either chunked encoding or close.
- */
- if (name_len == 14 && strcasecmp("content-length", name) == 0)
- strl2llrc(value, strlen(value), &hdr_contentlength);
-
- /* Check if the client annouces a transfer-encoding chunked it self. */
- if (name_len == 17 && value_len == 7 &&
- strcasecmp("transfer-encoding", name) == 0 &&
- strcasecmp("chunked", value) == 0)
- hdr_chunked = 1;
-
- /* Remove the array from the stack, and get next element with a remaining string. */
- lua_pop(L, 1);
- }
-
- /* Remove the array from the stack, and get next element with a remaining string. */
- lua_pop(L, 1);
- }
-
- /* If we dont have a content-length set, and the HTTP version is 1.1
- * and the status code implies the presence of a message body, we must
- * announce a transfer encoding chunked. This is required by haproxy
- * for the keepalive compliance. If the applet annouces a transfer-encoding
- * chunked itslef, don't do anything.
- */
- if (hdr_contentlength < 0 && hdr_chunked == 0 &&
- (appctx->appctx->ctx.hlua_apphttp.flags & APPLET_HTTP11) &&
- appctx->appctx->ctx.hlua_apphttp.status >= 200 &&
- appctx->appctx->ctx.hlua_apphttp.status != 204 &&
- appctx->appctx->ctx.hlua_apphttp.status != 304) {
- chunk_appendf(tmp, "Transfer-encoding: chunked\r\n");
- appctx->appctx->ctx.hlua_apphttp.flags |= APPLET_CHUNKED;
- }
-
- /* Finalize headers. */
- chunk_appendf(tmp, "\r\n");
-
- /* Remove the last entry and the array of headers */
- lua_pop(L, 2);
-
- /* Push the headers block. */
- lua_pushlstring(L, tmp->area, tmp->data);
-
return MAY_LJMP(hlua_applet_http_start_response_yield(L, 0, 0));
}
@@ -5188,152 +4733,62 @@ static int hlua_http_new(lua_State *L, struct hlua_txn *txn)
*/
__LJMP static int hlua_http_get_headers(lua_State *L, struct hlua_txn *htxn, struct http_msg *msg)
{
+ struct htx *htx;
+ int32_t pos;
+
/* Create the table. */
lua_newtable(L);
if (!htxn->s->txn)
return 1;
- if (IS_HTX_STRM(htxn->s)) {
- /* HTX version */
- struct htx *htx = htxbuf(&msg->chn->buf);
- int32_t pos;
-
- for (pos = htx_get_first(htx); pos != -1; pos = htx_get_next(htx, pos)) {
- struct htx_blk *blk = htx_get_blk(htx, pos);
- enum htx_blk_type type = htx_get_blk_type(blk);
- struct ist n, v;
- int len;
-
- if (type == HTX_BLK_HDR) {
- n = htx_get_blk_name(htx,blk);
- v = htx_get_blk_value(htx, blk);
- }
- else if (type == HTX_BLK_EOH)
- break;
- else
- continue;
-
- /* Check for existing entry:
- * assume that the table is on the top of the stack, and
- * push the key in the stack, the function lua_gettable()
- * perform the lookup.
- */
- lua_pushlstring(L, n.ptr, n.len);
- lua_gettable(L, -2);
-
- switch (lua_type(L, -1)) {
- case LUA_TNIL:
- /* Table not found, create it. */
- lua_pop(L, 1); /* remove the nil value. */
- lua_pushlstring(L, n.ptr, n.len); /* push the header name as key. */
- lua_newtable(L); /* create and push empty table. */
- lua_pushlstring(L, v.ptr, v.len); /* push header value. */
- lua_rawseti(L, -2, 0); /* index header value (pop it). */
- lua_rawset(L, -3); /* index new table with header name (pop the values). */
- break;
-
- case LUA_TTABLE:
- /* Entry found: push the value in the table. */
- len = lua_rawlen(L, -1);
- lua_pushlstring(L, v.ptr, v.len); /* push header value. */
- lua_rawseti(L, -2, len+1); /* index header value (pop it). */
- lua_pop(L, 1); /* remove the table (it is stored in the main table). */
- break;
-
- default:
- /* Other cases are errors. */
- hlua_pusherror(L, "internal error during the parsing of headers.");
- WILL_LJMP(lua_error(L));
- }
- }
- }
- else {
- /* Legacy HTTP version */
- const char *cur_ptr, *cur_next, *p;
- int old_idx, cur_idx;
- struct hdr_idx_elem *cur_hdr;
- const char *hn, *hv;
- int hnl, hvl;
- const char *in;
- char *out;
+ htx = htxbuf(&msg->chn->buf);
+ for (pos = htx_get_first(htx); pos != -1; pos = htx_get_next(htx, pos)) {
+ struct htx_blk *blk = htx_get_blk(htx, pos);
+ enum htx_blk_type type = htx_get_blk_type(blk);
+ struct ist n, v;
int len;
- /* Build array of headers. */
- old_idx = 0;
- cur_next = ci_head(msg->chn) + hdr_idx_first_pos(&htxn->s->txn->hdr_idx);
+ if (type == HTX_BLK_HDR) {
+ n = htx_get_blk_name(htx,blk);
+ v = htx_get_blk_value(htx, blk);
+ }
+ else if (type == HTX_BLK_EOH)
+ break;
+ else
+ continue;
- while (1) {
- cur_idx = htxn->s->txn->hdr_idx.v[old_idx].next;
- if (!cur_idx)
+ /* Check for existing entry:
+ * assume that the table is on the top of the stack, and
+ * push the key in the stack, the function lua_gettable()
+ * perform the lookup.
+ */
+ lua_pushlstring(L, n.ptr, n.len);
+ lua_gettable(L, -2);
+
+ switch (lua_type(L, -1)) {
+ case LUA_TNIL:
+ /* Table not found, create it. */
+ lua_pop(L, 1); /* remove the nil value. */
+ lua_pushlstring(L, n.ptr, n.len); /* push the header name as key. */
+ lua_newtable(L); /* create and push empty table. */
+ lua_pushlstring(L, v.ptr, v.len); /* push header value. */
+ lua_rawseti(L, -2, 0); /* index header value (pop it). */
+ lua_rawset(L, -3); /* index new table with header name (pop the values). */
break;
- old_idx = cur_idx;
- cur_hdr = &htxn->s->txn->hdr_idx.v[cur_idx];
- cur_ptr = cur_next;
- cur_next = cur_ptr + cur_hdr->len + cur_hdr->cr + 1;
+ case LUA_TTABLE:
+ /* Entry found: push the value in the table. */
+ len = lua_rawlen(L, -1);
+ lua_pushlstring(L, v.ptr, v.len); /* push header value. */
+ lua_rawseti(L, -2, len+1); /* index header value (pop it). */
+ lua_pop(L, 1); /* remove the table (it is stored in the main table). */
+ break;
- /* Now we have one full header at cur_ptr of len cur_hdr->len,
- * and the next header starts at cur_next. We'll check
- * this header in the list as well as against the default
- * rule.
- */
-
- /* look for ': *'. */
- hn = cur_ptr;
- for (p = cur_ptr; p < cur_ptr + cur_hdr->len && *p != ':'; p++);
- if (p >= cur_ptr+cur_hdr->len)
- continue;
- hnl = p - hn;
- p++;
- while (p < cur_ptr+cur_hdr->len && ( *p == ' ' || *p == '\t' ))
- p++;
- if (p >= cur_ptr+cur_hdr->len)
- continue;
- hv = p;
- hvl = cur_ptr+cur_hdr->len-p;
-
- /* Lowercase the key. Don't check the size of trash, it have
- * the size of one buffer and the input data contains in one
- * buffer.
- */
- out = trash.area;
- for (in=hn; ins)) {
- struct htx *htx = htxbuf(&msg->chn->buf);
-
- htx_transform_header_str(htxn->s, msg->chn, htx, ist2(name, name_len), value, re, action);
- }
- else
- http_transform_header_str(htxn->s, msg, name, name_len, value, re, action);
+ htx = htxbuf(&msg->chn->buf);
+ htx_transform_header_str(htxn->s, msg->chn, htx, ist2(name, name_len), value, re, action);
regex_free(re);
return 0;
}
@@ -5433,25 +4884,12 @@ __LJMP static inline int hlua_http_del_hdr(lua_State *L, struct hlua_txn *htxn,
{
size_t len;
const char *name = MAY_LJMP(luaL_checklstring(L, 2, &len));
+ struct htx *htx = htxbuf(&msg->chn->buf);
+ struct http_hdr_ctx ctx;
- if (IS_HTX_STRM(htxn->s)) {
- /* HTX version */
- struct htx *htx = htxbuf(&msg->chn->buf);
- struct http_hdr_ctx ctx;
-
- ctx.blk = NULL;
- while (http_find_header(htx, ist2(name, len), &ctx, 1))
- http_remove_header(htx, &ctx);
- }
- else {
- /* Legacy HTTP version */
- struct hdr_ctx ctx;
- struct http_txn *txn = htxn->s->txn;
-
- ctx.idx = 0;
- while (http_find_header2(name, len, ci_head(msg->chn), &txn->hdr_idx, &ctx))
- http_remove_header2(msg, &txn->hdr_idx, &ctx);
- }
+ ctx.blk = NULL;
+ while (http_find_header(htx, ist2(name, len), &ctx, 1))
+ http_remove_header(htx, &ctx);
return 0;
}
@@ -5484,35 +4922,10 @@ __LJMP static inline int hlua_http_add_hdr(lua_State *L, struct hlua_txn *htxn,
const char *name = MAY_LJMP(luaL_checklstring(L, 2, &name_len));
size_t value_len;
const char *value = MAY_LJMP(luaL_checklstring(L, 3, &value_len));
- char *p;
+ struct htx *htx = htxbuf(&msg->chn->buf);
- if (IS_HTX_STRM(htxn->s)) {
- /* HTX version */
- struct htx *htx = htxbuf(&msg->chn->buf);
-
- lua_pushboolean(L, http_add_header(htx, ist2(name, name_len),
- ist2(value, value_len)));
- }
- else {
- /* Legacy HTTP version */
- /* Check length. */
- trash.data = value_len + name_len + 2;
- if (trash.data > trash.size)
- return 0;
-
- /* Creates the header string. */
- p = trash.area;
- memcpy(p, name, name_len);
- p += name_len;
- *p = ':';
- p++;
- *p = ' ';
- p++;
- memcpy(p, value, value_len);
-
- lua_pushboolean(L, http_header_add_tail2(msg, &htxn->s->txn->hdr_idx,
- trash.area, trash.data) != 0);
- }
+ lua_pushboolean(L, http_add_header(htx, ist2(name, name_len),
+ ist2(value, value_len)));
return 0;
}
@@ -5565,7 +4978,7 @@ static int hlua_http_req_set_meth(lua_State *L)
size_t name_len;
const char *name = MAY_LJMP(luaL_checklstring(L, 2, &name_len));
- lua_pushboolean(L, http_replace_req_line(0, name, name_len, htxn->p, htxn->s) != -1);
+ lua_pushboolean(L, htx_req_replace_stline(0, name, name_len, htxn->p, htxn->s) != -1);
return 1;
}
@@ -5576,7 +4989,7 @@ static int hlua_http_req_set_path(lua_State *L)
size_t name_len;
const char *name = MAY_LJMP(luaL_checklstring(L, 2, &name_len));
- lua_pushboolean(L, http_replace_req_line(1, name, name_len, htxn->p, htxn->s) != -1);
+ lua_pushboolean(L, htx_req_replace_stline(1, name, name_len, htxn->p, htxn->s) != -1);
return 1;
}
@@ -5600,7 +5013,7 @@ static int hlua_http_req_set_query(lua_State *L)
trash.data += name_len;
lua_pushboolean(L,
- http_replace_req_line(2, trash.area, trash.data, htxn->p, htxn->s) != -1);
+ htx_req_replace_stline(2, trash.area, trash.data, htxn->p, htxn->s) != -1);
return 1;
}
@@ -5611,7 +5024,7 @@ static int hlua_http_req_set_uri(lua_State *L)
size_t name_len;
const char *name = MAY_LJMP(luaL_checklstring(L, 2, &name_len));
- lua_pushboolean(L, http_replace_req_line(3, name, name_len, htxn->p, htxn->s) != -1);
+ lua_pushboolean(L, htx_req_replace_stline(3, name, name_len, htxn->p, htxn->s) != -1);
return 1;
}
@@ -5622,7 +5035,7 @@ static int hlua_http_res_set_status(lua_State *L)
unsigned int code = MAY_LJMP(luaL_checkinteger(L, 2));
const char *reason = MAY_LJMP(luaL_optlstring(L, 3, NULL, NULL));
- http_set_status(code, reason, htxn->s);
+ htx_res_set_status(code, reason, htxn->s);
return 0;
}
@@ -5999,25 +5412,6 @@ __LJMP static int hlua_txn_done(lua_State *L)
if (IS_HTX_STRM(htxn->s))
htx_reply_and_close(htxn->s, 0, NULL);
else {
- if (htxn->s->txn) {
- /* HTTP mode, let's stay in sync with the stream */
- b_del(&ic->buf, htxn->s->txn->req.sov);
- htxn->s->txn->req.next -= htxn->s->txn->req.sov;
- htxn->s->txn->req.sov = 0;
-
- ic->analysers &= AN_REQ_HTTP_XFER_BODY;
- oc->analysers = AN_RES_HTTP_XFER_BODY;
- htxn->s->txn->req.msg_state = HTTP_MSG_CLOSED;
- htxn->s->txn->rsp.msg_state = HTTP_MSG_DONE;
-
- /* Note that if we want to support keep-alive, we need
- * to bypass the close/shutr_now calls below, but that
- * may only be done if the HTTP request was already
- * processed and the connection header is known (ie
- * not during TCP rules).
- */
- }
-
channel_auto_read(ic);
channel_abort(ic);
channel_auto_close(ic);
@@ -7185,7 +6579,7 @@ static int hlua_applet_http_init(struct appctx *ctx, struct proxy *px, struct st
return 1;
}
-static void hlua_applet_htx_fct(struct appctx *ctx)
+static void hlua_applet_http_fct(struct appctx *ctx)
{
struct stream_interface *si = ctx->owner;
struct stream *strm = si_strm(si);
@@ -7355,180 +6749,6 @@ static void hlua_applet_htx_fct(struct appctx *ctx)
goto done;
}
-static void hlua_applet_http_fct(struct appctx *ctx)
-{
- struct stream_interface *si = ctx->owner;
- struct stream *strm = si_strm(si);
- struct channel *req = si_oc(si);
- struct channel *res = si_ic(si);
- struct act_rule *rule = ctx->rule;
- struct proxy *px = strm->be;
- struct hlua *hlua = ctx->ctx.hlua_apphttp.hlua;
- const char *blk1;
- size_t len1;
- const char *blk2;
- size_t len2;
- int ret;
-
- if (IS_HTX_STRM(strm))
- return hlua_applet_htx_fct(ctx);
-
- /* If the stream is disconnect or closed, ldo nothing. */
- if (unlikely(si->state == SI_ST_DIS || si->state == SI_ST_CLO))
- goto out;
-
- /* Check if the input buffer is avalaible. */
- if (!b_size(&res->buf)) {
- si_rx_room_blk(si);
- goto out;
- }
- /* check that the output is not closed */
- if (res->flags & (CF_SHUTW|CF_SHUTW_NOW|CF_SHUTR))
- ctx->ctx.hlua_apphttp.flags |= APPLET_DONE;
-
- /* Set the currently running flag. */
- if (!HLUA_IS_RUNNING(hlua) &&
- !(ctx->ctx.hlua_apphttp.flags & APPLET_DONE)) {
- /* Store the max amount of bytes that we can read. */
- ctx->ctx.hlua_apphttp.left_bytes = strm->txn->req.body_len;
-
- /* We need to flush the request header. This left the body
- * for the Lua.
- */
-
- /* Read the maximum amount of data available. */
- ret = co_getblk_nc(req, &blk1, &len1, &blk2, &len2);
- if (ret == -1)
- goto out;
-
- /* No data available, ask for more data. */
- if (ret == 1)
- len2 = 0;
- if (ret == 0)
- len1 = 0;
- if (len1 + len2 < strm->txn->req.eoh + strm->txn->req.eol) {
- si_cant_get(si);
- goto out;
- }
-
- /* skip the requests bytes. */
- co_skip(req, strm->txn->req.eoh + strm->txn->req.eol);
- }
-
- /* Executes The applet if it is not done. */
- if (!(ctx->ctx.hlua_apphttp.flags & APPLET_DONE)) {
-
- /* Execute the function. */
- switch (hlua_ctx_resume(hlua, 1)) {
- /* finished. */
- case HLUA_E_OK:
- ctx->ctx.hlua_apphttp.flags |= APPLET_DONE;
- break;
-
- /* yield. */
- case HLUA_E_AGAIN:
- if (hlua->wake_time != TICK_ETERNITY)
- task_schedule(ctx->ctx.hlua_apphttp.task, hlua->wake_time);
- goto out;
-
- /* finished with error. */
- case HLUA_E_ERRMSG:
- /* Display log. */
- SEND_ERR(px, "Lua applet http '%s': %s.\n",
- rule->arg.hlua_rule->fcn.name, lua_tostring(hlua->T, -1));
- lua_pop(hlua->T, 1);
- goto error;
-
- case HLUA_E_ETMOUT:
- SEND_ERR(px, "Lua applet http '%s': execution timeout.\n",
- rule->arg.hlua_rule->fcn.name);
- goto error;
-
- case HLUA_E_NOMEM:
- SEND_ERR(px, "Lua applet http '%s': out of memory error.\n",
- rule->arg.hlua_rule->fcn.name);
- goto error;
-
- case HLUA_E_YIELD: /* unexpected */
- SEND_ERR(px, "Lua applet http '%s': yield not allowed.\n",
- rule->arg.hlua_rule->fcn.name);
- goto error;
-
- case HLUA_E_ERR:
- /* Display log. */
- SEND_ERR(px, "Lua applet http '%s' return an unknown error.\n",
- rule->arg.hlua_rule->fcn.name);
- goto error;
-
- default:
- goto error;
- }
- }
-
- if (ctx->ctx.hlua_apphttp.flags & APPLET_DONE) {
- if (ctx->ctx.hlua_apphttp.flags & APPLET_RSP_SENT)
- goto done;
-
- if (!(ctx->ctx.hlua_apphttp.flags & APPLET_HDR_SENT))
- goto error;
-
- /* We must send the final chunk. */
- if (ctx->ctx.hlua_apphttp.flags & APPLET_CHUNKED &&
- !(ctx->ctx.hlua_apphttp.flags & APPLET_LAST_CHK)) {
-
- /* sent last chunk at once. */
- ret = ci_putblk(res, "0\r\n\r\n", 5);
-
- /* critical error. */
- if (ret == -2 || ret == -3) {
- SEND_ERR(px, "Lua applet http '%s'cannont send last chunk.\n",
- rule->arg.hlua_rule->fcn.name);
- goto error;
- }
-
- /* no enough space error. */
- if (ret == -1) {
- si_rx_room_blk(si);
- goto out;
- }
-
- strm->txn->status = ctx->ctx.hlua_apphttp.status;
- ctx->ctx.hlua_apphttp.flags |= (APPLET_LAST_CHK|APPLET_RSP_SENT);
- }
- }
-
- done:
- if (ctx->ctx.hlua_apphttp.flags & APPLET_DONE) {
- if (!(res->flags & CF_SHUTR)) {
- res->flags |= CF_READ_NULL;
- si_shutr(si);
- }
-
- /* eat the whole request */
- if (co_data(req))
- co_skip(req, co_data(req));
- }
-
- out:
- return;
-
- error:
-
- /* If we are in HTTP mode, and we are not send any
- * data, return a 500 server error in best effort:
- * if there is no room available in the buffer,
- * just close the connection.
- */
- if (!(ctx->ctx.hlua_apphttp.flags & APPLET_HDR_SENT)) {
- channel_erase(res);
- ci_putblk(res, error_500, strlen(error_500));
- }
- if (!(strm->flags & SF_ERR_MASK))
- strm->flags |= SF_ERR_RESOURCE;
- ctx->ctx.hlua_apphttp.flags |= APPLET_DONE;
- goto done;
-}
-
static void hlua_applet_http_release(struct appctx *ctx)
{
task_destroy(ctx->ctx.hlua_apphttp.task);