summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--http-internal.h3
-rw-r--r--http.c69
-rw-r--r--include/event2/http.h9
-rw-r--r--test/regress_http.c25
4 files changed, 91 insertions, 15 deletions
diff --git a/http-internal.h b/http-internal.h
index 94059065..2d0ae8fc 100644
--- a/http-internal.h
+++ b/http-internal.h
@@ -215,6 +215,9 @@ void evhttp_start_write_(struct evhttp_connection *);
void evhttp_response_code_(struct evhttp_request *, int, const char *);
void evhttp_send_page_(struct evhttp_request *, struct evbuffer *);
+/* [] has been stripped */
+#define _EVHTTP_URI_HOST_HAS_BRACKETS 0x02
+
EVENT2_EXPORT_SYMBOL
int evhttp_decode_uri_internal(const char *uri, size_t length,
char *ret, int decode_plus);
diff --git a/http.c b/http.c
index 8afb3600..45441f22 100644
--- a/http.c
+++ b/http.c
@@ -180,7 +180,7 @@ extern int debug;
static evutil_socket_t create_bind_socket_nonblock(struct evutil_addrinfo *, int reuse);
static evutil_socket_t bind_socket(const char *, ev_uint16_t, int reuse);
static void name_from_addr(struct sockaddr *, ev_socklen_t, char **, char **);
-static struct evhttp_uri *evhttp_uri_parse_authority(char *source_uri);
+static struct evhttp_uri *evhttp_uri_parse_authority(char *source_uri, unsigned flags);
static int evhttp_associate_new_request_with_connection(
struct evhttp_connection *evcon);
static void evhttp_connection_start_detectclose(
@@ -2055,7 +2055,7 @@ evhttp_parse_request_line(struct evhttp_request *req, char *line, size_t len)
}
if (type == EVHTTP_REQ_CONNECT) {
- if ((req->uri_elems = evhttp_uri_parse_authority(req->uri)) == NULL) {
+ if ((req->uri_elems = evhttp_uri_parse_authority(req->uri, 0)) == NULL) {
return -1;
}
} else {
@@ -4910,9 +4910,11 @@ bracket_addr_ok(const char *s, const char *eos)
}
static int
-parse_authority(struct evhttp_uri *uri, char *s, char *eos)
+parse_authority(struct evhttp_uri *uri, char *s, char *eos, unsigned *flags)
{
+ size_t len;
char *cp, *port;
+
EVUTIL_ASSERT(eos);
if (eos == s) {
uri->host = mm_strdup("");
@@ -4952,22 +4954,31 @@ parse_authority(struct evhttp_uri *uri, char *s, char *eos)
/* Now, cp..eos holds the "host" port, which can be an IPv4Address,
* an IP-Literal, or a reg-name */
EVUTIL_ASSERT(eos >= cp);
+ len = eos-cp;
if (*cp == '[' && eos >= cp+2 && *(eos-1) == ']') {
/* IPv6address, IP-Literal, or junk. */
if (! bracket_addr_ok(cp, eos))
return -1;
+ if (*flags & EVHTTP_URI_HOST_STRIP_BRACKETS)
+ len = eos-cp-2;
} else {
/* Make sure the host part is ok. */
if (! regname_ok(cp,eos)) /* Match IPv4Address or reg-name */
return -1;
}
- uri->host = mm_malloc(eos-cp+1);
+
+ uri->host = mm_malloc(len+1);
if (uri->host == NULL) {
event_warn("%s: malloc", __func__);
return -1;
}
- memcpy(uri->host, cp, eos-cp);
- uri->host[eos-cp] = '\0';
+ if (*cp == '[' && *flags & EVHTTP_URI_HOST_STRIP_BRACKETS) {
+ memcpy(uri->host, cp+1, len);
+ *flags |= _EVHTTP_URI_HOST_HAS_BRACKETS;
+ } else {
+ memcpy(uri->host, cp, len);
+ }
+ uri->host[len] = '\0';
return 0;
}
@@ -5103,7 +5114,7 @@ evhttp_uri_parse_with_flags(const char *source_uri, unsigned flags)
readp += 2;
authority = readp;
path = end_of_authority(readp);
- if (parse_authority(uri, authority, path) < 0)
+ if (parse_authority(uri, authority, path, &uri->flags) < 0)
goto err;
readp = path;
got_authority = 1;
@@ -5182,7 +5193,7 @@ err:
}
static struct evhttp_uri *
-evhttp_uri_parse_authority(char *source_uri)
+evhttp_uri_parse_authority(char *source_uri, unsigned flags)
{
struct evhttp_uri *uri = mm_calloc(1, sizeof(struct evhttp_uri));
char *end;
@@ -5192,10 +5203,10 @@ evhttp_uri_parse_authority(char *source_uri)
goto err;
}
uri->port = -1;
- uri->flags = 0;
+ uri->flags = flags;
end = end_of_authority(source_uri);
- if (parse_authority(uri, source_uri, end) < 0)
+ if (parse_authority(uri, source_uri, end, &uri->flags) < 0)
goto err;
uri->path = mm_strdup("");
@@ -5254,7 +5265,13 @@ evhttp_uri_join(struct evhttp_uri *uri, char *buf, size_t limit)
evbuffer_add(tmp, "//", 2);
if (uri->userinfo)
evbuffer_add_printf(tmp,"%s@", uri->userinfo);
- URI_ADD_(host);
+ if (uri->flags & _EVHTTP_URI_HOST_HAS_BRACKETS) {
+ evbuffer_add(tmp, "[", 1);
+ URI_ADD_(host);
+ evbuffer_add(tmp, "]", 1);
+ } else {
+ URI_ADD_(host);
+ }
if (uri->port >= 0)
evbuffer_add_printf(tmp,":%d", uri->port);
@@ -5284,7 +5301,7 @@ evhttp_uri_join(struct evhttp_uri *uri, char *buf, size_t limit)
evbuffer_free(tmp);
return NULL;
}
- evbuffer_remove(tmp, buf, joined_size);
+ evbuffer_remove(tmp, buf, joined_size);
output = buf;
err:
@@ -5363,17 +5380,39 @@ evhttp_uri_set_userinfo(struct evhttp_uri *uri, const char *userinfo)
int
evhttp_uri_set_host(struct evhttp_uri *uri, const char *host)
{
+ size_t len = 0;
+
if (host) {
+ len = strlen(host);
+
if (host[0] == '[') {
- if (! bracket_addr_ok(host, host+strlen(host)))
+ if (! bracket_addr_ok(host, host+len))
return -1;
} else {
- if (! regname_ok(host, host+strlen(host)))
+ if (! regname_ok(host, host+len))
return -1;
}
}
- URI_SET_STR_(host);
+ if (host && host[0] == '[' && uri->flags & EVHTTP_URI_HOST_STRIP_BRACKETS) {
+ char *new_host;
+
+ len -= 2;
+ new_host = mm_realloc(uri->host, len+1);
+ if (!new_host) {
+ free(uri->host);
+ uri->host = NULL;
+ } else {
+ memcpy(new_host, host+1, len);
+ new_host[len] = '\0';
+ uri->host = new_host;
+ }
+ uri->flags |= _EVHTTP_URI_HOST_HAS_BRACKETS;
+ } else {
+ URI_SET_STR_(host);
+ uri->flags &= ~_EVHTTP_URI_HOST_HAS_BRACKETS;
+ }
+
return 0;
}
int
diff --git a/include/event2/http.h b/include/event2/http.h
index aef8a45b..d32bd0b3 100644
--- a/include/event2/http.h
+++ b/include/event2/http.h
@@ -1378,6 +1378,15 @@ struct evhttp_uri *evhttp_uri_parse_with_flags(const char *source_uri,
* </ul>
*/
#define EVHTTP_URI_NONCONFORMANT 0x01
+/**
+ * Strip brackets from the IPv6 address and only for evhttp_uri_get_host(),
+ * evhttp_uri_join() returns the host with brackets.
+ *
+ * Thus you can use host part of the evhttp_uri for getaddrinfo().
+ *
+ * @see also _EVHTTP_URI_HOST_HAS_BRACKETS
+ */
+#define EVHTTP_URI_HOST_STRIP_BRACKETS 0x04
/** Alias for evhttp_uri_parse_with_flags(source_uri, 0) */
EVENT2_EXPORT_SYMBOL
diff --git a/test/regress_http.c b/test/regress_http.c
index b952ff47..959fcc28 100644
--- a/test/regress_http.c
+++ b/test/regress_http.c
@@ -2835,6 +2835,8 @@ http_parse_uri_test(void *ptr)
nonconform ? EVHTTP_URI_NONCONFORMANT : 0;
struct evhttp_uri *uri = NULL;
char url_tmp[4096];
+#define URI_PARSE_FLAGS(uri, flags) \
+ evhttp_uri_parse_with_flags((uri), flags)
#define URI_PARSE(uri) \
evhttp_uri_parse_with_flags((uri), parse_flags)
@@ -3205,6 +3207,29 @@ http_parse_uri_test(void *ptr)
tt_want(strcmp(evhttp_uri_get_fragment(uri), "fr?ed") == 0);
TT_URI("#fr?ed");
evhttp_uri_free(uri);
+
+ // EVHTTP_URI_HOST_STRIP_BRACKETS
+ uri = URI_PARSE_FLAGS("ftp://[ff00::127.0.0.1]/?q=test", EVHTTP_URI_HOST_STRIP_BRACKETS);
+ tt_want(strcmp(evhttp_uri_get_scheme(uri), "ftp") == 0);
+ tt_want(strcmp(evhttp_uri_get_host(uri), "ff00::127.0.0.1") == 0);
+ tt_want(strcmp(evhttp_uri_get_path(uri), "/") == 0);
+ tt_want(strcmp(evhttp_uri_get_query(uri), "q=test") == 0);
+ tt_want(evhttp_uri_get_userinfo(uri) == NULL);
+ tt_want(evhttp_uri_get_port(uri) == -1);
+ tt_want(evhttp_uri_get_fragment(uri) == NULL);
+ TT_URI("ftp://[ff00::127.0.0.1]/?q=test");
+
+ tt_want(0 == evhttp_uri_set_host(uri, "foo"));
+ tt_want(strcmp(evhttp_uri_get_host(uri), "foo") == 0);
+ TT_URI("ftp://foo/?q=test");
+
+ tt_want(0 == evhttp_uri_set_host(uri, "[ff00::127.0.0.1]"));
+ tt_want(strcmp(evhttp_uri_get_host(uri), "ff00::127.0.0.1") == 0);
+ TT_URI("ftp://[ff00::127.0.0.1]/?q=test");
+
+ evhttp_uri_free(uri);
+
+#undef URI_PARSE_FLAGS
#undef URI_PARSE
#undef TT_URI
#undef BAD