mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2025-08-09 00:27:08 +02:00
[MINOR] http: add http_remove_header2() to remove a header value.
Calling this function after http_find_header2() automatically deletes the current value of the header, and removes the header itself if the value is the only one. The context is automatically adjusted for a next call to http_find_header2() to return the next header. No other change nor test should be made on the transient context though.
This commit is contained in:
parent
116f91e7a5
commit
68085d8cfb
@ -84,7 +84,7 @@ void check_response_for_cacheability(struct session *t, struct buffer *rtr);
|
|||||||
int stats_check_uri_auth(struct session *t, struct proxy *backend);
|
int stats_check_uri_auth(struct session *t, struct proxy *backend);
|
||||||
void init_proto_http();
|
void init_proto_http();
|
||||||
int http_find_header2(const char *name, int len,
|
int http_find_header2(const char *name, int len,
|
||||||
const char *sol, struct hdr_idx *idx,
|
char *sol, struct hdr_idx *idx,
|
||||||
struct hdr_ctx *ctx);
|
struct hdr_ctx *ctx);
|
||||||
void http_sess_log(struct session *s);
|
void http_sess_log(struct session *s);
|
||||||
void perform_http_redirect(struct session *s, struct stream_interface *si);
|
void perform_http_redirect(struct session *s, struct stream_interface *si);
|
||||||
|
@ -300,13 +300,17 @@ struct http_txn {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/* This structure is used by http_find_header() to return values of headers.
|
/* This structure is used by http_find_header() to return values of headers.
|
||||||
* The header starts at <line>, the value at <line>+<val> for <vlen> bytes.
|
* The header starts at <line>, the value at <line>+<val> for <vlen> bytes, and
|
||||||
|
* sets <line>+<del> to point to the last delimitor (colon or comma) before
|
||||||
|
* this value. <prev> points to the index of the header whose next is this one.
|
||||||
*/
|
*/
|
||||||
struct hdr_ctx {
|
struct hdr_ctx {
|
||||||
const char *line;
|
char *line;
|
||||||
int idx;
|
int idx;
|
||||||
int val; /* relative to line */
|
int val; /* relative to line */
|
||||||
int vlen; /* relative to line+val */
|
int vlen; /* relative to line+val */
|
||||||
|
int del; /* relative to line */
|
||||||
|
int prev; /* index of previous header */
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* _TYPES_PROTO_HTTP_H */
|
#endif /* _TYPES_PROTO_HTTP_H */
|
||||||
|
@ -452,11 +452,11 @@ int http_header_match2(const char *hdr, const char *end,
|
|||||||
return val - hdr;
|
return val - hdr;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Find the end of the header value contained between <s> and <e>.
|
/* Find the end of the header value contained between <s> and <e>. See RFC2616,
|
||||||
* See RFC2616, par 2.2 for more information. Note that it requires
|
* par 2.2 for more information. Note that it requires a valid header to return
|
||||||
* a valid header to return a valid result.
|
* a valid result. This works for headers defined as comma-separated lists.
|
||||||
*/
|
*/
|
||||||
const char *find_hdr_value_end(const char *s, const char *e)
|
char *find_hdr_value_end(char *s, const char *e)
|
||||||
{
|
{
|
||||||
int quoted, qdpair;
|
int quoted, qdpair;
|
||||||
|
|
||||||
@ -476,29 +476,35 @@ const char *find_hdr_value_end(const char *s, const char *e)
|
|||||||
* structure holds everything necessary to use the header and find next
|
* structure holds everything necessary to use the header and find next
|
||||||
* occurrence. If its <idx> member is 0, the header is searched from the
|
* occurrence. If its <idx> member is 0, the header is searched from the
|
||||||
* beginning. Otherwise, the next occurrence is returned. The function returns
|
* beginning. Otherwise, the next occurrence is returned. The function returns
|
||||||
* 1 when it finds a value, and 0 when there is no more.
|
* 1 when it finds a value, and 0 when there is no more. It is designed to work
|
||||||
|
* with headers defined as comma-separated lists. As a special case, if ctx->val
|
||||||
|
* is NULL when searching for a new values of a header, the current header is
|
||||||
|
* rescanned. This allows rescanning after a header deletion.
|
||||||
*/
|
*/
|
||||||
int http_find_header2(const char *name, int len,
|
int http_find_header2(const char *name, int len,
|
||||||
const char *sol, struct hdr_idx *idx,
|
char *sol, struct hdr_idx *idx,
|
||||||
struct hdr_ctx *ctx)
|
struct hdr_ctx *ctx)
|
||||||
{
|
{
|
||||||
const char *eol, *sov;
|
char *eol, *sov;
|
||||||
int cur_idx;
|
int cur_idx, old_idx;
|
||||||
|
|
||||||
if (ctx->idx) {
|
cur_idx = ctx->idx;
|
||||||
|
if (cur_idx) {
|
||||||
/* We have previously returned a value, let's search
|
/* We have previously returned a value, let's search
|
||||||
* another one on the same line.
|
* another one on the same line.
|
||||||
*/
|
*/
|
||||||
cur_idx = ctx->idx;
|
|
||||||
sol = ctx->line;
|
sol = ctx->line;
|
||||||
sov = sol + ctx->val + ctx->vlen;
|
ctx->del = ctx->val + ctx->vlen;
|
||||||
|
sov = sol + ctx->del;
|
||||||
eol = sol + idx->v[cur_idx].len;
|
eol = sol + idx->v[cur_idx].len;
|
||||||
|
|
||||||
if (sov >= eol)
|
if (sov >= eol)
|
||||||
/* no more values in this header */
|
/* no more values in this header */
|
||||||
goto next_hdr;
|
goto next_hdr;
|
||||||
|
|
||||||
/* values remaining for this header, skip the comma */
|
/* values remaining for this header, skip the comma but save it
|
||||||
|
* for later use (eg: for header deletion).
|
||||||
|
*/
|
||||||
sov++;
|
sov++;
|
||||||
while (sov < eol && http_is_lws[(unsigned char)*sov])
|
while (sov < eol && http_is_lws[(unsigned char)*sov])
|
||||||
sov++;
|
sov++;
|
||||||
@ -508,8 +514,8 @@ int http_find_header2(const char *name, int len,
|
|||||||
|
|
||||||
/* first request for this header */
|
/* first request for this header */
|
||||||
sol += hdr_idx_first_pos(idx);
|
sol += hdr_idx_first_pos(idx);
|
||||||
|
old_idx = 0;
|
||||||
cur_idx = hdr_idx_first_idx(idx);
|
cur_idx = hdr_idx_first_idx(idx);
|
||||||
|
|
||||||
while (cur_idx) {
|
while (cur_idx) {
|
||||||
eol = sol + idx->v[cur_idx].len;
|
eol = sol + idx->v[cur_idx].len;
|
||||||
|
|
||||||
@ -524,12 +530,14 @@ int http_find_header2(const char *name, int len,
|
|||||||
if ((len < eol - sol) &&
|
if ((len < eol - sol) &&
|
||||||
(sol[len] == ':') &&
|
(sol[len] == ':') &&
|
||||||
(strncasecmp(sol, name, len) == 0)) {
|
(strncasecmp(sol, name, len) == 0)) {
|
||||||
|
ctx->del = len;
|
||||||
sov = sol + len + 1;
|
sov = sol + len + 1;
|
||||||
while (sov < eol && http_is_lws[(unsigned char)*sov])
|
while (sov < eol && http_is_lws[(unsigned char)*sov])
|
||||||
sov++;
|
sov++;
|
||||||
return_hdr:
|
|
||||||
ctx->line = sol;
|
ctx->line = sol;
|
||||||
|
ctx->prev = old_idx;
|
||||||
|
return_hdr:
|
||||||
ctx->idx = cur_idx;
|
ctx->idx = cur_idx;
|
||||||
ctx->val = sov - sol;
|
ctx->val = sov - sol;
|
||||||
|
|
||||||
@ -539,18 +547,69 @@ int http_find_header2(const char *name, int len,
|
|||||||
}
|
}
|
||||||
next_hdr:
|
next_hdr:
|
||||||
sol = eol + idx->v[cur_idx].cr + 1;
|
sol = eol + idx->v[cur_idx].cr + 1;
|
||||||
|
old_idx = cur_idx;
|
||||||
cur_idx = idx->v[cur_idx].next;
|
cur_idx = idx->v[cur_idx].next;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int http_find_header(const char *name,
|
int http_find_header(const char *name,
|
||||||
const char *sol, struct hdr_idx *idx,
|
char *sol, struct hdr_idx *idx,
|
||||||
struct hdr_ctx *ctx)
|
struct hdr_ctx *ctx)
|
||||||
{
|
{
|
||||||
return http_find_header2(name, strlen(name), sol, idx, ctx);
|
return http_find_header2(name, strlen(name), sol, idx, ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Remove one value of a header. This only works on a <ctx> returned by one of
|
||||||
|
* the http_find_header functions. The value is removed, as well as surrounding
|
||||||
|
* commas if any. If the removed value was alone, the whole header is removed.
|
||||||
|
* The ctx is always updated accordingly, as well as buffer <buf> and HTTP
|
||||||
|
* message <msg>. The new index is returned. If it is zero, it means there is
|
||||||
|
* no more header, so any processing may stop. The ctx is always left in a form
|
||||||
|
* that can be handled by http_find_header2() to find next occurrence.
|
||||||
|
*/
|
||||||
|
int http_remove_header2(struct http_msg *msg, struct buffer *buf,
|
||||||
|
struct hdr_idx *idx, struct hdr_ctx *ctx)
|
||||||
|
{
|
||||||
|
int cur_idx = ctx->idx;
|
||||||
|
char *sol = ctx->line;
|
||||||
|
struct hdr_idx_elem *hdr;
|
||||||
|
int delta, skip_comma;
|
||||||
|
|
||||||
|
if (!cur_idx)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
hdr = &idx->v[cur_idx];
|
||||||
|
if (sol[ctx->del] == ':' && ctx->val + ctx->vlen == hdr->len) {
|
||||||
|
/* This was the only value of the header, we must now remove it entirely. */
|
||||||
|
delta = buffer_replace2(buf, sol, sol + hdr->len + hdr->cr + 1, NULL, 0);
|
||||||
|
http_msg_move_end(msg, delta);
|
||||||
|
idx->used--;
|
||||||
|
hdr->len = 0; /* unused entry */
|
||||||
|
idx->v[ctx->prev].next = idx->v[ctx->idx].next;
|
||||||
|
ctx->idx = ctx->prev; /* walk back to the end of previous header */
|
||||||
|
ctx->line -= idx->v[ctx->idx].len + idx->v[cur_idx].cr + 1;
|
||||||
|
ctx->val = idx->v[ctx->idx].len; /* point to end of previous header */
|
||||||
|
ctx->vlen = 0;
|
||||||
|
return ctx->idx;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* This was not the only value of this header. We have to remove between
|
||||||
|
* ctx->del+1 and ctx->val+ctx->vlen+1 included. If it is the last entry
|
||||||
|
* of the list, we remove the last separator.
|
||||||
|
*/
|
||||||
|
|
||||||
|
skip_comma = (ctx->val + ctx->vlen == hdr->len) ? 0 : 1;
|
||||||
|
delta = buffer_replace2(buf, sol + ctx->del + skip_comma,
|
||||||
|
sol + ctx->val + ctx->vlen + skip_comma,
|
||||||
|
NULL, 0);
|
||||||
|
hdr->len += delta;
|
||||||
|
http_msg_move_end(msg, delta);
|
||||||
|
ctx->val = ctx->del;
|
||||||
|
ctx->vlen = 0;
|
||||||
|
return ctx->idx;
|
||||||
|
}
|
||||||
|
|
||||||
/* This function handles a server error at the stream interface level. The
|
/* This function handles a server error at the stream interface level. The
|
||||||
* stream interface is assumed to be already in a closed state. An optional
|
* stream interface is assumed to be already in a closed state. An optional
|
||||||
* message is copied into the input buffer, and an HTTP status code stored.
|
* message is copied into the input buffer, and an HTTP status code stored.
|
||||||
|
Loading…
Reference in New Issue
Block a user