MINOR: httpclient: support payload within a buffer
httpclient_req_gen() takes a payload argument which can be use to put a
payload in the request. This payload can only fit a request buffer.
This payload can also be specified by the "body" named parameter within
the lua. httpclient.
It is also used within the CLI httpclient when specified as a CLI
payload with "<<".
diff --git a/include/haproxy/http_client.h b/include/haproxy/http_client.h
index 097997e..13673e8 100644
--- a/include/haproxy/http_client.h
+++ b/include/haproxy/http_client.h
@@ -9,7 +9,7 @@
struct appctx *httpclient_start(struct httpclient *hc);
int httpclient_res_xfer(struct httpclient *hc, struct buffer *dst);
-int httpclient_req_gen(struct httpclient *hc, const struct ist url, enum http_meth_t meth, const struct http_hdr *hdrs);
+int httpclient_req_gen(struct httpclient *hc, const struct ist url, enum http_meth_t meth, const struct http_hdr *hdrs, const struct ist payload);
/* Return the amount of data available in the httpclient response buffer */
diff --git a/reg-tests/lua/lua_httpclient.lua b/reg-tests/lua/lua_httpclient.lua
index 9ea8e33..5ded14f 100644
--- a/reg-tests/lua/lua_httpclient.lua
+++ b/reg-tests/lua/lua_httpclient.lua
@@ -21,7 +21,7 @@
core.Debug('CRON port:' .. vtc_port)
local httpclient = core.httpclient()
- local response = httpclient:get{url="http://127.0.0.1:" .. vtc_port}
+ local response = httpclient:get{url="http://127.0.0.1:" .. vtc_port, body="foobar-is-the-new-toto"}
core.Info("Received: " .. response.body)
end
diff --git a/src/hlua.c b/src/hlua.c
index ac61a31..a7ed113 100644
--- a/src/hlua.c
+++ b/src/hlua.c
@@ -7164,6 +7164,7 @@
struct http_hdr *hdrs_i = NULL;
struct hlua *hlua;
const char *url_str = NULL;
+ const char *body_str = NULL;
int ret;
hlua = hlua_gethlua(L);
@@ -7187,6 +7188,12 @@
}
lua_pop(L, 1);
+ ret = lua_getfield(L, -1, "body");
+ if (ret == LUA_TSTRING) {
+ body_str = lua_tostring(L, -1);
+ }
+ lua_pop(L, 1);
+
if (!url_str) {
WILL_LJMP(luaL_error(L, "'get' need a 'url' argument"));
return 0;
@@ -7204,7 +7211,7 @@
hlua_hc->hc->ops.res_end = hlua_httpclient_res_cb;
- httpclient_req_gen(hlua_hc->hc, hlua_hc->hc->req.url, HTTP_METH_GET, hdrs);
+ httpclient_req_gen(hlua_hc->hc, hlua_hc->hc->req.url, HTTP_METH_GET, hdrs, ist(body_str));
httpclient_start(hlua_hc->hc);
/* free the temporary headers array */
diff --git a/src/http_client.c b/src/http_client.c
index f298fe1..4d1ae05 100644
--- a/src/http_client.c
+++ b/src/http_client.c
@@ -116,6 +116,7 @@
enum http_meth_t meth;
char *meth_str;
struct ist uri;
+ struct ist body = IST_NULL;
if (!cli_has_level(appctx, ACCESS_LVL_ADMIN))
return 1;
@@ -128,6 +129,9 @@
meth_str = args[1];
uri = ist(args[2]);
+ if (payload)
+ body = ist(payload);
+
meth = find_http_meth(meth_str, strlen(meth_str));
hc = httpclient_new(appctx, meth, uri);
@@ -144,7 +148,7 @@
appctx->ctx.cli.p0 = hc; /* store the httpclient ptr in the applet */
appctx->ctx.cli.i0 = 0;
- if (httpclient_req_gen(hc, hc->req.url, hc->req.meth, default_httpclient_hdrs) != ERR_NONE)
+ if (httpclient_req_gen(hc, hc->req.url, hc->req.meth, default_httpclient_hdrs, body) != ERR_NONE)
goto err;
@@ -253,13 +257,13 @@
* If the buffer was filled correctly the function returns 0, if not it returns
* an error_code but there is no guarantee that the buffer wasn't modified.
*/
-int httpclient_req_gen(struct httpclient *hc, const struct ist url, enum http_meth_t meth, const struct http_hdr *hdrs)
+int httpclient_req_gen(struct httpclient *hc, const struct ist url, enum http_meth_t meth, const struct http_hdr *hdrs, const struct ist payload)
{
struct htx_sl *sl;
struct htx *htx;
int err_code = 0;
struct ist meth_ist, vsn;
- unsigned int flags = HTX_SL_F_VER_11 | HTX_SL_F_BODYLESS | HTX_SL_F_XFER_LEN | HTX_SL_F_NORMALIZED_URI | HTX_SL_F_HAS_SCHM;
+ unsigned int flags = HTX_SL_F_VER_11 | HTX_SL_F_NORMALIZED_URI | HTX_SL_F_HAS_SCHM;
if (meth >= HTTP_METH_OTHER)
goto error;
@@ -292,6 +296,13 @@
goto error;
}
+ if (isttest(payload)) {
+ /* add the payload if it can feat in the buffer, no need to set
+ * the Content-Length, the data will be sent chunked */
+ if (!htx_add_data_atonce(htx, payload))
+ goto error;
+ }
+
htx->flags |= HTX_FL_EOM;
htx_to_buf(htx, &hc->req.buf);