]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: httpclient: support payload within a buffer
authorWilliam Lallemand <wlallemand@haproxy.org>
Mon, 25 Oct 2021 17:48:37 +0000 (19:48 +0200)
committerWilliam Lallemand <wlallemand@haproxy.org>
Wed, 27 Oct 2021 08:19:41 +0000 (10:19 +0200)
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 "<<".

include/haproxy/http_client.h
reg-tests/lua/lua_httpclient.lua
src/hlua.c
src/http_client.c

index 097997eb5379560ed8f0dccbd72cc80dc6d08ec4..13673e801bb6536fe2ebde70eb93587473a83556 100644 (file)
@@ -9,7 +9,7 @@ struct httpclient *httpclient_new(void *caller, enum http_meth_t meth, struct is
 
 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 */
index 9ea8e334836b35ab10e758b3233951276191d4b7..5ded14f834cda4e934ca561e087a2709856f6d84 100644 (file)
@@ -21,7 +21,7 @@ local function cron()
        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
index ac61a3171bb67e896c60c85ccfea43aed5446d45..a7ed1137a7dca9b72f7d402c74aa1711b14dac86 100644 (file)
@@ -7164,6 +7164,7 @@ __LJMP static int hlua_httpclient_get(lua_State *L)
        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 @@ __LJMP static int hlua_httpclient_get(lua_State *L)
        }
        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 @@ __LJMP static int hlua_httpclient_get(lua_State *L)
        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 */
index f298fe11327023149cab6c6eddcd604cdbf53506..4d1ae053198e0d59d6ab08a252837cdc59d9758b 100644 (file)
@@ -116,6 +116,7 @@ static int hc_cli_parse(char **args, char *payload, struct appctx *appctx, void
        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 @@ static int hc_cli_parse(char **args, char *payload, struct appctx *appctx, void
        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 @@ static int hc_cli_parse(char **args, char *payload, struct appctx *appctx, void
        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 @@ INITCALL1(STG_REGISTER, cli_register_kw, &cli_kws);
  * 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 @@ int httpclient_req_gen(struct httpclient *hc, const struct ist url, enum http_me
                        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);