From: Christopher Faulet Date: Tue, 8 Oct 2019 12:56:58 +0000 (+0200) Subject: MINOR: http: Add a function to get the authority into a URI X-Git-Tag: v2.1-dev3~131 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=16fdc55f7987797b196c2edac34628bbf61bccc4;p=thirdparty%2Fhaproxy.git MINOR: http: Add a function to get the authority into a URI The function http_get_authority() may be used to parse a URI and looks for the authority, between the scheme and the path. An option may be used to skip the user info (part before the '@'). Most of time, the user info will be ignored. --- diff --git a/include/common/http.h b/include/common/http.h index fbbc33c0c2..857c66e1d4 100644 --- a/include/common/http.h +++ b/include/common/http.h @@ -136,6 +136,7 @@ extern const char *HTTP_407_fmt; enum http_meth_t find_http_meth(const char *str, const int len); int http_get_status_idx(unsigned int status); const char *http_get_reason(unsigned int status); +struct ist http_get_authority(const struct ist uri, int no_userinfo); struct ist http_get_path(const struct ist uri); int http_header_match2(const char *hdr, const char *end, const char *name, int len); diff --git a/src/http.c b/src/http.c index fe7ed4cdf7..c9168669db 100644 --- a/src/http.c +++ b/src/http.c @@ -476,6 +476,62 @@ const char *http_get_reason(unsigned int status) } } +/* Parse the uri and looks for the authority, between the scheme and the + * path. if no_userinfo is not zero, the part before the '@' (including it) is + * skipped. If not found, an empty ist is returned. Otherwise, the ist pointing + * on the authority is returned. + */ +struct ist http_get_authority(const struct ist uri, int no_userinfo) +{ + const char *ptr, *start, *end; + + if (!uri.len) + goto not_found; + + ptr = uri.ptr; + start = ptr; + end = ptr + uri.len; + + /* RFC7230, par. 2.7 : + * Request-URI = "*" | absuri | abspath | authority + */ + + if (*ptr == '*' || *ptr == '/') + goto not_found; + + if (isalpha((unsigned char)*ptr)) { + /* this is a scheme as described by RFC3986, par. 3.1, or only + * an authority (in case of a CONNECT method). + */ + ptr++; + while (ptr < end && + (isalnum((unsigned char)*ptr) || *ptr == '+' || *ptr == '-' || *ptr == '.')) + ptr++; + /* skip '://' or take the whole as authority if not found */ + if (ptr == end || *ptr++ != ':') + goto authority; + if (ptr == end || *ptr++ != '/') + goto authority; + if (ptr == end || *ptr++ != '/') + goto authority; + } + + start = ptr; + while (ptr < end && *ptr != '/') { + if (*ptr++ == '@' && no_userinfo) + start = ptr; + } + + /* OK, ptr point on the '/' or the end */ + end = ptr; + + authority: + return ist2(start, end - start); + + not_found: + return ist2(NULL, 0); +} + /* 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.