mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2025-08-06 07:07:04 +02:00
MINOR: mux-h1: Add a flag to ignore the request payload
There was a flag to skip the response payload on output, if any, by stating it is bodyless. It is used for responses to HEAD requests or for 204/304 responses. This allow rewrites during analysis. For instance a HEAD request can be rewrite to a GET request for any reason (ie, a server not supporting HEAD requests). In this case, the server will send a response with a payload. On frontend side, the payload will be skipped and a valid response (without payload) will be sent to the client. With this patch we introduce the corresponding flag for the request. It will be used to skip the request payload. In addition, when payload must be skipped for a request or a response, The zero-copy data forwarding is now disabled.
This commit is contained in:
parent
45a45c917a
commit
8e55d29109
@ -107,6 +107,8 @@ static forceinline char *h1c_show_flags(char *buf, size_t len, const char *delim
|
||||
#define H1S_F_HAVE_CLEN 0x00010000 /* Set during output process to know C*L header was found or generated */
|
||||
#define H1S_F_HAVE_CHNK 0x00020000 /* Set during output process to know "T-E; chunk" header was found or generated */
|
||||
|
||||
#define H1S_F_BODYLESS_REQ 0x00040000 /* Bodyless request message */
|
||||
|
||||
/* This function is used to report flags in debugging tools. Please reflect
|
||||
* below any single-bit flag addition above in the same order via the
|
||||
* __APPEND_FLAG macro. The new end of the buffer is returned.
|
||||
@ -122,7 +124,7 @@ static forceinline char *h1s_show_flags(char *buf, size_t len, const char *delim
|
||||
_(H1S_F_NOT_FIRST, _(H1S_F_BODYLESS_RESP,
|
||||
_(H1S_F_INTERNAL_ERROR, _(H1S_F_NOT_IMPL_ERROR, _(H1S_F_PARSING_ERROR, _(H1S_F_PROCESSING_ERROR,
|
||||
_(H1S_F_HAVE_SRV_NAME, _(H1S_F_HAVE_O_CONN, _(H1S_F_HAVE_WS_KEY,
|
||||
_(H1S_F_HAVE_CLEN, _(H1S_F_HAVE_CHNK)))))))))))))))));
|
||||
_(H1S_F_HAVE_CLEN, _(H1S_F_HAVE_CHNK, _(H1S_F_BODYLESS_REQ))))))))))))))))));
|
||||
/* epilogue */
|
||||
_(~0U);
|
||||
return buf;
|
||||
|
26
src/mux_h1.c
26
src/mux_h1.c
@ -2797,7 +2797,8 @@ static size_t h1_make_data(struct h1s *h1s, struct h1m *h1m, struct buffer *buf,
|
||||
* end-to-end. This is the situation that happens all the time with
|
||||
* large files.
|
||||
*/
|
||||
if ((!(h1m->flags & H1_MF_RESP) || !(h1s->flags & H1S_F_BODYLESS_RESP)) &&
|
||||
if (((!(h1m->flags & H1_MF_RESP) && !(h1s->flags & H1S_F_BODYLESS_REQ)) ||
|
||||
((h1m->flags & H1_MF_RESP) && !(h1s->flags & H1S_F_BODYLESS_RESP))) &&
|
||||
!b_data(&h1c->obuf) &&
|
||||
(!(h1m->flags & H1_MF_CHNK) || ((h1m->flags & H1_MF_CHNK) && (!h1m->curr_len || count == h1m->curr_len))) &&
|
||||
htx_nbblks(htx) == 1 &&
|
||||
@ -2924,8 +2925,9 @@ static size_t h1_make_data(struct h1s *h1s, struct h1m *h1m, struct buffer *buf,
|
||||
last_data = 1;
|
||||
}
|
||||
|
||||
if ((h1m->flags & H1_MF_RESP) && (h1s->flags & H1S_F_BODYLESS_RESP)) {
|
||||
TRACE_PROTO("Skip data for bodyless response", H1_EV_TX_DATA|H1_EV_TX_BODY, h1c->conn, h1s, htx);
|
||||
if ((!(h1m->flags & H1_MF_RESP) && (h1s->flags & H1S_F_BODYLESS_REQ)) ||
|
||||
((h1m->flags & H1_MF_RESP) && (h1s->flags & H1S_F_BODYLESS_RESP))) {
|
||||
TRACE_PROTO("Skip data for bodyless message", H1_EV_TX_DATA|H1_EV_TX_BODY, h1c->conn, h1s, htx);
|
||||
goto nextblk;
|
||||
}
|
||||
|
||||
@ -2996,7 +2998,8 @@ static size_t h1_make_data(struct h1s *h1s, struct h1m *h1m, struct buffer *buf,
|
||||
|
||||
}
|
||||
else if (type == HTX_BLK_EOT || type == HTX_BLK_TLR) {
|
||||
if ((h1m->flags & H1_MF_RESP) && (h1s->flags & H1S_F_BODYLESS_RESP)) {
|
||||
if ((!(h1m->flags & H1_MF_RESP) && (h1s->flags & H1S_F_BODYLESS_REQ)) ||
|
||||
((h1m->flags & H1_MF_RESP) && (h1s->flags & H1S_F_BODYLESS_RESP))) {
|
||||
/* Do nothing the payload must be skipped
|
||||
* because it is a bodyless response
|
||||
*/
|
||||
@ -3196,7 +3199,9 @@ static size_t h1_make_trailers(struct h1s *h1s, struct h1m *h1m, struct htx *htx
|
||||
if (sz > count)
|
||||
goto error;
|
||||
|
||||
if (!(h1m->flags & H1_MF_CHNK) || ((h1m->flags & H1_MF_RESP) && (h1s->flags & H1S_F_BODYLESS_RESP)))
|
||||
if (!(h1m->flags & H1_MF_CHNK) ||
|
||||
(!(h1m->flags & H1_MF_RESP) && (h1s->flags & H1S_F_BODYLESS_REQ)) ||
|
||||
((h1m->flags & H1_MF_RESP) && (h1s->flags & H1S_F_BODYLESS_RESP)))
|
||||
goto nextblk;
|
||||
|
||||
n = htx_get_blk_name(htx, blk);
|
||||
@ -3209,7 +3214,9 @@ static size_t h1_make_trailers(struct h1s *h1s, struct h1m *h1m, struct htx *htx
|
||||
goto full;
|
||||
}
|
||||
else if (type == HTX_BLK_EOT) {
|
||||
if (!(h1m->flags & H1_MF_CHNK) || ((h1m->flags & H1_MF_RESP) && (h1s->flags & H1S_F_BODYLESS_RESP))) {
|
||||
if (!(h1m->flags & H1_MF_CHNK) ||
|
||||
(!(h1m->flags & H1_MF_RESP) && (h1s->flags & H1S_F_BODYLESS_REQ)) ||
|
||||
((h1m->flags & H1_MF_RESP) && (h1s->flags & H1S_F_BODYLESS_RESP))) {
|
||||
TRACE_PROTO((!(h1m->flags & H1_MF_RESP) ? "H1 request trailers skipped" : "H1 response trailers skipped"),
|
||||
H1_EV_TX_DATA|H1_EV_TX_TLRS, h1c->conn, h1s);
|
||||
}
|
||||
@ -4592,6 +4599,13 @@ static size_t h1_nego_ff(struct stconn *sc, struct buffer *input, size_t count,
|
||||
goto out;
|
||||
}
|
||||
|
||||
if ((!(h1m->flags & H1_MF_RESP) && (h1s->flags & H1S_F_BODYLESS_REQ)) ||
|
||||
((h1m->flags & H1_MF_RESP) && (h1s->flags & H1S_F_BODYLESS_RESP))) {
|
||||
TRACE_STATE("Bodyless message, disable fastfwd", H1_EV_STRM_SEND|H1_EV_STRM_ERR, h1c->conn, h1s);
|
||||
h1s->sd->iobuf.flags |= IOBUF_FL_NO_FF;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (h1m->flags & H1_MF_CLEN) {
|
||||
if ((flags & NEGO_FF_FL_EXACT_SIZE) && count > h1m->curr_len) {
|
||||
TRACE_ERROR("more payload than announced", H1_EV_STRM_SEND|H1_EV_STRM_ERR, h1c->conn, h1s);
|
||||
|
Loading…
Reference in New Issue
Block a user