mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2026-04-04 02:21:53 +02:00
MINOR: haterm: Handle boolean request options as flags
Following request options are now handled as flags: - ?k=1 => flag HS_ST_OPT_CHUNK_RES is set - ?c=0 => flag HS_ST_OPT_NO_CACHE is set - ?R=1 => flag HS_ST_OPT_RANDOM_RES is set - ?A=A => flag HS_ST_OPT_REQ_AFTER_RES is set. By default, none is set.
This commit is contained in:
parent
f349d0b113
commit
3ab5044c1c
@ -21,15 +21,11 @@ struct hstream {
|
||||
int flags;
|
||||
|
||||
int ka; /* .0: keep-alive .1: forced .2: http/1.1, .3: was_reused */
|
||||
int req_cache;
|
||||
unsigned long long req_size; /* values passed in the URI to override the server's */
|
||||
unsigned long long req_body; /* remaining body to be consumed from the request */
|
||||
int req_code;
|
||||
int res_wait; /* time to wait before replying in ms */
|
||||
int res_time;
|
||||
int req_chunked;
|
||||
int req_random;
|
||||
int req_after_res; /* Drain the request body after having sent the response */
|
||||
enum http_meth_t req_meth;
|
||||
};
|
||||
|
||||
|
||||
68
src/haterm.c
68
src/haterm.c
@ -29,6 +29,10 @@ DECLARE_TYPED_POOL(pool_head_hstream, "hstream", struct hstream);
|
||||
#define HS_ST_HTTP_HELP 0x0010
|
||||
#define HS_ST_HTTP_EXPECT 0x0020
|
||||
#define HS_ST_HTTP_RESP_SL_SENT 0x0040
|
||||
#define HS_ST_OPT_CHUNK_RES 0x0080 /* chunk-encoded response (?k=1) */
|
||||
#define HS_ST_OPT_REQ_AFTER_RES 0x0100 /* drain the request payload after the response (?A=1) */
|
||||
#define HS_ST_OPT_RANDOM_RES 0x0200 /* random response (?R=1) */
|
||||
#define HS_ST_OPT_NO_CACHE 0x0400 /* non-cacheable resposne (?c=0) */
|
||||
|
||||
const char *HTTP_HELP =
|
||||
"HAProxy's dummy HTTP server for benchmarks - version " HAPROXY_VERSION ".\n"
|
||||
@ -48,7 +52,7 @@ const char *HTTP_HELP =
|
||||
" E.g. /?K=1\n"
|
||||
" - /?t=<time> wait <time> milliseconds before responding.\n"
|
||||
" E.g. /?t=500\n"
|
||||
" - /?k=<enable> Enable transfer encoding chunked with only one chunk if >0 (disable fast-forward and splicing).\n"
|
||||
" - /?k=<enable> Enable transfer encoding chunked with only one chunk if >0.\n"
|
||||
" - /?S=<enable> Disable use of splice() to send data if <1.\n"
|
||||
" - /?R=<enable> Enable sending random data if >0.\n"
|
||||
"\n"
|
||||
@ -213,7 +217,7 @@ struct task *sc_hstream_io_cb(struct task *t, void *ctx, unsigned int state)
|
||||
task_wakeup(hs->task, TASK_WOKEN_IO);
|
||||
}
|
||||
|
||||
if (((!hs->req_after_res || !hs->to_write) && hs->req_body) ||
|
||||
if (((!(hs->flags & HS_ST_OPT_REQ_AFTER_RES) || !hs->to_write) && hs->req_body) ||
|
||||
!htx_is_empty(htxbuf(&hs->req))) {
|
||||
TRACE_STATE("waking up task", HS_EV_HSTRM_IO_CB, hs);
|
||||
task_wakeup(hs->task, TASK_WOKEN_IO);
|
||||
@ -389,7 +393,7 @@ static int hstream_htx_buf_snd(struct connection *conn, struct hstream *hs)
|
||||
|
||||
if (!htxbuf(&hs->res)->data) {
|
||||
/* This is possible after having drained the body, so after
|
||||
* having sent the response here when req_after_res=1.
|
||||
* having sent the response here when HS_ST_OPT_REQ_AFTER_RES flag is set.
|
||||
*/
|
||||
ret = 1;
|
||||
goto out;
|
||||
@ -541,7 +545,7 @@ static size_t hstream_add_ff_data(struct hstream *hs, struct sedesc *sd, unsigne
|
||||
TRACE_ENTER(HS_EV_HSTRM_ADD_DATA, hs);
|
||||
b_add(sd->iobuf.buf, sd->iobuf.offset);
|
||||
|
||||
if (hs->req_random) {
|
||||
if (hs->flags & HS_ST_OPT_RANDOM_RES) {
|
||||
buffer = random_resp;
|
||||
buffer_len = random_resp_len;
|
||||
modulo = random_resp_len;
|
||||
@ -579,12 +583,12 @@ static size_t hstream_add_htx_data(struct hstream *hs, struct htx *htx, unsigned
|
||||
|
||||
TRACE_ENTER(HS_EV_HSTRM_ADD_DATA, hs);
|
||||
|
||||
if (hs->req_chunked) {
|
||||
if (hs->flags & HS_ST_OPT_CHUNK_RES) {
|
||||
buffer = common_chunk_resp;
|
||||
buffer_len = sizeof(common_chunk_resp);
|
||||
modulo = sizeof(common_chunk_resp);
|
||||
}
|
||||
else if (hs->req_random) {
|
||||
else if (hs->flags & HS_ST_OPT_RANDOM_RES) {
|
||||
buffer = random_resp;
|
||||
buffer_len = random_resp_len;
|
||||
modulo = random_resp_len;
|
||||
@ -615,7 +619,7 @@ static int hstream_build_http_resp(struct hstream *hs)
|
||||
int ret = 0;
|
||||
struct buffer *buf;
|
||||
struct htx *htx;
|
||||
unsigned int flags = HTX_SL_F_IS_RESP | HTX_SL_F_XFER_LEN | (!hs->req_chunked ? HTX_SL_F_CLEN : 0);
|
||||
unsigned int flags = HTX_SL_F_IS_RESP | HTX_SL_F_XFER_LEN | (!(hs->flags & HS_ST_OPT_CHUNK_RES) ? HTX_SL_F_CLEN : 0);
|
||||
struct htx_sl *sl;
|
||||
char *end;
|
||||
|
||||
@ -655,7 +659,7 @@ static int hstream_build_http_resp(struct hstream *hs)
|
||||
}
|
||||
}
|
||||
|
||||
if (!hs->req_chunked && (hs->ka & 1)) {
|
||||
if (!(hs->flags & HS_ST_OPT_CHUNK_RES) && (hs->ka & 1)) {
|
||||
char *end = ultoa_o(hs->req_size, trash.area, trash.size);
|
||||
if (!htx_add_header(htx, ist("Content-Length"), ist2(trash.area, end - trash.area))) {
|
||||
TRACE_ERROR("could not add content-length HTX header", HS_EV_HSTRM_RESP, hs);
|
||||
@ -663,7 +667,7 @@ static int hstream_build_http_resp(struct hstream *hs)
|
||||
}
|
||||
}
|
||||
|
||||
if (!hs->req_cache && !htx_add_header(htx, ist("Cache-control"), ist("no-cache"))) {
|
||||
if ((hs->flags & HS_ST_OPT_NO_CACHE) && !htx_add_header(htx, ist("Cache-control"), ist("no-cache"))) {
|
||||
TRACE_ERROR("could not add cache-control HTX header", HS_EV_HSTRM_RESP, hs);
|
||||
goto err;
|
||||
}
|
||||
@ -686,15 +690,11 @@ static int hstream_build_http_resp(struct hstream *hs)
|
||||
if (!end)
|
||||
goto err;
|
||||
trash.data = end - trash.area;
|
||||
if (!chunk_strcat(&trash, ", cache=")) {
|
||||
if (!chunk_strcat(&trash, ((hs->flags & HS_ST_OPT_NO_CACHE) ? ", cache=0" : ", cache=1"))) {
|
||||
TRACE_ERROR("could not build x-rsp HTX header", HS_EV_HSTRM_RESP, hs);
|
||||
goto err;
|
||||
}
|
||||
end = ultoa_o(hs->req_cache, trash.area + trash.data, trash.size - trash.data);
|
||||
if (!end)
|
||||
goto err;
|
||||
trash.data = end - trash.area;
|
||||
if (hs->req_chunked && !chunk_strcat(&trash, ", chunked,")) {
|
||||
if ((hs->flags & HS_ST_OPT_CHUNK_RES) && !chunk_strcat(&trash, ", chunked,")) {
|
||||
TRACE_ERROR("could not build x-rsp HTX header", HS_EV_HSTRM_RESP, hs);
|
||||
goto err;
|
||||
}
|
||||
@ -797,10 +797,16 @@ static void hstream_parse_uri(struct ist uri, struct hstream *hs)
|
||||
hs->res_wait = MS_TO_TICKS(result << mult);
|
||||
break;
|
||||
case 'c':
|
||||
hs->req_cache = result << mult;
|
||||
if (result < 1)
|
||||
hs->flags |= HS_ST_OPT_NO_CACHE;
|
||||
else
|
||||
hs->flags &= ~HS_ST_OPT_NO_CACHE;
|
||||
break;
|
||||
case 'A':
|
||||
hs->req_after_res = result;
|
||||
if (result > 0)
|
||||
hs->flags |= HS_ST_OPT_REQ_AFTER_RES;
|
||||
else
|
||||
hs->flags &= ~HS_ST_OPT_REQ_AFTER_RES;
|
||||
break;
|
||||
case 'C':
|
||||
hs->ka = (hs->ka & 4) | 2 | !result; // forced OFF
|
||||
@ -809,10 +815,16 @@ static void hstream_parse_uri(struct ist uri, struct hstream *hs)
|
||||
hs->ka = (hs->ka & 4) | 2 | !!result; // forced ON
|
||||
break;
|
||||
case 'k':
|
||||
hs->req_chunked = result;
|
||||
if (result > 0)
|
||||
hs->flags |= HS_ST_OPT_CHUNK_RES;
|
||||
else
|
||||
hs->flags &= ~HS_ST_OPT_CHUNK_RES;
|
||||
break;
|
||||
case 'R':
|
||||
hs->req_random = result;
|
||||
if (result > 0)
|
||||
hs->flags |= HS_ST_OPT_RANDOM_RES;
|
||||
else
|
||||
hs->flags &= ~HS_ST_OPT_RANDOM_RES;
|
||||
break;
|
||||
}
|
||||
arg = next;
|
||||
@ -858,11 +870,11 @@ static inline int hstream_sl_hdrs_htx_buf_snd(struct hstream *hs,
|
||||
/* Must be called before sending to determine if the body request must be
|
||||
* drained asap before sending. Return 1 if this is the case, 0 if not.
|
||||
* This is the case by default before sending the response except if
|
||||
* the contrary has been asked with ->req_after_res=0.
|
||||
* the contrary has been asked with flag HS_ST_OPT_REQ_AFTER_RES.
|
||||
* Return true if the body request has not been fully drained (->hs->req_body>0)
|
||||
* and if the response has been sent (hs->to_write=0 &&
|
||||
* htx_is_empty(htxbuf(&hs->res) or if it must not be drained after having
|
||||
* sent the response (->req_after_res=0) or
|
||||
* sent the response (HS_ST_OPT_REQ_AFTER_RES not set) or
|
||||
*/
|
||||
static inline int hstream_must_drain(struct hstream *hs)
|
||||
{
|
||||
@ -870,7 +882,7 @@ static inline int hstream_must_drain(struct hstream *hs)
|
||||
|
||||
TRACE_ENTER(HS_EV_PROCESS_HSTRM, hs);
|
||||
ret = !(hs->flags & HS_ST_CONN_ERROR) && hs->req_body > 0 &&
|
||||
((!hs->to_write && htx_is_empty(htxbuf(&hs->res))) || !hs->req_after_res);
|
||||
((!hs->to_write && htx_is_empty(htxbuf(&hs->res))) || !(hs->flags & HS_ST_OPT_REQ_AFTER_RES));
|
||||
TRACE_LEAVE(HS_EV_PROCESS_HSTRM, hs);
|
||||
|
||||
return ret;
|
||||
@ -881,7 +893,7 @@ static inline int hstream_is_fastfwd_supported(struct hstream *hs)
|
||||
return (!(global.tune.no_zero_copy_fwd & NO_ZERO_COPY_FWD) &&
|
||||
sc_ep_test(hs->sc, SE_FL_MAY_FASTFWD_CONS) &&
|
||||
!(hs->sc->sedesc->iobuf.flags & IOBUF_FL_NO_FF) &&
|
||||
!hs->req_chunked && hs->to_write);
|
||||
!(hs->flags & HS_ST_OPT_CHUNK_RES) && hs->to_write);
|
||||
}
|
||||
|
||||
/* haterm stream processing task */
|
||||
@ -949,7 +961,7 @@ static struct task *process_hstream(struct task *t, void *context, unsigned int
|
||||
}
|
||||
|
||||
if (hstream_must_drain(hs)) {
|
||||
/* The request must be drained before sending the response (hs->req_after_res=0).
|
||||
/* The request must be drained before sending the response (HS_ST_OPT_REQ_AFTER_RES not set).
|
||||
* The body will be drained upon next wakeup.
|
||||
*/
|
||||
TRACE_STATE("waking up task", HS_EV_HSTRM_IO_CB, hs);
|
||||
@ -969,7 +981,7 @@ static struct task *process_hstream(struct task *t, void *context, unsigned int
|
||||
goto err;
|
||||
|
||||
if (hstream_must_drain(hs)) {
|
||||
/* The request must be drained before sending the response (hs->req_after_res=0).
|
||||
/* The request must be drained before sending the response (HS_ST_OPT_REQ_AFTER_RES not set).
|
||||
* The body will be drained upon next wakeup.
|
||||
*/
|
||||
TRACE_STATE("waking up task", HS_EV_HSTRM_IO_CB, hs);
|
||||
@ -1035,7 +1047,7 @@ static struct task *process_hstream(struct task *t, void *context, unsigned int
|
||||
hstream_htx_buf_snd(conn, hs);
|
||||
|
||||
send_done:
|
||||
if (hs->req_body && hs->req_after_res && !hs->to_write) {
|
||||
if (hs->req_body && (hs->flags & HS_ST_OPT_REQ_AFTER_RES) && !hs->to_write) {
|
||||
/* Response sending has just complete. The body will be drained upon
|
||||
* next wakeup.
|
||||
*/
|
||||
@ -1101,15 +1113,11 @@ void *hstream_new(struct session *sess, struct stconn *sc, struct buffer *input)
|
||||
hs->flags = 0;
|
||||
|
||||
hs->ka = 0;
|
||||
hs->req_cache = 1;
|
||||
hs->req_size = 0;
|
||||
hs->req_body = 0;
|
||||
hs->req_code = 200;
|
||||
hs->res_wait = TICK_ETERNITY;
|
||||
hs->res_time = TICK_ETERNITY;
|
||||
hs->req_chunked = 0;
|
||||
hs->req_random = 0;
|
||||
hs->req_after_res = 0;
|
||||
hs->req_meth = HTTP_METH_OTHER;
|
||||
|
||||
if (sc_conn(sc)) {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user