mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2026-01-30 22:41:55 +01:00
MEDIUM: mux-h2: make h2_process_demux() capable of processing responses as well
The function now calls h2c_bck_handle_headers() or h2c_frt_handle_headers() depending on the connection's side. The former doesn't create a new stream but feeds an existing one. At this point it's possible to forward an H2 request to a backend server and retrieve the response headers.
This commit is contained in:
parent
c3e18f3448
commit
c12f38fe32
68
src/mux_h2.c
68
src/mux_h2.c
@ -1833,6 +1833,69 @@ static struct h2s *h2c_frt_handle_headers(struct h2c *h2c, struct h2s *h2s)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* processes a HEADERS frame. Returns h2s on success or NULL on missing data.
|
||||
* It may return an error in h2c or h2s. Described in RFC7540#6.2. Most of the
|
||||
* errors here are reported as connection errors since it's impossible to
|
||||
* recover from such errors after the compression context has been altered.
|
||||
*/
|
||||
static struct h2s *h2c_bck_handle_headers(struct h2c *h2c, struct h2s *h2s)
|
||||
{
|
||||
int error;
|
||||
|
||||
if (!h2c->dfl) {
|
||||
error = H2_ERR_PROTOCOL_ERROR; // empty headers frame!
|
||||
sess_log(h2c->conn->owner);
|
||||
goto strm_err;
|
||||
}
|
||||
|
||||
if (!b_size(&h2c->dbuf))
|
||||
return NULL; // empty buffer
|
||||
|
||||
if (b_data(&h2c->dbuf) < h2c->dfl && !b_full(&h2c->dbuf))
|
||||
return NULL; // incomplete frame
|
||||
|
||||
if (h2c->flags & H2_CF_DEM_TOOMANY)
|
||||
return 0; // too many cs still present
|
||||
|
||||
if (h2c->dff & H2_F_HEADERS_END_STREAM) {
|
||||
h2s->flags |= H2_SF_ES_RCVD;
|
||||
h2s->cs->flags |= CS_FL_REOS;
|
||||
}
|
||||
|
||||
if (!h2s_decode_headers(h2s))
|
||||
return NULL;
|
||||
|
||||
if (h2c->st0 >= H2_CS_ERROR)
|
||||
return NULL;
|
||||
|
||||
if (h2s->st >= H2_SS_ERROR) {
|
||||
/* stream error : send RST_STREAM */
|
||||
h2c->st0 = H2_CS_FRAME_E;
|
||||
}
|
||||
|
||||
if (h2s->cs->flags & CS_FL_ERROR && h2s->st < H2_SS_ERROR)
|
||||
h2s->st = H2_SS_ERROR;
|
||||
else if (h2s->cs->flags & CS_FL_REOS && h2s->st == H2_SS_OPEN)
|
||||
h2s->st = H2_SS_HREM;
|
||||
else if (h2s->cs->flags & CS_FL_REOS && h2s->st == H2_SS_HLOC)
|
||||
h2s_close(h2s);
|
||||
|
||||
return h2s;
|
||||
|
||||
conn_err:
|
||||
h2c_error(h2c, error);
|
||||
return NULL;
|
||||
|
||||
strm_err:
|
||||
if (h2s) {
|
||||
h2s_error(h2s, error);
|
||||
h2c->st0 = H2_CS_FRAME_E;
|
||||
}
|
||||
else
|
||||
h2c_error(h2c, error);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* processes a DATA frame. Returns > 0 on success or zero on missing data.
|
||||
* It may return an error in h2c or h2s. Described in RFC7540#6.1.
|
||||
*/
|
||||
@ -2173,7 +2236,10 @@ static void h2_process_demux(struct h2c *h2c)
|
||||
|
||||
case H2_FT_HEADERS:
|
||||
if (h2c->st0 == H2_CS_FRAME_P) {
|
||||
tmp_h2s = h2c_frt_handle_headers(h2c, h2s);
|
||||
if (h2c->flags & H2_CF_IS_BACK)
|
||||
tmp_h2s = h2c_bck_handle_headers(h2c, h2s);
|
||||
else
|
||||
tmp_h2s = h2c_frt_handle_headers(h2c, h2s);
|
||||
if (tmp_h2s) {
|
||||
h2s = tmp_h2s;
|
||||
ret = 1;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user