mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2025-08-07 23:56:57 +02:00
BUG/MINOR: http-act: Properly generate 103 responses when several rules are used
When several "early-hint" rules are used, we try, as far as possible, to merge links into the same 103-early-hints response. However, it only works if there is no ACLs. If a "early-hint" rule is not executed an invalid response is generated. the EOH block or the start-line may be missing, depending on the rule order. To fix the bug, we use the transaction status code. It is unused at this stage. Thus, it is set to 103 when a 103-early-hints response is in progress. And it is reset when the response is forwarded. In addition, the response is forwarded if the next rule is an "early-hint" rule with an ACL. This way, the response is always valid. This patch must be backported as far as 2.2.
This commit is contained in:
parent
4c8e58def6
commit
4c3d3d2a68
@ -1348,7 +1348,7 @@ static enum act_parse_ret parse_http_auth(const char **args, int *orig_arg, stru
|
|||||||
static enum act_return http_action_early_hint(struct act_rule *rule, struct proxy *px,
|
static enum act_return http_action_early_hint(struct act_rule *rule, struct proxy *px,
|
||||||
struct session *sess, struct stream *s, int flags)
|
struct session *sess, struct stream *s, int flags)
|
||||||
{
|
{
|
||||||
struct act_rule *prev_rule, *next_rule;
|
struct act_rule *next_rule;
|
||||||
struct channel *res = &s->res;
|
struct channel *res = &s->res;
|
||||||
struct htx *htx = htx_from_buf(&res->buf);
|
struct htx *htx = htx_from_buf(&res->buf);
|
||||||
struct buffer *value = alloc_trash_chunk();
|
struct buffer *value = alloc_trash_chunk();
|
||||||
@ -1363,13 +1363,10 @@ static enum act_return http_action_early_hint(struct act_rule *rule, struct prox
|
|||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* get previous and next rules */
|
/* if there is no pending 103 response, start a new response. Otherwise,
|
||||||
prev_rule = LIST_PREV(&rule->list, typeof(rule), list);
|
* continue to add link to a previously started response
|
||||||
next_rule = LIST_NEXT(&rule->list, typeof(rule), list);
|
*/
|
||||||
|
if (s->txn->status != 103) {
|
||||||
/* if no previous rule or previous rule is not early-hint, start a new response. Otherwise,
|
|
||||||
* continue to add link to a previously started response */
|
|
||||||
if (&prev_rule->list == s->current_rule_list || prev_rule->action_ptr != http_action_early_hint) {
|
|
||||||
struct htx_sl *sl;
|
struct htx_sl *sl;
|
||||||
unsigned int flags = (HTX_SL_F_IS_RESP|HTX_SL_F_VER_11|
|
unsigned int flags = (HTX_SL_F_IS_RESP|HTX_SL_F_VER_11|
|
||||||
HTX_SL_F_XFER_LEN|HTX_SL_F_BODYLESS);
|
HTX_SL_F_XFER_LEN|HTX_SL_F_BODYLESS);
|
||||||
@ -1379,6 +1376,7 @@ static enum act_return http_action_early_hint(struct act_rule *rule, struct prox
|
|||||||
if (!sl)
|
if (!sl)
|
||||||
goto error;
|
goto error;
|
||||||
sl->info.res.status = 103;
|
sl->info.res.status = 103;
|
||||||
|
s->txn->status = 103;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Add the HTTP Early Hint HTTP 103 response heade */
|
/* Add the HTTP Early Hint HTTP 103 response heade */
|
||||||
@ -1386,18 +1384,16 @@ static enum act_return http_action_early_hint(struct act_rule *rule, struct prox
|
|||||||
if (!htx_add_header(htx, rule->arg.http.str, ist2(b_head(value), b_data(value))))
|
if (!htx_add_header(htx, rule->arg.http.str, ist2(b_head(value), b_data(value))))
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
/* if it is the last rule or the next one is not an early-hint, terminate the current
|
/* if it is the last rule or the next one is not an early-hint or an
|
||||||
* response. */
|
* conditional early-hint, terminate the current response.
|
||||||
if (&next_rule->list == s->current_rule_list || next_rule->action_ptr != http_action_early_hint) {
|
*/
|
||||||
if (!htx_add_endof(htx, HTX_BLK_EOH)) {
|
next_rule = LIST_NEXT(&rule->list, typeof(rule), list);
|
||||||
/* If an error occurred during an Early-hint rule,
|
if (&next_rule->list == s->current_rule_list || next_rule->action_ptr != http_action_early_hint || next_rule->cond) {
|
||||||
* remove the incomplete HTTP 103 response from the
|
if (!htx_add_endof(htx, HTX_BLK_EOH))
|
||||||
* buffer */
|
|
||||||
goto error;
|
goto error;
|
||||||
}
|
|
||||||
|
|
||||||
if (!http_forward_proxy_resp(s, 0))
|
if (!http_forward_proxy_resp(s, 0))
|
||||||
goto error;
|
goto error;
|
||||||
|
s->txn->status = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
leave:
|
leave:
|
||||||
@ -1409,6 +1405,7 @@ static enum act_return http_action_early_hint(struct act_rule *rule, struct prox
|
|||||||
* HTTP 103 response from the buffer */
|
* HTTP 103 response from the buffer */
|
||||||
channel_htx_truncate(res, htx);
|
channel_htx_truncate(res, htx);
|
||||||
ret = ACT_RET_ERR;
|
ret = ACT_RET_ERR;
|
||||||
|
s->txn->status = 0;
|
||||||
goto leave;
|
goto leave;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user