From 6b952c81014a48a8d841e311d94afc68a1d573c8 Mon Sep 17 00:00:00 2001 From: Willy Tarreau Date: Mon, 10 Sep 2018 17:45:34 +0200 Subject: [PATCH] REORG: http: move http_get_path() to http.c This function is purely HTTP once http_txn is put aside. So the original one was renamed to http_txn_get_path() and it extracts the relevant offsets from the txn to pass them to http_get_path(). One benefit of the new version is that it returns the length at the same time so that allowed to slightly simplify http_get_path_from_string() which had to look up the end pointer previously and which is not needed anymore. --- include/common/http.h | 1 + include/proto/proto_http.h | 2 +- src/cache.c | 2 +- src/hlua.c | 2 +- src/http.c | 50 ++++++++++++++++ src/proto_http.c | 115 ++++++------------------------------- 6 files changed, 73 insertions(+), 99 deletions(-) diff --git a/include/common/http.h b/include/common/http.h index d283e2977b..4184a47f9c 100644 --- a/include/common/http.h +++ b/include/common/http.h @@ -114,6 +114,7 @@ extern const char *HTTP_302; extern const char *HTTP_303; enum http_meth_t find_http_meth(const char *str, const int len); +struct ist http_get_path(const struct ist uri); #endif /* _COMMON_HTTP_H */ diff --git a/include/proto/proto_http.h b/include/proto/proto_http.h index b537d45344..9eba1448d7 100644 --- a/include/proto/proto_http.h +++ b/include/proto/proto_http.h @@ -100,7 +100,7 @@ void http_capture_bad_message(struct proxy *proxy, struct stream *s, unsigned int http_get_hdr(const struct http_msg *msg, const char *hname, int hlen, struct hdr_idx *idx, int occ, struct hdr_ctx *ctx, char **vptr, size_t *vlen); -char *http_get_path(struct http_txn *txn); +char *http_txn_get_path(const struct http_txn *txn); const char *get_reason(unsigned int status); struct http_txn *http_alloc_txn(struct stream *s); diff --git a/src/cache.c b/src/cache.c index f58c3cc4ad..3abb46cea9 100644 --- a/src/cache.c +++ b/src/cache.c @@ -650,7 +650,7 @@ int sha1_hosturi(struct http_txn *txn) /* now retrieve the path */ end = ci_head(txn->req.chn) + txn->req.sl.rq.u + txn->req.sl.rq.u_l; - path = http_get_path(txn); + path = http_txn_get_path(txn); if (!path) return 0; chunk_strncat(trash, path, end - path); diff --git a/src/hlua.c b/src/hlua.c index f07df4708d..6f001d54df 100644 --- a/src/hlua.c +++ b/src/hlua.c @@ -3945,7 +3945,7 @@ static int hlua_applet_http_new(lua_State *L, struct appctx *ctx) lua_settable(L, -3); /* Get path and qs */ - path = http_get_path(txn); + path = http_txn_get_path(txn); if (path) { end = ci_head(txn->req.chn) + txn->req.sl.rq.u + txn->req.sl.rq.u_l; p = path; diff --git a/src/http.c b/src/http.c index ad620a9f22..66a91dba77 100644 --- a/src/http.c +++ b/src/http.c @@ -183,3 +183,53 @@ enum http_meth_t find_http_meth(const char *str, const int len) else if (isteq(m, ist("TRACE"))) return HTTP_METH_TRACE; else return HTTP_METH_OTHER; } + +/* Parse the URI from the given transaction (which is assumed to be in request + * phase) and look for the "/" beginning the PATH. If not found, ist2(0,0) is + * returned. Otherwise the pointer and length are returned. + */ +struct ist http_get_path(const struct ist uri) +{ + const char *ptr, *end; + + if (!uri.len) + goto not_found; + + ptr = uri.ptr; + end = ptr + uri.len; + + /* RFC7230, par. 2.7 : + * Request-URI = "*" | absuri | abspath | authority + */ + + if (*ptr == '*') + goto not_found; + + if (isalpha((unsigned char)*ptr)) { + /* this is a scheme as described by RFC3986, par. 3.1 */ + ptr++; + while (ptr < end && + (isalnum((unsigned char)*ptr) || *ptr == '+' || *ptr == '-' || *ptr == '.')) + ptr++; + /* skip '://' */ + if (ptr == end || *ptr++ != ':') + goto not_found; + if (ptr == end || *ptr++ != '/') + goto not_found; + if (ptr == end || *ptr++ != '/') + goto not_found; + } + /* skip [user[:passwd]@]host[:[port]] */ + + while (ptr < end && *ptr != '/') + ptr++; + + if (ptr == end) + goto not_found; + + /* OK, we got the '/' ! */ + return ist2(ptr, end - ptr); + + not_found: + return ist2(NULL, 0); +} diff --git a/src/proto_http.c b/src/proto_http.c index b153b14133..047e270df6 100644 --- a/src/proto_http.c +++ b/src/proto_http.c @@ -914,87 +914,13 @@ http_reply_and_close(struct stream *s, short status, struct buffer *msg) * phase) and look for the "/" beginning the PATH. If not found, return NULL. * It is returned otherwise. */ -char *http_get_path(struct http_txn *txn) +char *http_txn_get_path(const struct http_txn *txn) { - char *ptr, *end; - - ptr = ci_head(txn->req.chn) + txn->req.sl.rq.u; - end = ptr + txn->req.sl.rq.u_l; - - if (ptr >= end) - return NULL; - - /* RFC7230, par. 2.7 : - * Request-URI = "*" | absuri | abspath | authority - */ - - if (*ptr == '*') - return NULL; - - if (isalpha((unsigned char)*ptr)) { - /* this is a scheme as described by RFC3986, par. 3.1 */ - ptr++; - while (ptr < end && - (isalnum((unsigned char)*ptr) || *ptr == '+' || *ptr == '-' || *ptr == '.')) - ptr++; - /* skip '://' */ - if (ptr == end || *ptr++ != ':') - return NULL; - if (ptr == end || *ptr++ != '/') - return NULL; - if (ptr == end || *ptr++ != '/') - return NULL; - } - /* skip [user[:passwd]@]host[:[port]] */ - - while (ptr < end && *ptr != '/') - ptr++; - - if (ptr == end) - return NULL; - - /* OK, we got the '/' ! */ - return ptr; -} + struct ist ret; -/* Parse the URI from the given string and look for the "/" beginning the PATH. - * If not found, return NULL. It is returned otherwise. - */ -static char * -http_get_path_from_string(char *str) -{ - char *ptr = str; - - /* RFC2616, par. 5.1.2 : - * Request-URI = "*" | absuri | abspath | authority - */ - - if (*ptr == '*') - return NULL; - - if (isalpha((unsigned char)*ptr)) { - /* this is a scheme as described by RFC3986, par. 3.1 */ - ptr++; - while (isalnum((unsigned char)*ptr) || *ptr == '+' || *ptr == '-' || *ptr == '.') - ptr++; - /* skip '://' */ - if (*ptr == '\0' || *ptr++ != ':') - return NULL; - if (*ptr == '\0' || *ptr++ != '/') - return NULL; - if (*ptr == '\0' || *ptr++ != '/') - return NULL; - } - /* skip [user[:passwd]@]host[:[port]] */ + ret = http_get_path(ist2(ci_head(txn->req.chn) + txn->req.sl.rq.u, txn->req.sl.rq.u_l)); - while (*ptr != '\0' && *ptr != ' ' && *ptr != '/') - ptr++; - - if (*ptr == '\0' || *ptr == ' ') - return NULL; - - /* OK, we got the '/' ! */ - return ptr; + return ret.ptr; } /* Returns a 302 for a redirectable request that reaches a server working in @@ -1032,7 +958,7 @@ void http_perform_server_redirect(struct stream *s, struct stream_interface *si) txn = s->txn; c_rew(&s->req, rewind = http_hdr_rewind(&txn->req)); - path = http_get_path(txn); + path = http_txn_get_path(txn); len = b_dist(&s->req.buf, path, c_ptr(&s->req, txn->req.sl.rq.u + txn->req.sl.rq.u_l)); c_adv(&s->req, rewind); @@ -3159,7 +3085,7 @@ static int http_apply_redirect_rule(struct redirect_rule *rule, struct stream *s hostlen = ctx.vlen; } - path = http_get_path(txn); + path = http_txn_get_path(txn); /* build message using path */ if (path) { pathlen = req->sl.rq.u_l + (ci_head(req->chn) + req->sl.rq.u) - path; @@ -3226,7 +3152,7 @@ static int http_apply_redirect_rule(struct redirect_rule *rule, struct stream *s const char *path; int pathlen; - path = http_get_path(txn); + path = http_txn_get_path(txn); /* build message using path */ if (path) { pathlen = req->sl.rq.u_l + (ci_head(req->chn) + req->sl.rq.u) - path; @@ -3718,7 +3644,7 @@ int http_process_request(struct stream *s, struct channel *req, int an_bit) return 0; } - path = http_get_path(txn); + path = http_txn_get_path(txn); if (url2sa(ci_head(req) + msg->sl.rq.u, path ? path - (ci_head(req) + msg->sl.rq.u) : msg->sl.rq.u_l, &conn->addr.to, NULL) == -1) @@ -10323,7 +10249,7 @@ smp_fetch_path(const struct arg *args, struct sample *smp, const char *kw, void txn = smp->strm->txn; end = ci_head(txn->req.chn) + txn->req.sl.rq.u + txn->req.sl.rq.u_l; - ptr = http_get_path(txn); + ptr = http_txn_get_path(txn); if (!ptr) return 0; @@ -10370,7 +10296,7 @@ smp_fetch_base(const struct arg *args, struct sample *smp, const char *kw, void /* now retrieve the path */ end = ci_head(txn->req.chn) + txn->req.sl.rq.u + txn->req.sl.rq.u_l; - beg = http_get_path(txn); + beg = http_txn_get_path(txn); if (!beg) beg = end; @@ -10417,7 +10343,7 @@ smp_fetch_base32(const struct arg *args, struct sample *smp, const char *kw, voi /* now retrieve the path */ end = ci_head(txn->req.chn) + txn->req.sl.rq.u + txn->req.sl.rq.u_l; - beg = http_get_path(txn); + beg = http_txn_get_path(txn); if (!beg) beg = end; @@ -10758,9 +10684,9 @@ smp_fetch_capture_req_method(const struct arg *args, struct sample *smp, const c static int smp_fetch_capture_req_uri(const struct arg *args, struct sample *smp, const char *kw, void *private) { - struct buffer *temp; struct http_txn *txn = smp->strm->txn; - char *ptr; + struct ist path; + const char *ptr; if (!txn || !txn->uri) return 0; @@ -10775,15 +10701,12 @@ smp_fetch_capture_req_uri(const struct arg *args, struct sample *smp, const char ptr++; /* skip the space */ - temp = get_trash_chunk(); - ptr = temp->area = http_get_path_from_string(ptr); - if (!ptr) + path = http_get_path(ist(ptr)); + if (!path.ptr) return 0; - while (*ptr != ' ' && *ptr != '\0') /* find space after URI */ - ptr++; - smp->data.u.str = *temp; - smp->data.u.str.data = ptr - temp->area; + smp->data.u.str.area = path.ptr; + smp->data.u.str.data = path.len; smp->data.type = SMP_T_STR; smp->flags = SMP_F_CONST; @@ -11467,7 +11390,7 @@ smp_fetch_url32(const struct arg *args, struct sample *smp, const char *kw, void /* now retrieve the path */ end = ci_head(txn->req.chn) + txn->req.sl.rq.u + txn->req.sl.rq.u_l; - beg = http_get_path(txn); + beg = http_txn_get_path(txn); if (!beg) beg = end; @@ -11895,7 +11818,7 @@ int http_replace_req_line(int action, const char *replace, int len, break; case 1: // path - cur_ptr = http_get_path(txn); + cur_ptr = http_txn_get_path(txn); if (!cur_ptr) cur_ptr = ci_head(&s->req) + txn->req.sl.rq.u; -- 2.39.5