mirror of
http://git.haproxy.org/git/haproxy.git/
synced 2025-01-30 01:52:53 +00: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_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_transform_header_str(struct stream* s, struct channel *chn, struct htx *htx,
|
||||
struct ist name, const char *str, struct my_regex *re, int action);
|
||||
int http_replace_hdrs(struct stream* s, struct htx *htx, struct ist name, const char *str, struct my_regex *re, int full);
|
||||
int http_req_replace_stline(int action, const char *replace, int len,
|
||||
struct proxy *px, 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 .*/
|
||||
ACT_HTTP_ADD_HDR,
|
||||
ACT_HTTP_REPLACE_HDR,
|
||||
ACT_HTTP_REPLACE_VAL,
|
||||
ACT_HTTP_SET_HDR,
|
||||
ACT_HTTP_DEL_HDR,
|
||||
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.
|
||||
*/
|
||||
__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;
|
||||
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"));
|
||||
|
||||
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);
|
||||
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))
|
||||
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)
|
||||
@ -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))
|
||||
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)
|
||||
@ -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))
|
||||
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)
|
||||
@ -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))
|
||||
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.
|
||||
|
@ -990,6 +990,56 @@ static enum act_parse_ret parse_http_set_header(const char **args, int *orig_arg
|
||||
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,
|
||||
* a regex and replacement string as arguments. It returns ACT_RET_PRS_OK on
|
||||
* 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;
|
||||
|
||||
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;
|
||||
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;
|
||||
}
|
||||
|
||||
int http_transform_header_str(struct stream* s, struct channel *chn, struct htx *htx,
|
||||
struct ist name, const char *str, struct my_regex *re, int action)
|
||||
/* Replace all headers matching the name <name>. The header value is replaced if
|
||||
* 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 buffer *output = get_trash_chunk();
|
||||
|
||||
/* find full header is action is ACT_HTTP_REPLACE_HDR */
|
||||
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))
|
||||
continue;
|
||||
|
||||
@ -2725,48 +2729,6 @@ int http_transform_header_str(struct stream* s, struct channel *chn, struct htx
|
||||
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
|
||||
* 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;
|
||||
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:
|
||||
/* remove all occurrences of the header */
|
||||
ctx.blk = NULL;
|
||||
@ -3441,16 +3393,6 @@ resume_execution:
|
||||
s->logs.level = rule->arg.http.i;
|
||||
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:
|
||||
/* remove all occurrences of the header */
|
||||
ctx.blk = NULL;
|
||||
|
Loading…
Reference in New Issue
Block a user