]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: http: Add a function to get the authority into a URI
authorChristopher Faulet <cfaulet@haproxy.com>
Tue, 8 Oct 2019 12:56:58 +0000 (14:56 +0200)
committerChristopher Faulet <cfaulet@haproxy.com>
Wed, 9 Oct 2019 09:05:31 +0000 (11:05 +0200)
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.

include/common/http.h
src/http.c

index fbbc33c0c266a660c7f8bc330387ae979c413136..857c66e1d45c9a7e4a6f24a54e236bd3a39bb607 100644 (file)
@@ -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);
index fe7ed4cdf7a1ffdf2bd5913108a6c459bf50b585..c9168669db22c2fd0307672b8c77c5f3fbfc3945 100644 (file)
@@ -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.