mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2025-08-06 23:27:04 +02:00
REORG: h2: extract cookies concat function in http_htx
As specified by RFC 7540, multiple cookie headers are merged in a single entry before passing it to a HTTP/1.1 connection. This step is implemented during headers parsing in h2 module. Extract this code in the generic http_htx module. This will allow to reuse it quickly for HTTP/3 implementation which has the same requirement for cookie headers.
This commit is contained in:
parent
704675656b
commit
2c5a7ee333
@ -25,6 +25,7 @@
|
|||||||
|
|
||||||
#include <import/ist.h>
|
#include <import/ist.h>
|
||||||
#include <haproxy/buf-t.h>
|
#include <haproxy/buf-t.h>
|
||||||
|
#include <haproxy/http-hdr-t.h>
|
||||||
#include <haproxy/http_htx-t.h>
|
#include <haproxy/http_htx-t.h>
|
||||||
#include <haproxy/proxy-t.h>
|
#include <haproxy/proxy-t.h>
|
||||||
#include <haproxy/regex-t.h>
|
#include <haproxy/regex-t.h>
|
||||||
@ -68,6 +69,9 @@ struct http_reply *http_parse_http_reply(const char **args, int *orig_arg, struc
|
|||||||
|
|
||||||
int http_scheme_based_normalize(struct htx *htx);
|
int http_scheme_based_normalize(struct htx *htx);
|
||||||
|
|
||||||
|
void http_cookie_register(struct http_hdr *list, int idx, int *first, int *last);
|
||||||
|
int http_cookie_merge(struct htx *htx, struct http_hdr *list, int first);
|
||||||
|
|
||||||
struct buffer *http_load_errorfile(const char *file, char **errmsg);
|
struct buffer *http_load_errorfile(const char *file, char **errmsg);
|
||||||
struct buffer *http_load_errormsg(const char *key, const struct ist msg, char **errmsg);
|
struct buffer *http_load_errormsg(const char *key, const struct ist msg, char **errmsg);
|
||||||
struct buffer *http_parse_errorfile(int status, const char *file, char **errmsg);
|
struct buffer *http_parse_errorfile(int status, const char *file, char **errmsg);
|
||||||
|
40
src/h2.c
40
src/h2.c
@ -501,14 +501,7 @@ int h2_make_htx_request(struct http_hdr *list, struct htx *htx, unsigned int *ms
|
|||||||
|
|
||||||
/* cookie requires special processing at the end */
|
/* cookie requires special processing at the end */
|
||||||
if (isteq(list[idx].n, ist("cookie"))) {
|
if (isteq(list[idx].n, ist("cookie"))) {
|
||||||
list[idx].n.len = -1;
|
http_cookie_register(list, idx, &ck, &lck);
|
||||||
|
|
||||||
if (ck < 0)
|
|
||||||
ck = idx;
|
|
||||||
else
|
|
||||||
list[lck].n.len = idx;
|
|
||||||
|
|
||||||
lck = idx;
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -561,37 +554,8 @@ int h2_make_htx_request(struct http_hdr *list, struct htx *htx, unsigned int *ms
|
|||||||
* visited headers.
|
* visited headers.
|
||||||
*/
|
*/
|
||||||
if (ck >= 0) {
|
if (ck >= 0) {
|
||||||
uint32_t fs; // free space
|
if (http_cookie_merge(htx, list, ck))
|
||||||
uint32_t bs; // block size
|
|
||||||
uint32_t vl; // value len
|
|
||||||
uint32_t tl; // total length
|
|
||||||
struct htx_blk *blk;
|
|
||||||
|
|
||||||
blk = htx_add_header(htx, ist("cookie"), list[ck].v);
|
|
||||||
if (!blk)
|
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
tl = list[ck].v.len;
|
|
||||||
fs = htx_free_data_space(htx);
|
|
||||||
bs = htx_get_blksz(blk);
|
|
||||||
|
|
||||||
/* for each extra cookie, we'll extend the cookie's value and
|
|
||||||
* insert "; " before the new value.
|
|
||||||
*/
|
|
||||||
fs += tl; // first one is already counted
|
|
||||||
while ((ck = list[ck].n.len) >= 0) {
|
|
||||||
vl = list[ck].v.len;
|
|
||||||
tl += vl + 2;
|
|
||||||
if (tl > fs)
|
|
||||||
goto fail;
|
|
||||||
|
|
||||||
htx_change_blk_value_len(htx, blk, tl);
|
|
||||||
*(char *)(htx_get_blk_ptr(htx, blk) + bs + 0) = ';';
|
|
||||||
*(char *)(htx_get_blk_ptr(htx, blk) + bs + 1) = ' ';
|
|
||||||
memcpy(htx_get_blk_ptr(htx, blk) + bs + 2, list[ck].v.ptr, vl);
|
|
||||||
bs += vl + 2;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* now send the end of headers marker */
|
/* now send the end of headers marker */
|
||||||
|
@ -21,6 +21,7 @@
|
|||||||
#include <haproxy/global.h>
|
#include <haproxy/global.h>
|
||||||
#include <haproxy/h1.h>
|
#include <haproxy/h1.h>
|
||||||
#include <haproxy/http.h>
|
#include <haproxy/http.h>
|
||||||
|
#include <haproxy/http-hdr.h>
|
||||||
#include <haproxy/http_fetch.h>
|
#include <haproxy/http_fetch.h>
|
||||||
#include <haproxy/http_htx.h>
|
#include <haproxy/http_htx.h>
|
||||||
#include <haproxy/htx.h>
|
#include <haproxy/htx.h>
|
||||||
@ -1799,6 +1800,83 @@ int http_scheme_based_normalize(struct htx *htx)
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* First step function to merge multiple cookie headers in a single entry.
|
||||||
|
*
|
||||||
|
* Use it for each cookie header at <idx> index over HTTP headers in <list>.
|
||||||
|
* <first> and <last> are state variables used internally and must be
|
||||||
|
* initialized to -1 before the first invocation.
|
||||||
|
*/
|
||||||
|
void http_cookie_register(struct http_hdr *list, int idx, int *first, int *last)
|
||||||
|
{
|
||||||
|
/* Build a linked list of cookie headers. Use header length to point to
|
||||||
|
* the next one. The last entry will contains -1.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Mark the current end of cookie linked list. */
|
||||||
|
list[idx].n.len = -1;
|
||||||
|
if (*first < 0) {
|
||||||
|
/* Save first found cookie for http_cookie_merge call. */
|
||||||
|
*first = idx;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
/* Update linked list of cookies. */
|
||||||
|
list[*last].n.len = idx;
|
||||||
|
}
|
||||||
|
|
||||||
|
*last = idx;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Second step to merge multiple cookie headers in a single entry.
|
||||||
|
*
|
||||||
|
* Use it when looping over HTTP headers is done and <htx> message is built.
|
||||||
|
* This will concatenate each cookie headers present from <list> directly into
|
||||||
|
* <htx> message. <first> is reused from previous http_cookie_register
|
||||||
|
* invocation.
|
||||||
|
*
|
||||||
|
* Returns 0 on success else non-zero.
|
||||||
|
*/
|
||||||
|
int http_cookie_merge(struct htx *htx, struct http_hdr *list, int first)
|
||||||
|
{
|
||||||
|
uint32_t fs; /* free space */
|
||||||
|
uint32_t bs; /* block size */
|
||||||
|
uint32_t vl; /* value len */
|
||||||
|
uint32_t tl; /* total length */
|
||||||
|
struct htx_blk *blk;
|
||||||
|
|
||||||
|
if (first < 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
blk = htx_add_header(htx, ist("cookie"), list[first].v);
|
||||||
|
if (!blk)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
tl = list[first].v.len;
|
||||||
|
fs = htx_free_data_space(htx);
|
||||||
|
bs = htx_get_blksz(blk);
|
||||||
|
|
||||||
|
/* for each extra cookie, we'll extend the cookie's value and insert
|
||||||
|
* ";" before the new value.
|
||||||
|
*/
|
||||||
|
fs += tl; /* first one is already counted */
|
||||||
|
|
||||||
|
/* Loop over cookies linked list built from http_cookie_register. */
|
||||||
|
while ((first = list[first].n.len) >= 0) {
|
||||||
|
vl = list[first].v.len;
|
||||||
|
tl += vl + 2;
|
||||||
|
if (tl > fs)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
htx_change_blk_value_len(htx, blk, tl);
|
||||||
|
*(char *)(htx_get_blk_ptr(htx, blk) + bs + 0) = ';';
|
||||||
|
*(char *)(htx_get_blk_ptr(htx, blk) + bs + 1) = ' ';
|
||||||
|
memcpy(htx_get_blk_ptr(htx, blk) + bs + 2,
|
||||||
|
list[first].v.ptr, vl);
|
||||||
|
bs += vl + 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Parses the "errorloc[302|303]" proxy keyword */
|
/* Parses the "errorloc[302|303]" proxy keyword */
|
||||||
static int proxy_parse_errorloc(char **args, int section, struct proxy *curpx,
|
static int proxy_parse_errorloc(char **args, int section, struct proxy *curpx,
|
||||||
const struct proxy *defpx, const char *file, int line,
|
const struct proxy *defpx, const char *file, int line,
|
||||||
|
Loading…
Reference in New Issue
Block a user