mirror of
https://git.haproxy.org/git/haproxy.git/
synced 2025-09-22 14:21:25 +02:00
MINOR: http-rules: Make replace-header and replace-value custom actions
Now, these actions use their own dedicated function and are no longer handled "in place" during the HTTP rules evaluation. Thus the action names ACT_HTTP_REPLACE_HDR and ACT_HTTP_REPLACE_VAL are removed. The action type is now set to 0 to evaluate the whole header or to 1 to evaluate every comma-delimited values. The function http_transform_header_str() is renamed to http_replace_hdrs() to be more explicit and the function http_transform_header() is removed. In fact, this last one is now more or less the new action function. The lua code has been updated accordingly to use http_replace_hdrs().
This commit is contained in:
parent
2c22a6923a
commit
92d34fe38d
@ -40,8 +40,7 @@ int http_process_res_common(struct stream *s, struct channel *rep, int an_bit, s
|
|||||||
int http_request_forward_body(struct stream *s, struct channel *req, int an_bit);
|
int http_request_forward_body(struct stream *s, struct channel *req, int an_bit);
|
||||||
int http_response_forward_body(struct stream *s, struct channel *res, int an_bit);
|
int http_response_forward_body(struct stream *s, struct channel *res, int an_bit);
|
||||||
int http_apply_redirect_rule(struct redirect_rule *rule, struct stream *s, struct http_txn *txn);
|
int http_apply_redirect_rule(struct redirect_rule *rule, struct stream *s, struct http_txn *txn);
|
||||||
int http_transform_header_str(struct stream* s, struct channel *chn, struct htx *htx,
|
int http_replace_hdrs(struct stream* s, struct htx *htx, struct ist name, const char *str, struct my_regex *re, int full);
|
||||||
struct ist name, const char *str, struct my_regex *re, int action);
|
|
||||||
int http_req_replace_stline(int action, const char *replace, int len,
|
int http_req_replace_stline(int action, const char *replace, int len,
|
||||||
struct proxy *px, struct stream *s);
|
struct proxy *px, struct stream *s);
|
||||||
int http_res_set_status(unsigned int status, struct ist reason, struct stream *s);
|
int http_res_set_status(unsigned int status, struct ist reason, struct stream *s);
|
||||||
|
@ -79,8 +79,6 @@ enum act_name {
|
|||||||
|
|
||||||
/* common http actions .*/
|
/* common http actions .*/
|
||||||
ACT_HTTP_ADD_HDR,
|
ACT_HTTP_ADD_HDR,
|
||||||
ACT_HTTP_REPLACE_HDR,
|
|
||||||
ACT_HTTP_REPLACE_VAL,
|
|
||||||
ACT_HTTP_SET_HDR,
|
ACT_HTTP_SET_HDR,
|
||||||
ACT_HTTP_DEL_HDR,
|
ACT_HTTP_DEL_HDR,
|
||||||
ACT_HTTP_REDIR,
|
ACT_HTTP_REDIR,
|
||||||
|
12
src/hlua.c
12
src/hlua.c
@ -4795,7 +4795,7 @@ __LJMP static int hlua_http_res_get_headers(lua_State *L)
|
|||||||
* 4 following functions.
|
* 4 following functions.
|
||||||
*/
|
*/
|
||||||
__LJMP static inline int hlua_http_rep_hdr(lua_State *L, struct hlua_txn *htxn,
|
__LJMP static inline int hlua_http_rep_hdr(lua_State *L, struct hlua_txn *htxn,
|
||||||
struct http_msg *msg, int action)
|
struct http_msg *msg, int full)
|
||||||
{
|
{
|
||||||
size_t name_len;
|
size_t name_len;
|
||||||
const char *name = MAY_LJMP(luaL_checklstring(L, 2, &name_len));
|
const char *name = MAY_LJMP(luaL_checklstring(L, 2, &name_len));
|
||||||
@ -4808,7 +4808,7 @@ __LJMP static inline int hlua_http_rep_hdr(lua_State *L, struct hlua_txn *htxn,
|
|||||||
WILL_LJMP(luaL_argerror(L, 3, "invalid regex"));
|
WILL_LJMP(luaL_argerror(L, 3, "invalid regex"));
|
||||||
|
|
||||||
htx = htxbuf(&msg->chn->buf);
|
htx = htxbuf(&msg->chn->buf);
|
||||||
http_transform_header_str(htxn->s, msg->chn, htx, ist2(name, name_len), value, re, action);
|
http_replace_hdrs(htxn->s, htx, ist2(name, name_len), value, re, full);
|
||||||
regex_free(re);
|
regex_free(re);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -4823,7 +4823,7 @@ __LJMP static int hlua_http_req_rep_hdr(lua_State *L)
|
|||||||
if (htxn->dir != SMP_OPT_DIR_REQ || !(htxn->flags & HLUA_TXN_HTTP_RDY))
|
if (htxn->dir != SMP_OPT_DIR_REQ || !(htxn->flags & HLUA_TXN_HTTP_RDY))
|
||||||
WILL_LJMP(lua_error(L));
|
WILL_LJMP(lua_error(L));
|
||||||
|
|
||||||
return MAY_LJMP(hlua_http_rep_hdr(L, htxn, &htxn->s->txn->req, ACT_HTTP_REPLACE_HDR));
|
return MAY_LJMP(hlua_http_rep_hdr(L, htxn, &htxn->s->txn->req, 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
__LJMP static int hlua_http_res_rep_hdr(lua_State *L)
|
__LJMP static int hlua_http_res_rep_hdr(lua_State *L)
|
||||||
@ -4836,7 +4836,7 @@ __LJMP static int hlua_http_res_rep_hdr(lua_State *L)
|
|||||||
if (htxn->dir != SMP_OPT_DIR_RES || !(htxn->flags & HLUA_TXN_HTTP_RDY))
|
if (htxn->dir != SMP_OPT_DIR_RES || !(htxn->flags & HLUA_TXN_HTTP_RDY))
|
||||||
WILL_LJMP(lua_error(L));
|
WILL_LJMP(lua_error(L));
|
||||||
|
|
||||||
return MAY_LJMP(hlua_http_rep_hdr(L, htxn, &htxn->s->txn->rsp, ACT_HTTP_REPLACE_HDR));
|
return MAY_LJMP(hlua_http_rep_hdr(L, htxn, &htxn->s->txn->rsp, 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
__LJMP static int hlua_http_req_rep_val(lua_State *L)
|
__LJMP static int hlua_http_req_rep_val(lua_State *L)
|
||||||
@ -4849,7 +4849,7 @@ __LJMP static int hlua_http_req_rep_val(lua_State *L)
|
|||||||
if (htxn->dir != SMP_OPT_DIR_REQ || !(htxn->flags & HLUA_TXN_HTTP_RDY))
|
if (htxn->dir != SMP_OPT_DIR_REQ || !(htxn->flags & HLUA_TXN_HTTP_RDY))
|
||||||
WILL_LJMP(lua_error(L));
|
WILL_LJMP(lua_error(L));
|
||||||
|
|
||||||
return MAY_LJMP(hlua_http_rep_hdr(L, htxn, &htxn->s->txn->req, ACT_HTTP_REPLACE_VAL));
|
return MAY_LJMP(hlua_http_rep_hdr(L, htxn, &htxn->s->txn->req, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
__LJMP static int hlua_http_res_rep_val(lua_State *L)
|
__LJMP static int hlua_http_res_rep_val(lua_State *L)
|
||||||
@ -4862,7 +4862,7 @@ __LJMP static int hlua_http_res_rep_val(lua_State *L)
|
|||||||
if (htxn->dir != SMP_OPT_DIR_RES || !(htxn->flags & HLUA_TXN_HTTP_RDY))
|
if (htxn->dir != SMP_OPT_DIR_RES || !(htxn->flags & HLUA_TXN_HTTP_RDY))
|
||||||
WILL_LJMP(lua_error(L));
|
WILL_LJMP(lua_error(L));
|
||||||
|
|
||||||
return MAY_LJMP(hlua_http_rep_hdr(L, htxn, &htxn->s->txn->rsp, ACT_HTTP_REPLACE_VAL));
|
return MAY_LJMP(hlua_http_rep_hdr(L, htxn, &htxn->s->txn->rsp, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This function deletes all the occurrences of an header.
|
/* This function deletes all the occurrences of an header.
|
||||||
|
@ -990,6 +990,56 @@ static enum act_parse_ret parse_http_set_header(const char **args, int *orig_arg
|
|||||||
return ACT_RET_PRS_OK;
|
return ACT_RET_PRS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* This function executes a replace-header or replace-value actions. It
|
||||||
|
* builds a string in the trash from the specified format string. It finds
|
||||||
|
* the action to be performed in <.action>, previously filled by function
|
||||||
|
* parse_replace_header(). The replacement action is excuted by the function
|
||||||
|
* http_action_replace_header(). On success, it returns ACT_RET_CONT. If an error
|
||||||
|
* occurs while soft rewrites are enabled, the action is canceled, but the rule
|
||||||
|
* processing continue. Otherwsize ACT_RET_ERR is returned.
|
||||||
|
*/
|
||||||
|
static enum act_return http_action_replace_header(struct act_rule *rule, struct proxy *px,
|
||||||
|
struct session *sess, struct stream *s, int flags)
|
||||||
|
{
|
||||||
|
struct htx *htx = htxbuf((rule->from == ACT_F_HTTP_REQ) ? &s->req.buf : &s->res.buf);
|
||||||
|
enum act_return ret = ACT_RET_CONT;
|
||||||
|
struct buffer *replace;
|
||||||
|
int r;
|
||||||
|
|
||||||
|
replace = alloc_trash_chunk();
|
||||||
|
if (!replace)
|
||||||
|
goto fail_alloc;
|
||||||
|
|
||||||
|
replace->data = build_logline(s, replace->area, replace->size, &rule->arg.http.fmt);
|
||||||
|
|
||||||
|
r = http_replace_hdrs(s, htx, rule->arg.http.str, replace->area, rule->arg.http.re, (rule->action == 0));
|
||||||
|
if (r == -1)
|
||||||
|
goto fail_rewrite;
|
||||||
|
|
||||||
|
leave:
|
||||||
|
free_trash_chunk(replace);
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
fail_alloc:
|
||||||
|
if (!(s->flags & SF_ERR_MASK))
|
||||||
|
s->flags |= SF_ERR_RESOURCE;
|
||||||
|
ret = ACT_RET_ERR;
|
||||||
|
goto leave;
|
||||||
|
|
||||||
|
fail_rewrite:
|
||||||
|
_HA_ATOMIC_ADD(&sess->fe->fe_counters.failed_rewrites, 1);
|
||||||
|
if (s->flags & SF_BE_ASSIGNED)
|
||||||
|
_HA_ATOMIC_ADD(&s->be->be_counters.failed_rewrites, 1);
|
||||||
|
if (sess->listener->counters)
|
||||||
|
_HA_ATOMIC_ADD(&sess->listener->counters->failed_rewrites, 1);
|
||||||
|
if (objt_server(s->target))
|
||||||
|
_HA_ATOMIC_ADD(&__objt_server(s->target)->counters.failed_rewrites, 1);
|
||||||
|
|
||||||
|
if (!(s->txn->req.flags & HTTP_MSGF_SOFT_RW))
|
||||||
|
ret = ACT_RET_ERR;
|
||||||
|
goto leave;
|
||||||
|
}
|
||||||
|
|
||||||
/* Parse a "replace-header" or "replace-value" actions. It takes an header name,
|
/* Parse a "replace-header" or "replace-value" actions. It takes an header name,
|
||||||
* a regex and replacement string as arguments. It returns ACT_RET_PRS_OK on
|
* a regex and replacement string as arguments. It returns ACT_RET_PRS_OK on
|
||||||
* success, ACT_RET_PRS_ERR on error.
|
* success, ACT_RET_PRS_ERR on error.
|
||||||
@ -999,7 +1049,11 @@ static enum act_parse_ret parse_http_replace_header(const char **args, int *orig
|
|||||||
{
|
{
|
||||||
int cap, cur_arg;
|
int cap, cur_arg;
|
||||||
|
|
||||||
rule->action = args[*orig_arg-1][8] == 'h' ? ACT_HTTP_REPLACE_HDR : ACT_HTTP_REPLACE_VAL;
|
if (args[*orig_arg-1][8] == 'h')
|
||||||
|
rule->action = 0; // replace-header
|
||||||
|
else
|
||||||
|
rule->action = 1; // replace-value
|
||||||
|
rule->action_ptr = http_action_replace_header;
|
||||||
|
|
||||||
cur_arg = *orig_arg;
|
cur_arg = *orig_arg;
|
||||||
if (!*args[cur_arg] || !*args[cur_arg+1] || !*args[cur_arg+2]) {
|
if (!*args[cur_arg] || !*args[cur_arg+1] || !*args[cur_arg+2]) {
|
||||||
|
@ -2704,15 +2704,19 @@ int http_apply_redirect_rule(struct redirect_rule *rule, struct stream *s, struc
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int http_transform_header_str(struct stream* s, struct channel *chn, struct htx *htx,
|
/* Replace all headers matching the name <name>. The header value is replaced if
|
||||||
struct ist name, const char *str, struct my_regex *re, int action)
|
* it matches the regex <re>. <str> is used for the replacement. If <full> is
|
||||||
|
* set to 1, the full-line is matched and replaced. Otherwise, comma-separated
|
||||||
|
* values are evaluated one by one. It returns 0 on success and -1 on error.
|
||||||
|
*/
|
||||||
|
int http_replace_hdrs(struct stream* s, struct htx *htx, struct ist name,
|
||||||
|
const char *str, struct my_regex *re, int full)
|
||||||
{
|
{
|
||||||
struct http_hdr_ctx ctx;
|
struct http_hdr_ctx ctx;
|
||||||
struct buffer *output = get_trash_chunk();
|
struct buffer *output = get_trash_chunk();
|
||||||
|
|
||||||
/* find full header is action is ACT_HTTP_REPLACE_HDR */
|
|
||||||
ctx.blk = NULL;
|
ctx.blk = NULL;
|
||||||
while (http_find_header(htx, name, &ctx, (action == ACT_HTTP_REPLACE_HDR))) {
|
while (http_find_header(htx, name, &ctx, full)) {
|
||||||
if (!regex_exec_match2(re, ctx.value.ptr, ctx.value.len, MAX_MATCH, pmatch, 0))
|
if (!regex_exec_match2(re, ctx.value.ptr, ctx.value.len, MAX_MATCH, pmatch, 0))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@ -2725,48 +2729,6 @@ int http_transform_header_str(struct stream* s, struct channel *chn, struct htx
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int http_transform_header(struct stream* s, struct channel *chn, struct htx *htx,
|
|
||||||
const struct ist name, struct list *fmt, struct my_regex *re, int action)
|
|
||||||
{
|
|
||||||
struct buffer *replace;
|
|
||||||
int ret = 0;
|
|
||||||
|
|
||||||
replace = alloc_trash_chunk();
|
|
||||||
if (!replace)
|
|
||||||
goto fail_alloc;
|
|
||||||
|
|
||||||
replace->data = build_logline(s, replace->area, replace->size, fmt);
|
|
||||||
if (replace->data >= replace->size - 1)
|
|
||||||
goto fail_rewrite;
|
|
||||||
|
|
||||||
if (http_transform_header_str(s, chn, htx, name, replace->area, re, action) == -1)
|
|
||||||
goto fail_rewrite;
|
|
||||||
|
|
||||||
leave:
|
|
||||||
free_trash_chunk(replace);
|
|
||||||
return ret;
|
|
||||||
|
|
||||||
fail_alloc:
|
|
||||||
if (!(s->flags & SF_ERR_MASK))
|
|
||||||
s->flags |= SF_ERR_RESOURCE;
|
|
||||||
ret = -1;
|
|
||||||
goto leave;
|
|
||||||
|
|
||||||
fail_rewrite:
|
|
||||||
_HA_ATOMIC_ADD(&s->sess->fe->fe_counters.failed_rewrites, 1);
|
|
||||||
if (s->flags & SF_BE_ASSIGNED)
|
|
||||||
_HA_ATOMIC_ADD(&s->be->be_counters.failed_rewrites, 1);
|
|
||||||
if (s->sess->listener->counters)
|
|
||||||
_HA_ATOMIC_ADD(&s->sess->listener->counters->failed_rewrites, 1);
|
|
||||||
if (objt_server(s->target))
|
|
||||||
_HA_ATOMIC_ADD(&__objt_server(s->target)->counters.failed_rewrites, 1);
|
|
||||||
|
|
||||||
if (!(s->txn->req.flags & HTTP_MSGF_SOFT_RW))
|
|
||||||
ret = -1;
|
|
||||||
goto leave;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Terminate a 103-Erly-hints response and send it to the client. It returns 0
|
/* Terminate a 103-Erly-hints response and send it to the client. It returns 0
|
||||||
* on success and -1 on error. The response channel is updated accordingly.
|
* on success and -1 on error. The response channel is updated accordingly.
|
||||||
*/
|
*/
|
||||||
@ -3069,16 +3031,6 @@ static enum rule_result http_req_get_intercept_rule(struct proxy *px, struct lis
|
|||||||
s->logs.level = rule->arg.http.i;
|
s->logs.level = rule->arg.http.i;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ACT_HTTP_REPLACE_HDR:
|
|
||||||
case ACT_HTTP_REPLACE_VAL:
|
|
||||||
if (http_transform_header(s, &s->req, htx, rule->arg.http.str,
|
|
||||||
&rule->arg.http.fmt,
|
|
||||||
rule->arg.http.re, rule->action)) {
|
|
||||||
rule_ret = HTTP_RULE_RES_ERROR;
|
|
||||||
goto end;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ACT_HTTP_DEL_HDR:
|
case ACT_HTTP_DEL_HDR:
|
||||||
/* remove all occurrences of the header */
|
/* remove all occurrences of the header */
|
||||||
ctx.blk = NULL;
|
ctx.blk = NULL;
|
||||||
@ -3441,16 +3393,6 @@ resume_execution:
|
|||||||
s->logs.level = rule->arg.http.i;
|
s->logs.level = rule->arg.http.i;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ACT_HTTP_REPLACE_HDR:
|
|
||||||
case ACT_HTTP_REPLACE_VAL:
|
|
||||||
if (http_transform_header(s, &s->res, htx, rule->arg.http.str,
|
|
||||||
&rule->arg.http.fmt,
|
|
||||||
rule->arg.http.re, rule->action)) {
|
|
||||||
rule_ret = HTTP_RULE_RES_ERROR;
|
|
||||||
goto end;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ACT_HTTP_DEL_HDR:
|
case ACT_HTTP_DEL_HDR:
|
||||||
/* remove all occurrences of the header */
|
/* remove all occurrences of the header */
|
||||||
ctx.blk = NULL;
|
ctx.blk = NULL;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user