From: Christopher Faulet Date: Wed, 24 Oct 2018 08:36:45 +0000 (+0200) Subject: MINOR: http_htx: Add functions to replace part of the start-line X-Git-Tag: v1.9-dev7~65 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=e010c807533d2330527ce1b0d276310902898e03;p=thirdparty%2Fhaproxy.git MINOR: http_htx: Add functions to replace part of the start-line --- diff --git a/include/proto/http_htx.h b/include/proto/http_htx.h index 1ca7902f9a..c9f730ebc7 100644 --- a/include/proto/http_htx.h +++ b/include/proto/http_htx.h @@ -33,6 +33,12 @@ int http_find_header(const struct htx *htx, const struct ist name, struct http_h int http_add_header(struct htx *htx, const struct ist n, const struct ist v); int http_replace_reqline(struct htx *htx, const union h1_sl sl); int http_replace_resline(struct htx *htx, const union h1_sl sl); +int http_replace_req_meth(struct htx *htx, const struct ist meth); +int http_replace_req_uri(struct htx *htx, const struct ist uri); +int http_replace_req_path(struct htx *htx, const struct ist path); +int http_replace_req_query(struct htx *htx, const struct ist query); +int http_replace_res_status(struct htx *htx, const struct ist status); +int http_replace_res_reason(struct htx *htx, const struct ist reason); int http_replace_header_value(struct htx *htx, struct http_hdr_ctx *ctx, const struct ist data); int http_replace_header(struct htx *htx, struct http_hdr_ctx *ctx, const struct ist name, const struct ist value); int http_remove_header(struct htx *htx, struct http_hdr_ctx *ctx); diff --git a/src/http_htx.c b/src/http_htx.c index 47e36c8560..36a2793424 100644 --- a/src/http_htx.c +++ b/src/http_htx.c @@ -241,6 +241,180 @@ int http_replace_resline(struct htx *htx, const union h1_sl sl) return 0; } +/* Replace the request method in the HTX message by . It returns 1 + * on success, otherwise 0. + */ +int http_replace_req_meth(struct htx *htx, const struct ist meth) +{ + struct buffer *temp = get_trash_chunk(); + union h1_sl sl = http_find_stline(htx); + union h1_sl new_sl; + + /* Start by copying old uri and version */ + chunk_memcat(temp, sl.rq.u.ptr, sl.rq.u.len); /* uri */ + chunk_memcat(temp, sl.rq.v.ptr, sl.rq.v.len); /* vsn */ + + /* create the new start line */ + new_sl.rq.meth = find_http_meth(meth.ptr, meth.len); + new_sl.rq.m = meth; + new_sl.rq.u = ist2(temp->area, sl.rq.u.len); + new_sl.rq.v = ist2(temp->area + sl.rq.u.len, sl.rq.v.len); + + return http_replace_reqline(htx, new_sl); +} + +/* Replace the request uri in the HTX message by . It returns 1 on + * success, otherwise 0. + */ +int http_replace_req_uri(struct htx *htx, const struct ist uri) +{ + struct buffer *temp = get_trash_chunk(); + union h1_sl sl = http_find_stline(htx); + union h1_sl new_sl; + + /* Start by copying old method and version */ + chunk_memcat(temp, sl.rq.m.ptr, sl.rq.m.len); /* meth */ + chunk_memcat(temp, sl.rq.v.ptr, sl.rq.v.len); /* vsn */ + + /* create the new start line */ + new_sl.rq.meth = sl.rq.meth; + new_sl.rq.m = ist2(temp->area, sl.rq.m.len); + new_sl.rq.u = uri; + new_sl.rq.v = ist2(temp->area + sl.rq.m.len, sl.rq.v.len); + + return http_replace_reqline(htx, new_sl); +} + +/* Replace the request path in the HTX message by . The host part + * and the query string are preserved. It returns 1 on success, otherwise 0. + */ +int http_replace_req_path(struct htx *htx, const struct ist path) +{ + struct buffer *temp = get_trash_chunk(); + union h1_sl sl = http_find_stline(htx); + union h1_sl new_sl; + struct ist p, uri; + size_t plen = 0; + + p = http_get_path(sl.rq.u); + if (!p.ptr) + p = sl.rq.u; + while (plen < p.len && *(p.ptr + plen) != '?') + plen++; + + /* Start by copying old method and version and create the new uri */ + chunk_memcat(temp, sl.rq.m.ptr, sl.rq.m.len); /* meth */ + chunk_memcat(temp, sl.rq.v.ptr, sl.rq.v.len); /* vsn */ + + chunk_memcat(temp, sl.rq.u.ptr, p.ptr - sl.rq.u.ptr); /* uri: host part */ + chunk_memcat(temp, path.ptr, path.len); /* uri: new path */ + chunk_memcat(temp, p.ptr + plen, p.len - plen); /* uri: QS part */ + + /* Get uri ptr and len */ + uri.ptr = temp->area + sl.rq.m.len + sl.rq.v.len; + uri.len = sl.rq.u.len - plen + path.len; + + /* create the new start line */ + new_sl.rq.meth = sl.rq.meth; + new_sl.rq.m = ist2(temp->area, sl.rq.m.len); + new_sl.rq.u = uri; + new_sl.rq.v = ist2(temp->area + sl.rq.m.len, sl.rq.v.len); + + return http_replace_reqline(htx, new_sl); +} + +/* Replace the request query-string in the HTX message by . The + * host part and the path are preserved. It returns 1 on success, otherwise + * 0. + */ +int http_replace_req_query(struct htx *htx, const struct ist query) +{ + struct buffer *temp = get_trash_chunk(); + union h1_sl sl = http_find_stline(htx); + union h1_sl new_sl; + struct ist q, uri; + int offset = 1; + + q = sl.rq.u; + while (q.len > 0 && *(q.ptr) != '?') { + q.ptr++; + q.len--; + } + + /* skip the question mark or indicate that we must insert it + * (but only if the format string is not empty then). + */ + if (q.len) { + q.ptr++; + q.len--; + } + else if (query.len > 1) + offset = 0; + + /* Start by copying old method and version and create the new uri */ + chunk_memcat(temp, sl.rq.m.ptr, sl.rq.m.len); /* meth */ + chunk_memcat(temp, sl.rq.v.ptr, sl.rq.v.len); /* vsn */ + + chunk_memcat(temp, sl.rq.u.ptr, q.ptr - sl.rq.u.ptr); /* uri: host + path part */ + chunk_memcat(temp, query.ptr + offset, query.len - offset); /* uri: new QS */ + + /* Get uri ptr and len */ + uri.ptr = temp->area + sl.rq.m.len + sl.rq.v.len; + uri.len = sl.rq.u.len - q.len + query.len - offset; + + /* create the new start line */ + new_sl.rq.meth = sl.rq.meth; + new_sl.rq.m = ist2(temp->area, sl.rq.m.len); + new_sl.rq.u = uri; + new_sl.rq.v = ist2(temp->area + sl.rq.m.len, sl.rq.v.len); + + return http_replace_reqline(htx, new_sl); +} + +/* Replace the response status in the HTX message by . It returns + * 1 on success, otherwise 0. +*/ +int http_replace_res_status(struct htx *htx, const struct ist status) +{ + struct buffer *temp = get_trash_chunk(); + union h1_sl sl = http_find_stline(htx); + union h1_sl new_sl; + + /* Start by copying old uri and version */ + chunk_memcat(temp, sl.st.v.ptr, sl.st.v.len); /* vsn */ + chunk_memcat(temp, sl.st.r.ptr, sl.st.r.len); /* reason */ + + /* create the new start line */ + new_sl.st.status = strl2ui(status.ptr, status.len); + new_sl.st.v = ist2(temp->area, sl.st.v.len); + new_sl.st.c = status; + new_sl.st.r = ist2(temp->area + sl.st.v.len, sl.st.r.len); + + return http_replace_resline(htx, new_sl); +} + +/* Replace the response reason in the HTX message by . It returns + * 1 on success, otherwise 0. +*/ +int http_replace_res_reason(struct htx *htx, const struct ist reason) +{ + struct buffer *temp = get_trash_chunk(); + union h1_sl sl = http_find_stline(htx); + union h1_sl new_sl; + + /* Start by copying old uri and version */ + chunk_memcat(temp, sl.st.v.ptr, sl.st.v.len); /* vsn */ + chunk_memcat(temp, sl.st.c.ptr, sl.st.c.len); /* code */ + + /* create the new start line */ + new_sl.st.status = sl.st.status; + new_sl.st.v = ist2(temp->area, sl.st.v.len); + new_sl.st.c = ist2(temp->area + sl.st.v.len, sl.st.c.len); + new_sl.st.r = reason; + + return http_replace_resline(htx, new_sl); +} + /* Replaces a part of a header value referenced in the context by * . It returns 1 on success, otherwise it returns 0. The context is * updated if necessary.