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 <haproxy/buf-t.h>
|
||||
#include <haproxy/http-hdr-t.h>
|
||||
#include <haproxy/http_htx-t.h>
|
||||
#include <haproxy/proxy-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);
|
||||
|
||||
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_errormsg(const char *key, const struct ist msg, 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 */
|
||||
if (isteq(list[idx].n, ist("cookie"))) {
|
||||
list[idx].n.len = -1;
|
||||
|
||||
if (ck < 0)
|
||||
ck = idx;
|
||||
else
|
||||
list[lck].n.len = idx;
|
||||
|
||||
lck = idx;
|
||||
http_cookie_register(list, idx, &ck, &lck);
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -561,37 +554,8 @@ int h2_make_htx_request(struct http_hdr *list, struct htx *htx, unsigned int *ms
|
||||
* visited headers.
|
||||
*/
|
||||
if (ck >= 0) {
|
||||
uint32_t fs; // free space
|
||||
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)
|
||||
if (http_cookie_merge(htx, list, ck))
|
||||
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 */
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include <haproxy/global.h>
|
||||
#include <haproxy/h1.h>
|
||||
#include <haproxy/http.h>
|
||||
#include <haproxy/http-hdr.h>
|
||||
#include <haproxy/http_fetch.h>
|
||||
#include <haproxy/http_htx.h>
|
||||
#include <haproxy/htx.h>
|
||||
@ -1799,6 +1800,83 @@ int http_scheme_based_normalize(struct htx *htx)
|
||||
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 */
|
||||
static int proxy_parse_errorloc(char **args, int section, struct proxy *curpx,
|
||||
const struct proxy *defpx, const char *file, int line,
|
||||
|
Loading…
Reference in New Issue
Block a user