From: Maxime Henrion Date: Fri, 26 Jun 2026 20:43:12 +0000 (-0400) Subject: MINOR: http: factor 103 emission into start/end helpers X-Git-Url: http://git.kaiwu.me/%7Bsubstring-before(@doc,%20'.xml')%7D.html?a=commitdiff_plain;h=7f3c30d96c3b5f94750b2f96a810f34feef469de;p=haproxy.git MINOR: http: factor 103 emission into start/end helpers Pull the 103 emission code out of http_action_early_hint() and split it into http_early_hint_start() (open the response and return the htx) and http_early_hint_end() (close with EOH and forward). The split shape lets callers add their own Link headers in between, which is what the HTTP cache will need when it gets support for sending 103 Early Hints from cached responses. --- diff --git a/include/haproxy/http_ana.h b/include/haproxy/http_ana.h index 6215c50cc..4dd80e647 100644 --- a/include/haproxy/http_ana.h +++ b/include/haproxy/http_ana.h @@ -58,6 +58,8 @@ struct http_reply *http_error_message(struct stream *s); int http_reply_to_htx(struct stream *s, struct htx *htx, struct http_reply *reply); int http_reply_message(struct stream *s, struct http_reply *reply); int http_forward_proxy_resp(struct stream *s, int final); +struct htx *http_early_hint_start(struct stream *s); +int http_early_hint_end(struct stream *s); struct http_txn *http_create_txn(struct stream *s); void http_destroy_txn(struct stream *s); diff --git a/src/http_act.c b/src/http_act.c index 7b6914909..bf0d9a47c 100644 --- a/src/http_act.c +++ b/src/http_act.c @@ -1370,21 +1370,8 @@ static enum act_return http_action_early_hint(struct act_rule *rule, struct prox goto error; } - /* if there is no pending 103 response, start a new response. Otherwise, - * continue to add link to a previously started response - */ - if (s->txn.http->status != 103) { - struct htx_sl *sl; - unsigned int flags = (HTX_SL_F_IS_RESP|HTX_SL_F_VER_11| - HTX_SL_F_XFER_LEN|HTX_SL_F_BODYLESS); - - sl = htx_add_stline(htx, HTX_BLK_RES_SL, flags, - ist("HTTP/1.1"), ist("103"), ist("Early Hints")); - if (!sl) - goto error; - sl->info.res.status = 103; - s->txn.http->status = 103; - } + if (!http_early_hint_start(s)) + goto error; /* Add the HTTP Early Hint HTTP 103 response header */ value->data = build_logline(s, b_tail(value), b_room(value), &rule->arg.http.fmt); @@ -1396,11 +1383,8 @@ static enum act_return http_action_early_hint(struct act_rule *rule, struct prox */ next_rule = LIST_NEXT(&rule->list, typeof(rule), list); if (&next_rule->list == s->current_rule_list || next_rule->action_ptr != http_action_early_hint || next_rule->cond) { - if (!htx_add_endof(htx, HTX_BLK_EOH)) - goto error; - if (!http_forward_proxy_resp(s, 0)) + if (!http_early_hint_end(s)) goto error; - s->txn.http->status = 0; } leave: diff --git a/src/http_ana.c b/src/http_ana.c index 4806afd65..749f7919e 100644 --- a/src/http_ana.c +++ b/src/http_ana.c @@ -4765,6 +4765,47 @@ int http_forward_proxy_resp(struct stream *s, int final) return 1; } +/* + * Start a 103 Early Hints response in the response buffer if not already in + * progress (txn->status != 103). The caller is responsible for skipping this + * call for HTTP/1.0 clients. Returns the htx to which the caller can add Link + * headers, or NULL on error. + */ +struct htx *http_early_hint_start(struct stream *s) +{ + struct htx *htx = htx_from_buf(&s->res.buf); + + if (s->txn.http->status != 103) { + struct htx_sl *sl; + unsigned int flags = (HTX_SL_F_IS_RESP|HTX_SL_F_VER_11| + HTX_SL_F_XFER_LEN|HTX_SL_F_BODYLESS); + + sl = htx_add_stline(htx, HTX_BLK_RES_SL, flags, + ist("HTTP/1.1"), ist("103"), ist("Early Hints")); + if (!sl) + return NULL; + sl->info.res.status = 103; + s->txn.http->status = 103; + } + return htx; +} + +/* + * Finalize a 103 Early Hints response. Returns 1 on success, 0 on error + * (caller is responsible for truncating the response buffer on failure). + */ +int http_early_hint_end(struct stream *s) +{ + struct htx *htx = htxbuf(&s->res.buf); + + if (!htx_add_endof(htx, HTX_BLK_EOH)) + return 0; + if (!http_forward_proxy_resp(s, 0)) + return 0; + s->txn.http->status = 0; + return 1; +} + void http_server_error(struct stream *s, struct stconn *sc, int err, int finst, struct http_reply *msg) {