summaryrefslogtreecommitdiffstats
path: root/web/server/h2o/libh2o/t/00unit/lib/common/url.c
diff options
context:
space:
mode:
Diffstat (limited to 'web/server/h2o/libh2o/t/00unit/lib/common/url.c')
-rw-r--r--web/server/h2o/libh2o/t/00unit/lib/common/url.c662
1 files changed, 662 insertions, 0 deletions
diff --git a/web/server/h2o/libh2o/t/00unit/lib/common/url.c b/web/server/h2o/libh2o/t/00unit/lib/common/url.c
new file mode 100644
index 00000000..ce167600
--- /dev/null
+++ b/web/server/h2o/libh2o/t/00unit/lib/common/url.c
@@ -0,0 +1,662 @@
+/*
+ * Copyright (c) 2014,2015 DeNA Co., Ltd.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to
+ * deal in the Software without restriction, including without limitation the
+ * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
+ * sell copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ */
+#include "../../test.h"
+#include "../../../../lib/common/url.c"
+
+static void test_normalize_path(void)
+{
+ h2o_mem_pool_t pool;
+
+ h2o_mem_init_pool(&pool);
+
+ size_t q;
+ size_t *norm_indexes = NULL;
+ h2o_iovec_t input;
+ h2o_iovec_t b;
+
+ input = h2o_iovec_init(NULL, 0);
+ b = h2o_url_normalize_path(&pool, input.base, input.len, &q, &norm_indexes);
+ ok(b.len == 1);
+ ok(memcmp(b.base, H2O_STRLIT("/")) == 0);
+ ok(q == SIZE_MAX);
+ ok(norm_indexes == NULL);
+
+ input = h2o_iovec_init(H2O_STRLIT("a"));
+ b = h2o_url_normalize_path(&pool, input.base, input.len, &q, &norm_indexes);
+ ok(b.len == 2);
+ ok(memcmp(b.base, H2O_STRLIT("/a")) == 0);
+ ok(q == SIZE_MAX);
+ ok(norm_indexes != NULL);
+ ok(norm_indexes[0] == 0);
+ ok(norm_indexes[1] == 1);
+ norm_indexes = NULL;
+
+ input = h2o_iovec_init(H2O_STRLIT("aa"));
+ b = h2o_url_normalize_path(&pool, input.base, input.len, &q, &norm_indexes);
+ ok(b.len == 3);
+ ok(memcmp(b.base, H2O_STRLIT("/aa")) == 0);
+ ok(q == SIZE_MAX);
+ ok(norm_indexes != NULL);
+ ok(norm_indexes[0] == 0);
+ ok(norm_indexes[1] == 1);
+ ok(norm_indexes[2] == 2);
+ norm_indexes = NULL;
+
+ input = h2o_iovec_init(H2O_STRLIT("/"));
+ b = h2o_url_normalize_path(&pool, input.base, input.len, &q, &norm_indexes);
+ ok(b.len == 1);
+ ok(memcmp(b.base, H2O_STRLIT("/")) == 0);
+ ok(q == SIZE_MAX);
+ ok(norm_indexes == NULL);
+
+ input = h2o_iovec_init(H2O_STRLIT("/."));
+ b = h2o_url_normalize_path(&pool, input.base, input.len, &q, &norm_indexes);
+ ok(b.len == 1);
+ ok(memcmp(b.base, H2O_STRLIT("/")) == 0);
+ ok(q == SIZE_MAX);
+ ok(norm_indexes != NULL);
+ ok(norm_indexes[0] == 1);
+ norm_indexes = NULL;
+
+ input = h2o_iovec_init(H2O_STRLIT("/./"));
+ b = h2o_url_normalize_path(&pool, input.base, input.len, &q, &norm_indexes);
+ ok(b.len == 1);
+ ok(memcmp(b.base, H2O_STRLIT("/")) == 0);
+ ok(q == SIZE_MAX);
+ ok(norm_indexes != NULL);
+ ok(norm_indexes[0] == 1);
+ norm_indexes = NULL;
+
+ input = h2o_iovec_init(H2O_STRLIT("/.."));
+ b = h2o_url_normalize_path(&pool, input.base, input.len, &q, &norm_indexes);
+ ok(b.len == 1);
+ ok(memcmp(b.base, H2O_STRLIT("/")) == 0);
+ ok(q == SIZE_MAX);
+ ok(norm_indexes != NULL);
+ ok(norm_indexes[0] == 1);
+ norm_indexes = NULL;
+
+ input = h2o_iovec_init(H2O_STRLIT("/../"));
+ b = h2o_url_normalize_path(&pool, input.base, input.len, &q, &norm_indexes);
+ ok(b.len == 1);
+ ok(memcmp(b.base, H2O_STRLIT("/")) == 0);
+ ok(q == SIZE_MAX);
+ ok(norm_indexes != NULL);
+ ok(norm_indexes[0] == 1);
+ norm_indexes = NULL;
+
+ input = h2o_iovec_init(H2O_STRLIT("/abc"));
+ b = h2o_url_normalize_path(&pool, input.base, input.len, &q, &norm_indexes);
+ ok(b.len == 4);
+ ok(memcmp(b.base, H2O_STRLIT("/abc")) == 0);
+ ok(q == SIZE_MAX);
+ ok(norm_indexes == NULL);
+
+ input = h2o_iovec_init(H2O_STRLIT("/abc"));
+ b = h2o_url_normalize_path(&pool, input.base, input.len, &q, &norm_indexes);
+ ok(b.len == 4);
+ ok(memcmp(b.base, H2O_STRLIT("/abc")) == 0);
+ ok(q == SIZE_MAX);
+ ok(norm_indexes == NULL);
+
+ input = h2o_iovec_init(H2O_STRLIT("/abc/../def"));
+ b = h2o_url_normalize_path(&pool, input.base, input.len, &q, &norm_indexes);
+ ok(b.len == 4);
+ ok(memcmp(b.base, H2O_STRLIT("/def")) == 0);
+ ok(q == SIZE_MAX);
+ ok(norm_indexes != NULL);
+ ok(norm_indexes[0] == 1);
+ ok(norm_indexes[1] == 9);
+ ok(norm_indexes[2] == 10);
+ ok(norm_indexes[3] == 11);
+ norm_indexes = NULL;
+
+ input = h2o_iovec_init(H2O_STRLIT("/abc/../../def"));
+ b = h2o_url_normalize_path(&pool, input.base, input.len, &q, &norm_indexes);
+ ok(b.len == 4);
+ ok(memcmp(b.base, H2O_STRLIT("/def")) == 0);
+ ok(q == SIZE_MAX);
+ ok(norm_indexes != NULL);
+ ok(norm_indexes[0] == 1);
+ ok(norm_indexes[1] == 12);
+ ok(norm_indexes[2] == 13);
+ ok(norm_indexes[3] == 14);
+ norm_indexes = NULL;
+
+ input = h2o_iovec_init(H2O_STRLIT("/abc/./def"));
+ b = h2o_url_normalize_path(&pool, input.base, input.len, &q, &norm_indexes);
+ ok(b.len == 8);
+ ok(memcmp(b.base, H2O_STRLIT("/abc/def")) == 0);
+ ok(q == SIZE_MAX);
+ ok(norm_indexes != NULL);
+ ok(norm_indexes[0] == 1);
+ ok(norm_indexes[1] == 2);
+ ok(norm_indexes[2] == 3);
+ ok(norm_indexes[3] == 4);
+ ok(norm_indexes[4] == 5);
+ ok(norm_indexes[5] == 8);
+ ok(norm_indexes[6] == 9);
+ ok(norm_indexes[7] == 10);
+ norm_indexes = NULL;
+
+ input = h2o_iovec_init(H2O_STRLIT("/abc/././def"));
+ b = h2o_url_normalize_path(&pool, input.base, input.len, &q, &norm_indexes);
+ ok(b.len == 8);
+ ok(memcmp(b.base, H2O_STRLIT("/abc/def")) == 0);
+ ok(q == SIZE_MAX);
+ ok(norm_indexes != NULL);
+ ok(norm_indexes[0] == 1);
+ ok(norm_indexes[1] == 2);
+ ok(norm_indexes[2] == 3);
+ ok(norm_indexes[3] == 4);
+ ok(norm_indexes[4] == 5);
+ ok(norm_indexes[5] == 10);
+ ok(norm_indexes[6] == 11);
+ ok(norm_indexes[7] == 12);
+ norm_indexes = NULL;
+
+ input = h2o_iovec_init(H2O_STRLIT("/abc/def/ghi/../.."));
+ b = h2o_url_normalize_path(&pool, input.base, input.len, &q, &norm_indexes);
+ ok(b.len == 5);
+ ok(memcmp(b.base, H2O_STRLIT("/abc/")) == 0);
+ ok(q == SIZE_MAX);
+ ok(norm_indexes != NULL);
+ ok(norm_indexes[0] == 1);
+ ok(norm_indexes[1] == 2);
+ ok(norm_indexes[2] == 3);
+ ok(norm_indexes[3] == 4);
+ ok(norm_indexes[4] == 5);
+ norm_indexes = NULL;
+
+ input = h2o_iovec_init(H2O_STRLIT("/abc/def/./."));
+ b = h2o_url_normalize_path(&pool, input.base, input.len, &q, &norm_indexes);
+ ok(b.len == 9);
+ ok(memcmp(b.base, H2O_STRLIT("/abc/def/")) == 0);
+ ok(q == SIZE_MAX);
+ ok(norm_indexes != NULL);
+ ok(norm_indexes[0] == 1);
+ ok(norm_indexes[1] == 2);
+ ok(norm_indexes[2] == 3);
+ ok(norm_indexes[3] == 4);
+ ok(norm_indexes[4] == 5);
+ ok(norm_indexes[5] == 6);
+ ok(norm_indexes[6] == 7);
+ ok(norm_indexes[7] == 8);
+ norm_indexes = NULL;
+
+ input = h2o_iovec_init(H2O_STRLIT("/abc/def/ghi/../."));
+ b = h2o_url_normalize_path(&pool, input.base, input.len, &q, &norm_indexes);
+ ok(b.len == 9);
+ ok(memcmp(b.base, H2O_STRLIT("/abc/def/")) == 0);
+ ok(q == SIZE_MAX);
+ ok(norm_indexes != NULL);
+ ok(norm_indexes[0] == 1);
+ ok(norm_indexes[1] == 2);
+ ok(norm_indexes[2] == 3);
+ ok(norm_indexes[3] == 4);
+ ok(norm_indexes[4] == 5);
+ ok(norm_indexes[5] == 6);
+ ok(norm_indexes[6] == 7);
+ ok(norm_indexes[7] == 8);
+ norm_indexes = NULL;
+
+ input = h2o_iovec_init(H2O_STRLIT("/abc/def/./.."));
+ b = h2o_url_normalize_path(&pool, input.base, input.len, &q, &norm_indexes);
+ ok(b.len == 5);
+ ok(memcmp(b.base, H2O_STRLIT("/abc/")) == 0);
+ ok(q == SIZE_MAX);
+ ok(norm_indexes != NULL);
+ ok(norm_indexes[0] == 1);
+ ok(norm_indexes[1] == 2);
+ ok(norm_indexes[2] == 3);
+ ok(norm_indexes[3] == 4);
+ ok(norm_indexes[4] == 5);
+ norm_indexes = NULL;
+
+ input = h2o_iovec_init(H2O_STRLIT("/abc/def/.."));
+ b = h2o_url_normalize_path(&pool, input.base, input.len, &q, &norm_indexes);
+ ok(b.len == 5);
+ ok(memcmp(b.base, H2O_STRLIT("/abc/")) == 0);
+ ok(q == SIZE_MAX);
+ ok(norm_indexes != NULL);
+ ok(norm_indexes[0] == 1);
+ ok(norm_indexes[1] == 2);
+ ok(norm_indexes[2] == 3);
+ ok(norm_indexes[3] == 4);
+ ok(norm_indexes[4] == 5);
+ norm_indexes = NULL;
+
+ input = h2o_iovec_init(H2O_STRLIT("/abc/def/."));
+ b = h2o_url_normalize_path(&pool, input.base, input.len, &q, &norm_indexes);
+ ok(b.len == 9);
+ ok(memcmp(b.base, H2O_STRLIT("/abc/def/")) == 0);
+ ok(q == SIZE_MAX);
+ ok(norm_indexes != NULL);
+ ok(norm_indexes[0] == 1);
+ ok(norm_indexes[1] == 2);
+ ok(norm_indexes[2] == 3);
+ ok(norm_indexes[3] == 4);
+ ok(norm_indexes[4] == 5);
+ ok(norm_indexes[5] == 6);
+ ok(norm_indexes[6] == 7);
+ norm_indexes = NULL;
+
+ input = h2o_iovec_init(H2O_STRLIT("/abc?xx"));
+ b = h2o_url_normalize_path(&pool, input.base, input.len, &q, &norm_indexes);
+ ok(b.len == 4);
+ ok(memcmp(b.base, H2O_STRLIT("/abc")) == 0);
+ ok(q == 4);
+ ok(norm_indexes == NULL);
+
+ input = h2o_iovec_init(H2O_STRLIT("/abc/../def?xx"));
+ b = h2o_url_normalize_path(&pool, input.base, input.len, &q, &norm_indexes);
+ ok(b.len == 4);
+ ok(memcmp(b.base, H2O_STRLIT("/def")) == 0);
+ ok(q == 11);
+ ok(norm_indexes != NULL);
+ ok(norm_indexes[0] == 1);
+ ok(norm_indexes[1] == 9);
+ ok(norm_indexes[2] == 10);
+ ok(norm_indexes[3] == 11);
+ norm_indexes = NULL;
+
+ input = h2o_iovec_init(H2O_STRLIT("/a%62c"));
+ b = h2o_url_normalize_path(&pool, input.base, input.len, &q, &norm_indexes);
+ ok(b.len == 4);
+ ok(memcmp(b.base, H2O_STRLIT("/abc")) == 0);
+ ok(q == SIZE_MAX);
+ ok(norm_indexes != NULL);
+ ok(norm_indexes[0] == 1);
+ ok(norm_indexes[1] == 2);
+ ok(norm_indexes[2] == 5);
+ ok(norm_indexes[3] == 6);
+ norm_indexes = NULL;
+
+ input = h2o_iovec_init(H2O_STRLIT("/a%6"));
+ b = h2o_url_normalize_path(&pool, input.base, input.len, &q, &norm_indexes);
+ ok(b.len == 4);
+ ok(memcmp(b.base, H2O_STRLIT("/a%6")) == 0);
+ ok(q == SIZE_MAX);
+ ok(norm_indexes != NULL);
+ ok(norm_indexes[0] == 1);
+ ok(norm_indexes[1] == 2);
+ ok(norm_indexes[2] == 3);
+ ok(norm_indexes[3] == 4);
+ norm_indexes = NULL;
+
+ input = h2o_iovec_init(H2O_STRLIT("/a%6?"));
+ b = h2o_url_normalize_path(&pool, input.base, input.len, &q, &norm_indexes);
+ ok(b.len == 4);
+ ok(memcmp(b.base, H2O_STRLIT("/a%6")) == 0);
+ ok(q == 4);
+ ok(norm_indexes != NULL);
+ ok(norm_indexes[0] == 1);
+ ok(norm_indexes[1] == 2);
+ ok(norm_indexes[2] == 3);
+ ok(norm_indexes[3] == 4);
+ norm_indexes = NULL;
+
+ input = h2o_iovec_init(H2O_STRLIT("/%25"));
+ b = h2o_url_normalize_path(&pool, input.base, input.len, &q, &norm_indexes);
+ ok(b.len == 2);
+ ok(memcmp(b.base, H2O_STRLIT("/%")) == 0);
+ ok(q == SIZE_MAX);
+ ok(norm_indexes != NULL);
+ ok(norm_indexes[0] == 1);
+ ok(norm_indexes[1] == 4);
+ norm_indexes = NULL;
+
+ input = h2o_iovec_init(H2O_STRLIT("/abc//"));
+ b = h2o_url_normalize_path(&pool, input.base, input.len, &q, &norm_indexes);
+ ok(b.len == 6);
+ ok(memcmp(b.base, H2O_STRLIT("/abc//")) == 0);
+ ok(q == SIZE_MAX);
+ ok(norm_indexes == NULL);
+
+ input = h2o_iovec_init(H2O_STRLIT("/abc//d"));
+ b = h2o_url_normalize_path(&pool, input.base, input.len, &q, &norm_indexes);
+ ok(b.len == 7);
+ ok(memcmp(b.base, H2O_STRLIT("/abc//d")) == 0);
+ ok(q == SIZE_MAX);
+ ok(norm_indexes == NULL);
+
+ input = h2o_iovec_init(H2O_STRLIT("//"));
+ b = h2o_url_normalize_path(&pool, input.base, input.len, &q, &norm_indexes);
+ ok(b.len == 2);
+ ok(memcmp(b.base, H2O_STRLIT("//")) == 0);
+ ok(q == SIZE_MAX);
+ ok(norm_indexes == NULL);
+
+ input = h2o_iovec_init(H2O_STRLIT("//abc"));
+ b = h2o_url_normalize_path(&pool, input.base, input.len, &q, &norm_indexes);
+ ok(b.len == 5);
+ ok(memcmp(b.base, H2O_STRLIT("//abc")) == 0);
+ ok(q == SIZE_MAX);
+ ok(norm_indexes == NULL);
+
+ h2o_mem_clear_pool(&pool);
+}
+
+static void test_hostport(void)
+{
+ h2o_iovec_t input, host;
+ uint16_t port;
+ const char *ret;
+
+ input = h2o_iovec_init(H2O_STRLIT("127.0.0.1"));
+ ret = h2o_url_parse_hostport(input.base, input.len, &host, &port);
+ ok(ret == input.base + input.len);
+ ok(h2o_memis(host.base, host.len, H2O_STRLIT("127.0.0.1")));
+ ok(port == 65535);
+
+ input = h2o_iovec_init(H2O_STRLIT("127.0.0.1/"));
+ ret = h2o_url_parse_hostport(input.base, input.len, &host, &port);
+ ok(strcmp(ret, "/") == 0);
+ ok(h2o_memis(host.base, host.len, H2O_STRLIT("127.0.0.1")));
+ ok(port == 65535);
+
+ input = h2o_iovec_init(H2O_STRLIT("127.0.0.1:8081/"));
+ ret = h2o_url_parse_hostport(input.base, input.len, &host, &port);
+ ok(strcmp(ret, "/") == 0);
+ ok(h2o_memis(host.base, host.len, H2O_STRLIT("127.0.0.1")));
+ ok(port == 8081);
+
+ input = h2o_iovec_init(H2O_STRLIT("[::ffff:192.0.2.1]:8081/"));
+ ret = h2o_url_parse_hostport(input.base, input.len, &host, &port);
+ ok(strcmp(ret, "/") == 0);
+ ok(h2o_memis(host.base, host.len, H2O_STRLIT("::ffff:192.0.2.1")));
+ ok(port == 8081);
+
+ input = h2o_iovec_init(H2O_STRLIT("[::ffff:192.0.2.1:8081/"));
+ ret = h2o_url_parse_hostport(input.base, input.len, &host, &port);
+ ok(ret == NULL);
+
+ input = h2o_iovec_init(H2O_STRLIT(":8081/"));
+ ret = h2o_url_parse_hostport(input.base, input.len, &host, &port);
+ ok(ret == NULL);
+
+ input = h2o_iovec_init(H2O_STRLIT("[]:8081/"));
+ ret = h2o_url_parse_hostport(input.base, input.len, &host, &port);
+ ok(ret == NULL);
+}
+
+static void test_parse(void)
+{
+ h2o_url_t parsed;
+ int ret;
+
+ ret = h2o_url_parse("http://example.com/abc", SIZE_MAX, &parsed);
+ ok(ret == 0);
+ ok(parsed.scheme == &H2O_URL_SCHEME_HTTP);
+ ok(h2o_memis(parsed.authority.base, parsed.authority.len, H2O_STRLIT("example.com")));
+ ok(h2o_memis(parsed.host.base, parsed.host.len, H2O_STRLIT("example.com")));
+ ok(parsed._port == 65535);
+ ok(h2o_url_get_port(&parsed) == 80);
+ ok(h2o_memis(parsed.path.base, parsed.path.len, H2O_STRLIT("/abc")));
+
+ ret = h2o_url_parse("http://example.com", SIZE_MAX, &parsed);
+ ok(ret == 0);
+ ok(parsed.scheme == &H2O_URL_SCHEME_HTTP);
+ ok(h2o_memis(parsed.authority.base, parsed.authority.len, H2O_STRLIT("example.com")));
+ ok(h2o_memis(parsed.host.base, parsed.host.len, H2O_STRLIT("example.com")));
+ ok(parsed._port == 65535);
+ ok(h2o_url_get_port(&parsed) == 80);
+ ok(h2o_memis(parsed.path.base, parsed.path.len, H2O_STRLIT("/")));
+
+ ret = h2o_url_parse("http://example.com:81/abc", SIZE_MAX, &parsed);
+ ok(ret == 0);
+ ok(parsed.scheme == &H2O_URL_SCHEME_HTTP);
+ ok(h2o_memis(parsed.authority.base, parsed.authority.len, H2O_STRLIT("example.com:81")));
+ ok(h2o_memis(parsed.host.base, parsed.host.len, H2O_STRLIT("example.com")));
+ ok(parsed._port == 81);
+ ok(h2o_url_get_port(&parsed) == 81);
+ ok(h2o_memis(parsed.path.base, parsed.path.len, H2O_STRLIT("/abc")));
+
+ ret = h2o_url_parse("http://example.com:81", SIZE_MAX, &parsed);
+ ok(ret == 0);
+ ok(parsed.scheme == &H2O_URL_SCHEME_HTTP);
+ ok(h2o_memis(parsed.authority.base, parsed.authority.len, H2O_STRLIT("example.com:81")));
+ ok(h2o_memis(parsed.host.base, parsed.host.len, H2O_STRLIT("example.com")));
+ ok(parsed._port == 81);
+ ok(h2o_url_get_port(&parsed) == 81);
+ ok(h2o_memis(parsed.path.base, parsed.path.len, H2O_STRLIT("/")));
+
+ ret = h2o_url_parse("https://example.com/abc", SIZE_MAX, &parsed);
+ ok(ret == 0);
+ ok(parsed.scheme == &H2O_URL_SCHEME_HTTPS);
+ ok(h2o_memis(parsed.authority.base, parsed.authority.len, H2O_STRLIT("example.com")));
+ ok(h2o_memis(parsed.host.base, parsed.host.len, H2O_STRLIT("example.com")));
+ ok(parsed._port == 65535);
+ ok(h2o_url_get_port(&parsed) == 443);
+ ok(h2o_memis(parsed.path.base, parsed.path.len, H2O_STRLIT("/abc")));
+
+ ret = h2o_url_parse("http:/abc", SIZE_MAX, &parsed);
+ ok(ret != 0);
+
+ ret = h2o_url_parse("ftp://example.com/abc", SIZE_MAX, &parsed);
+ ok(ret != 0);
+
+ ret = h2o_url_parse("http://abc:111111/def", SIZE_MAX, &parsed);
+ ok(ret != 0);
+
+ ret = h2o_url_parse("http://[::ffff:192.0.2.128]", SIZE_MAX, &parsed);
+ ok(ret == 0);
+ ok(parsed.scheme == &H2O_URL_SCHEME_HTTP);
+ ok(h2o_memis(parsed.authority.base, parsed.authority.len, H2O_STRLIT("[::ffff:192.0.2.128]")));
+ ok(h2o_memis(parsed.host.base, parsed.host.len, H2O_STRLIT("::ffff:192.0.2.128")));
+ ok(parsed._port == 65535);
+ ok(h2o_url_get_port(&parsed) == 80);
+ ok(h2o_memis(parsed.path.base, parsed.path.len, H2O_STRLIT("/")));
+
+ ret = h2o_url_parse("https://[::ffff:192.0.2.128]/abc", SIZE_MAX, &parsed);
+ ok(ret == 0);
+ ok(parsed.scheme == &H2O_URL_SCHEME_HTTPS);
+ ok(h2o_memis(parsed.authority.base, parsed.authority.len, H2O_STRLIT("[::ffff:192.0.2.128]")));
+ ok(h2o_memis(parsed.host.base, parsed.host.len, H2O_STRLIT("::ffff:192.0.2.128")));
+ ok(parsed._port == 65535);
+ ok(h2o_url_get_port(&parsed) == 443);
+ ok(h2o_memis(parsed.path.base, parsed.path.len, H2O_STRLIT("/abc")));
+
+ ret = h2o_url_parse("https://[::ffff:192.0.2.128]:111/abc", SIZE_MAX, &parsed);
+ ok(ret == 0);
+ ok(parsed.scheme == &H2O_URL_SCHEME_HTTPS);
+ ok(h2o_memis(parsed.authority.base, parsed.authority.len, H2O_STRLIT("[::ffff:192.0.2.128]:111")));
+ ok(h2o_memis(parsed.host.base, parsed.host.len, H2O_STRLIT("::ffff:192.0.2.128")));
+ ok(parsed._port == 111);
+ ok(h2o_url_get_port(&parsed) == 111);
+ ok(h2o_memis(parsed.path.base, parsed.path.len, H2O_STRLIT("/abc")));
+}
+
+static void test_parse_relative(void)
+{
+ h2o_url_t parsed;
+ int ret;
+
+ memset(&parsed, 0x55, sizeof(parsed));
+ ret = h2o_url_parse_relative("abc", SIZE_MAX, &parsed);
+ ok(ret == 0);
+ ok(parsed.scheme == NULL);
+ ok(parsed.authority.base == NULL);
+ ok(parsed.host.base == NULL);
+ ok(parsed._port == 65535);
+ ok(h2o_memis(parsed.path.base, parsed.path.len, H2O_STRLIT("abc")));
+
+ memset(&parsed, 0x55, sizeof(parsed));
+ ret = h2o_url_parse_relative("/abc", SIZE_MAX, &parsed);
+ ok(ret == 0);
+ ok(parsed.scheme == NULL);
+ ok(parsed.authority.base == NULL);
+ ok(parsed.host.base == NULL);
+ ok(parsed._port == 65535);
+ ok(h2o_memis(parsed.path.base, parsed.path.len, H2O_STRLIT("/abc")));
+
+ memset(&parsed, 0x55, sizeof(parsed));
+ ret = h2o_url_parse_relative("http:abc", SIZE_MAX, &parsed);
+ ok(ret == 0);
+ ok(parsed.scheme == &H2O_URL_SCHEME_HTTP);
+ ok(parsed.authority.base == NULL);
+ ok(parsed.host.base == NULL);
+ ok(parsed._port == 65535);
+ ok(h2o_memis(parsed.path.base, parsed.path.len, H2O_STRLIT("abc")));
+
+ memset(&parsed, 0x55, sizeof(parsed));
+ ret = h2o_url_parse_relative("//host", SIZE_MAX, &parsed);
+ ok(ret == 0);
+ ok(parsed.scheme == NULL);
+ ok(h2o_memis(parsed.authority.base, parsed.authority.len, H2O_STRLIT("host")));
+ ok(h2o_memis(parsed.host.base, parsed.host.len, H2O_STRLIT("host")));
+ ok(parsed._port == 65535);
+ ok(h2o_memis(parsed.path.base, parsed.path.len, H2O_STRLIT("/")));
+
+ memset(&parsed, 0x55, sizeof(parsed));
+ ret = h2o_url_parse_relative("//host:12345/path", SIZE_MAX, &parsed);
+ ok(ret == 0);
+ ok(parsed.scheme == NULL);
+ ok(h2o_memis(parsed.authority.base, parsed.authority.len, H2O_STRLIT("host:12345")));
+ ok(h2o_memis(parsed.host.base, parsed.host.len, H2O_STRLIT("host")));
+ ok(parsed._port == 12345);
+ ok(h2o_memis(parsed.path.base, parsed.path.len, H2O_STRLIT("/path")));
+
+ memset(&parsed, 0x55, sizeof(parsed));
+ ret = h2o_url_parse_relative("https://host:12345/path", SIZE_MAX, &parsed);
+ ok(ret == 0);
+ ok(parsed.scheme == &H2O_URL_SCHEME_HTTPS);
+ ok(h2o_memis(parsed.authority.base, parsed.authority.len, H2O_STRLIT("host:12345")));
+ ok(h2o_memis(parsed.host.base, parsed.host.len, H2O_STRLIT("host")));
+ ok(parsed._port == 12345);
+ ok(h2o_memis(parsed.path.base, parsed.path.len, H2O_STRLIT("/path")));
+}
+
+static void test_resolve(void)
+{
+ h2o_mem_pool_t pool;
+ h2o_url_t base, relative, resolved;
+ h2o_iovec_t final;
+ int ret;
+
+ h2o_mem_init_pool(&pool);
+
+ ret = h2o_url_parse("http://example.com/dir/index.html", SIZE_MAX, &base);
+ ok(ret == 0);
+
+ ret = h2o_url_parse_relative("../assets/jquery.js", SIZE_MAX, &relative);
+ ok(ret == 0);
+ final = h2o_url_resolve(&pool, &base, &relative, &resolved);
+ ok(h2o_memis(final.base, final.len, H2O_STRLIT("http://example.com/assets/jquery.js")));
+ ok(resolved.scheme == &H2O_URL_SCHEME_HTTP);
+ ok(h2o_memis(resolved.authority.base, resolved.authority.len, H2O_STRLIT("example.com")));
+ ok(h2o_memis(resolved.host.base, resolved.host.len, H2O_STRLIT("example.com")));
+ ok(resolved._port == 65535);
+ ok(h2o_url_get_port(&resolved) == 80);
+ ok(h2o_memis(resolved.path.base, resolved.path.len, H2O_STRLIT("/assets/jquery.js")));
+
+ ret = h2o_url_parse_relative("foo.html", SIZE_MAX, &relative);
+ ok(ret == 0);
+ final = h2o_url_resolve(&pool, &base, &relative, &resolved);
+ ok(h2o_memis(final.base, final.len, H2O_STRLIT("http://example.com/dir/foo.html")));
+ ok(resolved.scheme == &H2O_URL_SCHEME_HTTP);
+ ok(h2o_memis(resolved.authority.base, resolved.authority.len, H2O_STRLIT("example.com")));
+ ok(h2o_memis(resolved.host.base, resolved.host.len, H2O_STRLIT("example.com")));
+ ok(resolved._port == 65535);
+ ok(h2o_url_get_port(&resolved) == 80);
+ ok(h2o_memis(resolved.path.base, resolved.path.len, H2O_STRLIT("/dir/foo.html")));
+
+ ret = h2o_url_parse_relative("./bar.txt", SIZE_MAX, &relative);
+ ok(ret == 0);
+ final = h2o_url_resolve(&pool, &base, &relative, &resolved);
+ ok(h2o_memis(final.base, final.len, H2O_STRLIT("http://example.com/dir/bar.txt")));
+ ok(resolved.scheme == &H2O_URL_SCHEME_HTTP);
+ ok(h2o_memis(resolved.authority.base, resolved.authority.len, H2O_STRLIT("example.com")));
+ ok(h2o_memis(resolved.host.base, resolved.host.len, H2O_STRLIT("example.com")));
+ ok(resolved._port == 65535);
+ ok(h2o_url_get_port(&resolved) == 80);
+ ok(h2o_memis(resolved.path.base, resolved.path.len, H2O_STRLIT("/dir/bar.txt")));
+
+ ret = h2o_url_parse_relative("../../../traverse", SIZE_MAX, &relative);
+ ok(ret == 0);
+ final = h2o_url_resolve(&pool, &base, &relative, &resolved);
+ ok(h2o_memis(final.base, final.len, H2O_STRLIT("http://example.com/traverse")));
+ ok(resolved.scheme == &H2O_URL_SCHEME_HTTP);
+ ok(h2o_memis(resolved.authority.base, resolved.authority.len, H2O_STRLIT("example.com")));
+ ok(h2o_memis(resolved.host.base, resolved.host.len, H2O_STRLIT("example.com")));
+ ok(resolved._port == 65535);
+ ok(h2o_url_get_port(&resolved) == 80);
+ ok(h2o_memis(resolved.path.base, resolved.path.len, H2O_STRLIT("/traverse")));
+
+ ret = h2o_url_parse_relative("http:foo.html", SIZE_MAX, &relative);
+ ok(ret == 0);
+ final = h2o_url_resolve(&pool, &base, &relative, &resolved);
+ ok(h2o_memis(final.base, final.len, H2O_STRLIT("http://example.com/dir/foo.html")));
+ ok(resolved.scheme == &H2O_URL_SCHEME_HTTP);
+ ok(h2o_memis(resolved.authority.base, resolved.authority.len, H2O_STRLIT("example.com")));
+ ok(h2o_memis(resolved.host.base, resolved.host.len, H2O_STRLIT("example.com")));
+ ok(resolved._port == 65535);
+ ok(h2o_url_get_port(&resolved) == 80);
+ ok(h2o_memis(resolved.path.base, resolved.path.len, H2O_STRLIT("/dir/foo.html")));
+
+ ret = h2o_url_parse_relative("http:/icon.ico", SIZE_MAX, &relative);
+ ok(ret == 0);
+ final = h2o_url_resolve(&pool, &base, &relative, &resolved);
+ ok(h2o_memis(final.base, final.len, H2O_STRLIT("http://example.com/icon.ico")));
+ ok(resolved.scheme == &H2O_URL_SCHEME_HTTP);
+ ok(h2o_memis(resolved.authority.base, resolved.authority.len, H2O_STRLIT("example.com")));
+ ok(h2o_memis(resolved.host.base, resolved.host.len, H2O_STRLIT("example.com")));
+ ok(resolved._port == 65535);
+ ok(h2o_url_get_port(&resolved) == 80);
+ ok(h2o_memis(resolved.path.base, resolved.path.len, H2O_STRLIT("/icon.ico")));
+
+ ret = h2o_url_parse_relative("https:/icon.ico", SIZE_MAX, &relative);
+ ok(ret == 0);
+ final = h2o_url_resolve(&pool, &base, &relative, &resolved);
+ ok(h2o_memis(final.base, final.len, H2O_STRLIT("https://example.com/icon.ico")));
+ ok(resolved.scheme == &H2O_URL_SCHEME_HTTPS);
+ ok(h2o_memis(resolved.authority.base, resolved.authority.len, H2O_STRLIT("example.com")));
+ ok(h2o_memis(resolved.host.base, resolved.host.len, H2O_STRLIT("example.com")));
+ ok(resolved._port == 65535);
+ ok(h2o_url_get_port(&resolved) == 443);
+ ok(h2o_memis(resolved.path.base, resolved.path.len, H2O_STRLIT("/icon.ico")));
+
+ ret = h2o_url_parse_relative("//example.jp:81/icon.ico", SIZE_MAX, &relative);
+ ok(ret == 0);
+ final = h2o_url_resolve(&pool, &base, &relative, &resolved);
+ ok(h2o_memis(final.base, final.len, H2O_STRLIT("http://example.jp:81/icon.ico")));
+ ok(resolved.scheme == &H2O_URL_SCHEME_HTTP);
+ ok(h2o_memis(resolved.authority.base, resolved.authority.len, H2O_STRLIT("example.jp:81")));
+ ok(h2o_memis(resolved.host.base, resolved.host.len, H2O_STRLIT("example.jp")));
+ ok(resolved._port == 81);
+ ok(h2o_url_get_port(&resolved) == 81);
+ ok(h2o_memis(resolved.path.base, resolved.path.len, H2O_STRLIT("/icon.ico")));
+
+ final = h2o_url_stringify(&pool, &base);
+ ok(h2o_memis(final.base, final.len, H2O_STRLIT("http://example.com/dir/index.html")));
+
+ h2o_mem_clear_pool(&pool);
+}
+
+void test_lib__common__url_c(void)
+{
+ subtest("normalize_path", test_normalize_path);
+ subtest("hostport", test_hostport);
+ subtest("parse", test_parse);
+ subtest("parse_relative", test_parse_relative);
+ subtest("resolve", test_resolve);
+}