MINOR: proto_htx: Rewrite htx_apply_redirect_rule to handle HTX messages
diff --git a/src/proto_htx.c b/src/proto_htx.c
index 5950924..f229ab3 100644
--- a/src/proto_htx.c
+++ b/src/proto_htx.c
@@ -2354,8 +2354,8 @@
*/
int htx_apply_redirect_rule(struct redirect_rule *rule, struct stream *s, struct http_txn *txn)
{
- struct http_msg *req = &txn->req;
- struct http_msg *res = &txn->rsp;
+ struct htx *htx = htx_from_buf(&s->req.buf);
+ union h1_sl sl;
const char *msg_fmt;
struct buffer *chunk;
int ret = 0;
@@ -2389,178 +2389,129 @@
switch(rule->type) {
case REDIRECT_TYPE_SCHEME: {
- const char *path;
- const char *host;
- struct hdr_ctx ctx;
- int pathlen;
- int hostlen;
+ struct http_hdr_ctx ctx;
+ struct ist path, host;
- host = "";
- hostlen = 0;
- ctx.idx = 0;
- if (http_find_header2("Host", 4, ci_head(req->chn), &txn->hdr_idx, &ctx)) {
- host = ctx.line + ctx.val;
- hostlen = ctx.vlen;
- }
+ host = ist("");
+ ctx.blk = NULL;
+ if (http_find_header(htx, ist("Host"), &ctx, 0))
+ host = ctx.value;
- path = http_txn_get_path(txn);
+ sl = http_find_stline(htx);
+ path = http_get_path(sl.rq.u);
/* build message using path */
- if (path) {
- pathlen = req->sl.rq.u_l + (ci_head(req->chn) + req->sl.rq.u) - path;
+ if (path.ptr) {
if (rule->flags & REDIRECT_FLAG_DROP_QS) {
int qs = 0;
- while (qs < pathlen) {
- if (path[qs] == '?') {
- pathlen = qs;
+ while (qs < path.len) {
+ if (*(path.ptr + qs) == '?') {
+ path.len = qs;
break;
}
qs++;
}
}
- } else {
- path = "/";
- pathlen = 1;
}
+ else
+ path = ist("/");
if (rule->rdr_str) { /* this is an old "redirect" rule */
- /* check if we can add scheme + "://" + host + path */
- if (chunk->data + rule->rdr_len + 3 + hostlen + pathlen > chunk->size - 4)
- goto leave;
-
/* add scheme */
- memcpy(chunk->area + chunk->data, rule->rdr_str,
- rule->rdr_len);
- chunk->data += rule->rdr_len;
+ if (!chunk_memcat(chunk, rule->rdr_str, rule->rdr_len))
+ goto leave;
}
else {
/* add scheme with executing log format */
- chunk->data += build_logline(s,
- chunk->area + chunk->data,
- chunk->size - chunk->data,
- &rule->rdr_fmt);
-
- /* check if we can add scheme + "://" + host + path */
- if (chunk->data + 3 + hostlen + pathlen > chunk->size - 4)
- goto leave;
+ chunk->data += build_logline(s, chunk->area + chunk->data,
+ chunk->size - chunk->data,
+ &rule->rdr_fmt);
}
- /* add "://" */
- memcpy(chunk->area + chunk->data, "://", 3);
- chunk->data += 3;
-
- /* add host */
- memcpy(chunk->area + chunk->data, host, hostlen);
- chunk->data += hostlen;
-
- /* add path */
- memcpy(chunk->area + chunk->data, path, pathlen);
- chunk->data += pathlen;
+ /* add "://" + host + path */
+ if (!chunk_memcat(chunk, "://", 3) ||
+ !chunk_memcat(chunk, host.ptr, host.len) ||
+ !chunk_memcat(chunk, path.ptr, path.len))
+ goto leave;
/* append a slash at the end of the location if needed and missing */
if (chunk->data && chunk->area[chunk->data - 1] != '/' &&
(rule->flags & REDIRECT_FLAG_APPEND_SLASH)) {
- if (chunk->data > chunk->size - 5)
+ if (chunk->data + 1 >= chunk->size)
goto leave;
- chunk->area[chunk->data] = '/';
- chunk->data++;
+ chunk->area[chunk->data++] = '/';
}
-
break;
}
case REDIRECT_TYPE_PREFIX: {
- const char *path;
- int pathlen;
+ struct ist path;
- path = http_txn_get_path(txn);
+ sl = http_find_stline(htx);
+ path = http_get_path(sl.rq.u);
/* build message using path */
- if (path) {
- pathlen = req->sl.rq.u_l + (ci_head(req->chn) + req->sl.rq.u) - path;
+ if (path.ptr) {
if (rule->flags & REDIRECT_FLAG_DROP_QS) {
int qs = 0;
- while (qs < pathlen) {
- if (path[qs] == '?') {
- pathlen = qs;
+ while (qs < path.len) {
+ if (*(path.ptr + qs) == '?') {
+ path.len = qs;
break;
}
qs++;
}
}
- } else {
- path = "/";
- pathlen = 1;
}
+ else
+ path = ist("/");
if (rule->rdr_str) { /* this is an old "redirect" rule */
- if (chunk->data + rule->rdr_len + pathlen > chunk->size - 4)
- goto leave;
-
/* add prefix. Note that if prefix == "/", we don't want to
* add anything, otherwise it makes it hard for the user to
* configure a self-redirection.
*/
if (rule->rdr_len != 1 || *rule->rdr_str != '/') {
- memcpy(chunk->area + chunk->data,
- rule->rdr_str, rule->rdr_len);
- chunk->data += rule->rdr_len;
+ if (!chunk_memcat(chunk, rule->rdr_str, rule->rdr_len))
+ goto leave;
}
}
else {
/* add prefix with executing log format */
- chunk->data += build_logline(s,
- chunk->area + chunk->data,
- chunk->size - chunk->data,
- &rule->rdr_fmt);
-
- /* Check length */
- if (chunk->data + pathlen > chunk->size - 4)
- goto leave;
+ chunk->data += build_logline(s, chunk->area + chunk->data,
+ chunk->size - chunk->data,
+ &rule->rdr_fmt);
}
/* add path */
- memcpy(chunk->area + chunk->data, path, pathlen);
- chunk->data += pathlen;
+ if (!chunk_memcat(chunk, path.ptr, path.len))
+ goto leave;
/* append a slash at the end of the location if needed and missing */
if (chunk->data && chunk->area[chunk->data - 1] != '/' &&
(rule->flags & REDIRECT_FLAG_APPEND_SLASH)) {
- if (chunk->data > chunk->size - 5)
+ if (chunk->data + 1 >= chunk->size)
goto leave;
- chunk->area[chunk->data] = '/';
- chunk->data++;
+ chunk->area[chunk->data++] = '/';
}
-
break;
}
case REDIRECT_TYPE_LOCATION:
default:
if (rule->rdr_str) { /* this is an old "redirect" rule */
- if (chunk->data + rule->rdr_len > chunk->size - 4)
- goto leave;
-
/* add location */
- memcpy(chunk->area + chunk->data, rule->rdr_str,
- rule->rdr_len);
- chunk->data += rule->rdr_len;
+ if (!chunk_memcat(chunk, rule->rdr_str, rule->rdr_len))
+ goto leave;
}
else {
/* add location with executing log format */
- chunk->data += build_logline(s,
- chunk->area + chunk->data,
- chunk->size - chunk->data,
- &rule->rdr_fmt);
-
- /* Check left length */
- if (chunk->data > chunk->size - 4)
- goto leave;
+ chunk->data += build_logline(s, chunk->area + chunk->data,
+ chunk->size - chunk->data,
+ &rule->rdr_fmt);
}
break;
}
if (rule->cookie_len) {
- memcpy(chunk->area + chunk->data, "\r\nSet-Cookie: ", 14);
- chunk->data += 14;
- memcpy(chunk->area + chunk->data, rule->cookie_str,
- rule->cookie_len);
- chunk->data += rule->cookie_len;
+ if (!chunk_memcat(chunk, "\r\nSet-Cookie: ", 14) ||
+ !chunk_memcat(chunk, rule->cookie_str, rule->cookie_len))
+ goto leave;
}
/* add end of headers and the keep-alive/close status. */
@@ -2568,50 +2519,16 @@
/* let's log the request time */
s->logs.tv_request = now;
- if (((!(req->flags & HTTP_MSGF_TE_CHNK) && !req->body_len) || (req->msg_state == HTTP_MSG_DONE))) {
- /* keep-alive possible */
- if (!(req->flags & HTTP_MSGF_VER_11)) {
- if (unlikely(txn->flags & TX_USE_PX_CONN)) {
- memcpy(chunk->area + chunk->data,
- "\r\nProxy-Connection: keep-alive", 30);
- chunk->data += 30;
- } else {
- memcpy(chunk->area + chunk->data,
- "\r\nConnection: keep-alive", 24);
- chunk->data += 24;
- }
- }
- memcpy(chunk->area + chunk->data, "\r\n\r\n", 4);
- chunk->data += 4;
- FLT_STRM_CB(s, flt_http_reply(s, txn->status, chunk));
- co_inject(res->chn, chunk->area, chunk->data);
- /* "eat" the request */
- b_del(&req->chn->buf, req->sov);
- req->next -= req->sov;
- req->sov = 0;
- s->req.analysers = AN_REQ_HTTP_XFER_BODY | (s->req.analysers & AN_REQ_FLT_END);
- s->res.analysers = AN_RES_HTTP_XFER_BODY | (s->res.analysers & AN_RES_FLT_END);
- req->msg_state = HTTP_MSG_CLOSED;
- res->msg_state = HTTP_MSG_DONE;
- /* Trim any possible response */
- b_set_data(&res->chn->buf, co_data(res->chn));
- res->next = res->sov = 0;
- /* let the server side turn to SI_ST_CLO */
- channel_shutw_now(req->chn);
+ /* FIXME: close for now, but it could be cool to handle the keep-alive here */
+ if (unlikely(txn->flags & TX_USE_PX_CONN)) {
+ if (!chunk_memcat(chunk, "\r\nProxy-Connection: close\r\n\r\n", 29))
+ goto leave;
} else {
- /* keep-alive not possible */
- if (unlikely(txn->flags & TX_USE_PX_CONN)) {
- memcpy(chunk->area + chunk->data,
- "\r\nProxy-Connection: close\r\n\r\n", 29);
- chunk->data += 29;
- } else {
- memcpy(chunk->area + chunk->data,
- "\r\nConnection: close\r\n\r\n", 23);
- chunk->data += 23;
- }
- http_reply_and_close(s, txn->status, chunk);
- req->chn->analysers &= AN_REQ_FLT_END;
+ if (!chunk_memcat(chunk, "\r\nConnection: close\r\n\r\n", 23))
+ goto leave;
}
+ htx_reply_and_close(s, txn->status, chunk);
+ s->req.analysers &= AN_REQ_FLT_END;
if (!(s->flags & SF_ERR_MASK))
s->flags |= SF_ERR_LOCAL;
@@ -2619,7 +2536,7 @@
s->flags |= SF_FINST_R;
ret = 1;
- leave:
+ leave:
free_trash_chunk(chunk);
return ret;
}