http: "absolute-form" target URL parsing
Type: improvement Change-Id: If39680a148d39add40433547369b2ddad3c2e226 Signed-off-by: Matus Fabian <matfabia@cisco.com>
This commit is contained in:
@ -13,6 +13,7 @@ COPY \
|
||||
$DIR/af_packet_plugin.so \
|
||||
$DIR/hs_apps_plugin.so \
|
||||
$DIR/http_plugin.so \
|
||||
$DIR/http_unittest_plugin.so \
|
||||
$DIR/unittest_plugin.so \
|
||||
$DIR/quic_plugin.so \
|
||||
$DIR/http_static_plugin.so \
|
||||
|
@ -31,7 +31,7 @@ func init() {
|
||||
HttpStaticMacTimeTest, HttpStaticBuildInUrlGetVersionVerboseTest, HttpVersionNotSupportedTest,
|
||||
HttpInvalidContentLengthTest, HttpInvalidTargetSyntaxTest, HttpStaticPathTraversalTest, HttpUriDecodeTest,
|
||||
HttpHeadersTest, HttpStaticFileHandlerTest, HttpStaticFileHandlerDefaultMaxAgeTest, HttpClientTest, HttpClientErrRespTest, HttpClientPostFormTest,
|
||||
HttpClientPostFileTest, HttpClientPostFilePtrTest, AuthorityFormTargetTest, HttpRequestLineTest,
|
||||
HttpClientPostFileTest, HttpClientPostFilePtrTest, HttpUnitTest, HttpRequestLineTest,
|
||||
HttpStaticFileHandlerWrkTest, HttpStaticUrlHandlerWrkTest, HttpConnTimeoutTest)
|
||||
RegisterNoTopoSoloTests(HttpStaticPromTest, HttpGetTpsTest, HttpGetTpsInterruptModeTest, PromConcurrentConnectionsTest,
|
||||
PromMemLeakTest, HttpClientPostMemLeakTest, HttpInvalidClientRequestMemLeakTest, HttpPostTpsTest, HttpPostTpsInterruptModeTest,
|
||||
@ -352,24 +352,11 @@ func HttpClientPostFilePtrTest(s *NoTopoSuite) {
|
||||
httpClientPostFile(s, true, 131072)
|
||||
}
|
||||
|
||||
func cliTestAuthority(s *NoTopoSuite, authority string) {
|
||||
o := s.GetContainerByName("vpp").VppInstance.Vppctl("test http authority-form " + authority)
|
||||
s.AssertNotContains(o, "error")
|
||||
s.AssertContains(o, authority)
|
||||
}
|
||||
|
||||
func cliTestAuthorityError(s *NoTopoSuite, authority string) {
|
||||
o := s.GetContainerByName("vpp").VppInstance.Vppctl("test http authority-form " + authority)
|
||||
s.AssertContains(o, "error")
|
||||
}
|
||||
|
||||
func AuthorityFormTargetTest(s *NoTopoSuite) {
|
||||
cliTestAuthority(s, "10.10.2.45:20")
|
||||
cliTestAuthority(s, "[dead:beef::1234]:443")
|
||||
cliTestAuthorityError(s, "example.com:80")
|
||||
cliTestAuthorityError(s, "10.10.2.45")
|
||||
cliTestAuthorityError(s, "1000.10.2.45:20")
|
||||
cliTestAuthorityError(s, "[xyz0::1234]:443")
|
||||
func HttpUnitTest(s *NoTopoSuite) {
|
||||
vpp := s.GetContainerByName("vpp").VppInstance
|
||||
o := vpp.Vppctl("test http all")
|
||||
s.Log(o)
|
||||
s.AssertNotContains(o, "FAIL")
|
||||
}
|
||||
|
||||
func HttpStaticPromTest(s *NoTopoSuite) {
|
||||
|
@ -60,6 +60,7 @@ plugins {
|
||||
plugin af_packet_plugin.so { enable }
|
||||
plugin hs_apps_plugin.so { enable }
|
||||
plugin http_plugin.so { enable }
|
||||
plugin http_unittest_plugin.so { enable }
|
||||
plugin http_static_plugin.so { enable }
|
||||
plugin prom_plugin.so { enable }
|
||||
plugin tlsopenssl_plugin.so { enable }
|
||||
|
@ -16,5 +16,9 @@ add_vpp_plugin(http
|
||||
http.c
|
||||
http_buffer.c
|
||||
http_timer.c
|
||||
http_test.c
|
||||
)
|
||||
|
||||
add_vpp_plugin(http_unittest
|
||||
SOURCES
|
||||
test/http_test.c
|
||||
)
|
||||
|
@ -447,9 +447,10 @@ typedef struct http_main_
|
||||
} http_main_t;
|
||||
|
||||
always_inline int
|
||||
_validate_target_syntax (u8 *target, int is_query, int *is_encoded)
|
||||
_validate_target_syntax (u8 *target, u32 len, int is_query, int *is_encoded)
|
||||
{
|
||||
int i, encoded = 0;
|
||||
int encoded = 0;
|
||||
u32 i;
|
||||
|
||||
static uword valid_chars[4] = {
|
||||
/* !$&'()*+,-./0123456789:;= */
|
||||
@ -460,7 +461,7 @@ _validate_target_syntax (u8 *target, int is_query, int *is_encoded)
|
||||
0x0000000000000000,
|
||||
};
|
||||
|
||||
for (i = 0; i < vec_len (target); i++)
|
||||
for (i = 0; i < len; i++)
|
||||
{
|
||||
if (clib_bitmap_get_no_check (valid_chars, target[i]))
|
||||
continue;
|
||||
@ -471,7 +472,7 @@ _validate_target_syntax (u8 *target, int is_query, int *is_encoded)
|
||||
/* pct-encoded = "%" HEXDIG HEXDIG */
|
||||
if (target[i] == '%')
|
||||
{
|
||||
if ((i + 2) > vec_len (target))
|
||||
if ((i + 2) >= len)
|
||||
return -1;
|
||||
if (!isxdigit (target[i + 1]) || !isxdigit (target[i + 2]))
|
||||
return -1;
|
||||
@ -490,7 +491,7 @@ _validate_target_syntax (u8 *target, int is_query, int *is_encoded)
|
||||
/**
|
||||
* An "absolute-path" rule validation (RFC9110 section 4.1).
|
||||
*
|
||||
* @param path Target path to validate.
|
||||
* @param path Vector of target path to validate.
|
||||
* @param is_encoded Return flag that indicates if percent-encoded (optional).
|
||||
*
|
||||
* @return @c 0 on success.
|
||||
@ -498,13 +499,13 @@ _validate_target_syntax (u8 *target, int is_query, int *is_encoded)
|
||||
always_inline int
|
||||
http_validate_abs_path_syntax (u8 *path, int *is_encoded)
|
||||
{
|
||||
return _validate_target_syntax (path, 0, is_encoded);
|
||||
return _validate_target_syntax (path, vec_len (path), 0, is_encoded);
|
||||
}
|
||||
|
||||
/**
|
||||
* A "query" rule validation (RFC3986 section 2.1).
|
||||
*
|
||||
* @param query Target query to validate.
|
||||
* @param query Vector of target query to validate.
|
||||
* @param is_encoded Return flag that indicates if percent-encoded (optional).
|
||||
*
|
||||
* @return @c 0 on success.
|
||||
@ -512,7 +513,7 @@ http_validate_abs_path_syntax (u8 *path, int *is_encoded)
|
||||
always_inline int
|
||||
http_validate_query_syntax (u8 *query, int *is_encoded)
|
||||
{
|
||||
return _validate_target_syntax (query, 1, is_encoded);
|
||||
return _validate_target_syntax (query, vec_len (query), 1, is_encoded);
|
||||
}
|
||||
|
||||
#define htoi(x) (isdigit (x) ? (x - '0') : (tolower (x) - 'a' + 10))
|
||||
@ -977,6 +978,168 @@ http_serialize_authority_form_target (http_uri_t *authority)
|
||||
return s;
|
||||
}
|
||||
|
||||
typedef enum http_url_scheme_
|
||||
{
|
||||
HTTP_URL_SCHEME_HTTP,
|
||||
HTTP_URL_SCHEME_HTTPS,
|
||||
} http_url_scheme_t;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
http_url_scheme_t scheme;
|
||||
u16 port;
|
||||
u32 host_offset;
|
||||
u32 host_len;
|
||||
u32 path_offset;
|
||||
u32 path_len;
|
||||
u8 host_is_ip6;
|
||||
} http_url_t;
|
||||
|
||||
/**
|
||||
* An "absolute-form" URL parsing.
|
||||
*
|
||||
* @param url Vector of target URL to validate.
|
||||
* @param parsed Parsed URL metadata in case of success.
|
||||
*
|
||||
* @return @c 0 on success.
|
||||
*/
|
||||
always_inline int
|
||||
http_parse_absolute_form (u8 *url, http_url_t *parsed)
|
||||
{
|
||||
u8 *token_start, *token_end, *end;
|
||||
int is_encoded = 0;
|
||||
|
||||
static uword valid_chars[4] = {
|
||||
/* -.0123456789 */
|
||||
0x03ff600000000000,
|
||||
/* ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz */
|
||||
0x07fffffe07fffffe,
|
||||
0x0000000000000000,
|
||||
0x0000000000000000,
|
||||
};
|
||||
|
||||
if (vec_len (url) < 9)
|
||||
{
|
||||
clib_warning ("uri too short");
|
||||
return -1;
|
||||
}
|
||||
|
||||
clib_memset (parsed, 0, sizeof (*parsed));
|
||||
|
||||
end = url + vec_len (url);
|
||||
|
||||
/* parse scheme */
|
||||
if (!memcmp (url, "http:// ", 7))
|
||||
{
|
||||
parsed->scheme = HTTP_URL_SCHEME_HTTP;
|
||||
parsed->port = clib_host_to_net_u16 (80);
|
||||
parsed->host_offset = 7;
|
||||
}
|
||||
else if (!memcmp (url, "https:// ", 8))
|
||||
{
|
||||
parsed->scheme = HTTP_URL_SCHEME_HTTPS;
|
||||
parsed->port = clib_host_to_net_u16 (443);
|
||||
parsed->host_offset = 8;
|
||||
}
|
||||
else
|
||||
{
|
||||
clib_warning ("invalid scheme");
|
||||
return -1;
|
||||
}
|
||||
token_start = url + parsed->host_offset;
|
||||
|
||||
/* parse host */
|
||||
if (*token_start == '[')
|
||||
/* IPv6 address */
|
||||
{
|
||||
parsed->host_is_ip6 = 1;
|
||||
parsed->host_offset++;
|
||||
token_end = ++token_start;
|
||||
while (1)
|
||||
{
|
||||
if (token_end == end)
|
||||
{
|
||||
clib_warning ("invalid host, IPv6 addr not terminated with ']'");
|
||||
return -1;
|
||||
}
|
||||
else if (*token_end == ']')
|
||||
{
|
||||
parsed->host_len = token_end - token_start;
|
||||
token_start = token_end + 1;
|
||||
break;
|
||||
}
|
||||
else if (*token_end != ':' && *token_end != '.' &&
|
||||
!isxdigit (*token_end))
|
||||
{
|
||||
clib_warning ("invalid character '%u'", *token_end);
|
||||
return -1;
|
||||
}
|
||||
token_end++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
token_end = token_start;
|
||||
while (token_end != end && *token_end != ':' && *token_end != '/')
|
||||
{
|
||||
if (!clib_bitmap_get_no_check (valid_chars, *token_end))
|
||||
{
|
||||
clib_warning ("invalid character '%u'", *token_end);
|
||||
return -1;
|
||||
}
|
||||
token_end++;
|
||||
}
|
||||
parsed->host_len = token_end - token_start;
|
||||
token_start = token_end;
|
||||
}
|
||||
|
||||
if (!parsed->host_len)
|
||||
{
|
||||
clib_warning ("zero length host");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* parse port, if any */
|
||||
if (token_start != end && *token_start == ':')
|
||||
{
|
||||
u32 port = 0;
|
||||
token_end = ++token_start;
|
||||
while (token_end != end && *token_end != '/')
|
||||
{
|
||||
if (isdigit (*token_end))
|
||||
{
|
||||
port = port * 10 + *token_end - '0';
|
||||
if (port > 65535)
|
||||
{
|
||||
clib_warning ("invalid port number");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
clib_warning ("expected digit '%u'", *token_end);
|
||||
return -1;
|
||||
}
|
||||
token_end++;
|
||||
}
|
||||
parsed->port = clib_host_to_net_u16 ((u16) port);
|
||||
token_start = token_end;
|
||||
}
|
||||
|
||||
if (token_start == end)
|
||||
return 0;
|
||||
|
||||
token_start++; /* drop leading slash */
|
||||
parsed->path_offset = token_start - url;
|
||||
parsed->path_len = end - token_start;
|
||||
|
||||
if (parsed->path_len)
|
||||
return _validate_target_syntax (token_start, parsed->path_len, 0,
|
||||
&is_encoded);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* SRC_PLUGINS_HTTP_HTTP_H_ */
|
||||
|
||||
/*
|
||||
|
@ -1,34 +0,0 @@
|
||||
/* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright(c) 2024 Cisco Systems, Inc.
|
||||
*/
|
||||
|
||||
#include <http/http.h>
|
||||
|
||||
static clib_error_t *
|
||||
test_http_authority_command_fn (vlib_main_t *vm, unformat_input_t *input,
|
||||
vlib_cli_command_t *cmd)
|
||||
{
|
||||
u8 *target = 0;
|
||||
http_uri_t authority;
|
||||
int rv;
|
||||
|
||||
if (!unformat (input, "%v", &target))
|
||||
return clib_error_return (0, "error: no input provided");
|
||||
|
||||
rv = http_parse_authority_form_target (target, &authority);
|
||||
vec_free (target);
|
||||
if (rv)
|
||||
return clib_error_return (0, "error: parsing failed");
|
||||
|
||||
target = http_serialize_authority_form_target (&authority);
|
||||
vlib_cli_output (vm, "%v", target);
|
||||
vec_free (target);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
VLIB_CLI_COMMAND (test_http_authority_command) = {
|
||||
.path = "test http authority-form",
|
||||
.short_help = "test dns authority-form",
|
||||
.function = test_http_authority_command_fn,
|
||||
};
|
292
src/plugins/http/test/http_test.c
Normal file
292
src/plugins/http/test/http_test.c
Normal file
@ -0,0 +1,292 @@
|
||||
/* SPDX-License-Identifier: Apache-2.0
|
||||
* Copyright(c) 2024 Cisco Systems, Inc.
|
||||
*/
|
||||
|
||||
#include <vnet/plugin/plugin.h>
|
||||
#include <vpp/app/version.h>
|
||||
#include <http/http.h>
|
||||
|
||||
#define HTTP_TEST_I(_cond, _comment, _args...) \
|
||||
({ \
|
||||
int _evald = (_cond); \
|
||||
if (!(_evald)) \
|
||||
{ \
|
||||
vlib_cli_output (vm, "FAIL:%d: " _comment "\n", __LINE__, ##_args); \
|
||||
} \
|
||||
else \
|
||||
{ \
|
||||
vlib_cli_output (vm, "PASS:%d: " _comment "\n", __LINE__, ##_args); \
|
||||
} \
|
||||
_evald; \
|
||||
})
|
||||
|
||||
#define HTTP_TEST(_cond, _comment, _args...) \
|
||||
{ \
|
||||
if (!HTTP_TEST_I (_cond, _comment, ##_args)) \
|
||||
{ \
|
||||
return 1; \
|
||||
} \
|
||||
}
|
||||
|
||||
static int
|
||||
http_test_authority_form (vlib_main_t *vm)
|
||||
{
|
||||
u8 *target = 0, *formated_target = 0;
|
||||
http_uri_t authority;
|
||||
int rv;
|
||||
|
||||
target = format (0, "10.10.2.45:20");
|
||||
rv = http_parse_authority_form_target (target, &authority);
|
||||
HTTP_TEST ((rv == 0), "'%v' should be valid", target);
|
||||
formated_target = http_serialize_authority_form_target (&authority);
|
||||
rv = vec_cmp (target, formated_target);
|
||||
HTTP_TEST ((rv == 0), "'%v' should match '%v'", target, formated_target);
|
||||
vec_free (target);
|
||||
vec_free (formated_target);
|
||||
|
||||
target = format (0, "[dead:beef::1234]:443");
|
||||
rv = http_parse_authority_form_target (target, &authority);
|
||||
HTTP_TEST ((rv == 0), "'%v' should be valid", target);
|
||||
formated_target = http_serialize_authority_form_target (&authority);
|
||||
rv = vec_cmp (target, formated_target);
|
||||
HTTP_TEST ((rv == 0), "'%v' should match '%v'", target, formated_target);
|
||||
vec_free (target);
|
||||
vec_free (formated_target);
|
||||
|
||||
target = format (0, "example.com:80");
|
||||
rv = http_parse_authority_form_target (target, &authority);
|
||||
HTTP_TEST ((rv != 0), "'%v' reg-name not supported", target);
|
||||
vec_free (target);
|
||||
|
||||
target = format (0, "10.10.2.45");
|
||||
rv = http_parse_authority_form_target (target, &authority);
|
||||
HTTP_TEST ((rv != 0), "'%v' should be invalid", target);
|
||||
vec_free (target);
|
||||
|
||||
target = format (0, "1000.10.2.45:20");
|
||||
rv = http_parse_authority_form_target (target, &authority);
|
||||
HTTP_TEST ((rv != 0), "'%v' should be invalid", target);
|
||||
vec_free (target);
|
||||
|
||||
target = format (0, "[xyz0::1234]:443");
|
||||
rv = http_parse_authority_form_target (target, &authority);
|
||||
HTTP_TEST ((rv != 0), "'%v' should be invalid", target);
|
||||
vec_free (target);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
http_test_absolute_form (vlib_main_t *vm)
|
||||
{
|
||||
u8 *url = 0;
|
||||
http_url_t parsed_url;
|
||||
int rv;
|
||||
|
||||
url = format (0, "https://example.org/.well-known/masque/udp/1.2.3.4/123/");
|
||||
clib_warning (
|
||||
"strlen %u vec_len %u",
|
||||
strlen ("https://example.org/.well-known/masque/udp/1.2.3.4/123/"),
|
||||
vec_len (url));
|
||||
rv = http_parse_absolute_form (url, &parsed_url);
|
||||
HTTP_TEST ((rv == 0), "'%v' should be valid", url);
|
||||
HTTP_TEST ((parsed_url.scheme == HTTP_URL_SCHEME_HTTPS),
|
||||
"scheme should be https");
|
||||
HTTP_TEST ((parsed_url.host_is_ip6 == 0), "host_is_ip6=%u should be 0",
|
||||
parsed_url.host_is_ip6);
|
||||
HTTP_TEST ((parsed_url.host_offset == strlen ("https://")),
|
||||
"host_offset=%u should be %u", parsed_url.host_offset,
|
||||
strlen ("https://"));
|
||||
HTTP_TEST ((parsed_url.host_len == strlen ("example.org")),
|
||||
"host_len=%u should be %u", parsed_url.host_len,
|
||||
strlen ("example.org"));
|
||||
HTTP_TEST ((clib_net_to_host_u16 (parsed_url.port) == 443),
|
||||
"port=%u should be 443", clib_net_to_host_u16 (parsed_url.port));
|
||||
HTTP_TEST ((parsed_url.path_offset == strlen ("https://example.org/")),
|
||||
"path_offset=%u should be %u", parsed_url.path_offset,
|
||||
strlen ("https://example.org/"));
|
||||
HTTP_TEST (
|
||||
(parsed_url.path_len == strlen (".well-known/masque/udp/1.2.3.4/123/")),
|
||||
"path_len=%u should be %u", parsed_url.path_len,
|
||||
strlen (".well-known/masque/udp/1.2.3.4/123/"));
|
||||
vec_free (url);
|
||||
|
||||
url = format (0, "http://vpp-example.org");
|
||||
rv = http_parse_absolute_form (url, &parsed_url);
|
||||
HTTP_TEST ((rv == 0), "'%v' should be valid", url);
|
||||
HTTP_TEST ((parsed_url.scheme == HTTP_URL_SCHEME_HTTP),
|
||||
"scheme should be http");
|
||||
HTTP_TEST ((parsed_url.host_is_ip6 == 0), "host_is_ip6=%u should be 0",
|
||||
parsed_url.host_is_ip6);
|
||||
HTTP_TEST ((parsed_url.host_offset == strlen ("http://")),
|
||||
"host_offset=%u should be %u", parsed_url.host_offset,
|
||||
strlen ("http://"));
|
||||
HTTP_TEST ((parsed_url.host_len == strlen ("vpp-example.org")),
|
||||
"host_len=%u should be %u", parsed_url.host_len,
|
||||
strlen ("vpp-example.org"));
|
||||
HTTP_TEST ((clib_net_to_host_u16 (parsed_url.port) == 80),
|
||||
"port=%u should be 80", clib_net_to_host_u16 (parsed_url.port));
|
||||
HTTP_TEST ((parsed_url.path_len == 0), "path_len=%u should be 0",
|
||||
parsed_url.path_len);
|
||||
vec_free (url);
|
||||
|
||||
url = format (0, "http://1.2.3.4:8080/abcd");
|
||||
rv = http_parse_absolute_form (url, &parsed_url);
|
||||
HTTP_TEST ((rv == 0), "'%v' should be valid", url);
|
||||
HTTP_TEST ((parsed_url.scheme == HTTP_URL_SCHEME_HTTP),
|
||||
"scheme should be http");
|
||||
HTTP_TEST ((parsed_url.host_is_ip6 == 0), "host_is_ip6=%u should be 0",
|
||||
parsed_url.host_is_ip6);
|
||||
HTTP_TEST ((parsed_url.host_offset == strlen ("http://")),
|
||||
"host_offset=%u should be %u", parsed_url.host_offset,
|
||||
strlen ("http://"));
|
||||
HTTP_TEST ((parsed_url.host_len == strlen ("1.2.3.4")),
|
||||
"host_len=%u should be %u", parsed_url.host_len,
|
||||
strlen ("1.2.3.4"));
|
||||
HTTP_TEST ((clib_net_to_host_u16 (parsed_url.port) == 8080),
|
||||
"port=%u should be 8080", clib_net_to_host_u16 (parsed_url.port));
|
||||
HTTP_TEST ((parsed_url.path_offset == strlen ("http://1.2.3.4:8080/")),
|
||||
"path_offset=%u should be %u", parsed_url.path_offset,
|
||||
strlen ("http://1.2.3.4:8080/"));
|
||||
HTTP_TEST ((parsed_url.path_len == strlen ("abcd")),
|
||||
"path_len=%u should be %u", parsed_url.path_len, strlen ("abcd"));
|
||||
vec_free (url);
|
||||
|
||||
url = format (0, "https://[dead:beef::1234]/abcd");
|
||||
rv = http_parse_absolute_form (url, &parsed_url);
|
||||
HTTP_TEST ((rv == 0), "'%v' should be valid", url);
|
||||
HTTP_TEST ((parsed_url.scheme == HTTP_URL_SCHEME_HTTPS),
|
||||
"scheme should be https");
|
||||
HTTP_TEST ((parsed_url.host_is_ip6 == 1), "host_is_ip6=%u should be 1",
|
||||
parsed_url.host_is_ip6);
|
||||
HTTP_TEST ((parsed_url.host_offset == strlen ("https://[")),
|
||||
"host_offset=%u should be %u", parsed_url.host_offset,
|
||||
strlen ("https://["));
|
||||
HTTP_TEST ((parsed_url.host_len == strlen ("dead:beef::1234")),
|
||||
"host_len=%u should be %u", parsed_url.host_len,
|
||||
strlen ("dead:beef::1234"));
|
||||
HTTP_TEST ((clib_net_to_host_u16 (parsed_url.port) == 443),
|
||||
"port=%u should be 443", clib_net_to_host_u16 (parsed_url.port));
|
||||
HTTP_TEST ((parsed_url.path_offset == strlen ("https://[dead:beef::1234]/")),
|
||||
"path_offset=%u should be %u", parsed_url.path_offset,
|
||||
strlen ("https://[dead:beef::1234]/"));
|
||||
HTTP_TEST ((parsed_url.path_len == strlen ("abcd")),
|
||||
"path_len=%u should be %u", parsed_url.path_len, strlen ("abcd"));
|
||||
vec_free (url);
|
||||
|
||||
url = format (0, "http://[::ffff:192.0.2.128]:8080/");
|
||||
rv = http_parse_absolute_form (url, &parsed_url);
|
||||
HTTP_TEST ((rv == 0), "'%v' should be valid", url);
|
||||
HTTP_TEST ((parsed_url.scheme == HTTP_URL_SCHEME_HTTP),
|
||||
"scheme should be http");
|
||||
HTTP_TEST ((parsed_url.host_is_ip6 == 1), "host_is_ip6=%u should be 1",
|
||||
parsed_url.host_is_ip6);
|
||||
HTTP_TEST ((parsed_url.host_offset == strlen ("http://[")),
|
||||
"host_offset=%u should be %u", parsed_url.host_offset,
|
||||
strlen ("http://["));
|
||||
HTTP_TEST ((parsed_url.host_len == strlen ("::ffff:192.0.2.128")),
|
||||
"host_len=%u should be %u", parsed_url.host_len,
|
||||
strlen ("::ffff:192.0.2.128"));
|
||||
HTTP_TEST ((clib_net_to_host_u16 (parsed_url.port) == 8080),
|
||||
"port=%u should be 8080", clib_net_to_host_u16 (parsed_url.port));
|
||||
HTTP_TEST ((parsed_url.path_len == 0), "path_len=%u should be 0",
|
||||
parsed_url.path_len);
|
||||
vec_free (url);
|
||||
|
||||
url = format (0, "http://[dead:beef::1234/abc");
|
||||
rv = http_parse_absolute_form (url, &parsed_url);
|
||||
HTTP_TEST ((rv != 0), "'%v' should be invalid", url);
|
||||
vec_free (url);
|
||||
|
||||
url = format (0, "http://[dead|beef::1234]/abc");
|
||||
rv = http_parse_absolute_form (url, &parsed_url);
|
||||
HTTP_TEST ((rv != 0), "'%v' should be invalid", url);
|
||||
vec_free (url);
|
||||
|
||||
url = format (0, "http:example.org:8080/abcd");
|
||||
rv = http_parse_absolute_form (url, &parsed_url);
|
||||
HTTP_TEST ((rv != 0), "'%v' should be invalid", url);
|
||||
vec_free (url);
|
||||
|
||||
url = format (0, "htt://example.org:8080/abcd");
|
||||
rv = http_parse_absolute_form (url, &parsed_url);
|
||||
HTTP_TEST ((rv != 0), "'%v' should be invalid", url);
|
||||
vec_free (url);
|
||||
|
||||
url = format (0, "http://");
|
||||
rv = http_parse_absolute_form (url, &parsed_url);
|
||||
HTTP_TEST ((rv != 0), "'%v' should be invalid", url);
|
||||
vec_free (url);
|
||||
|
||||
url = format (0, "http:///abcd");
|
||||
rv = http_parse_absolute_form (url, &parsed_url);
|
||||
HTTP_TEST ((rv != 0), "'%v' should be invalid", url);
|
||||
vec_free (url);
|
||||
|
||||
url = format (0, "http://example.org:808080/abcd");
|
||||
rv = http_parse_absolute_form (url, &parsed_url);
|
||||
HTTP_TEST ((rv != 0), "'%v' should be invalid", url);
|
||||
vec_free (url);
|
||||
|
||||
url = format (0, "http://example.org/a%%3Xbcd");
|
||||
rv = http_parse_absolute_form (url, &parsed_url);
|
||||
HTTP_TEST ((rv != 0), "'%v' should be invalid", url);
|
||||
vec_free (url);
|
||||
|
||||
url = format (0, "http://example.org/a%%3");
|
||||
rv = http_parse_absolute_form (url, &parsed_url);
|
||||
HTTP_TEST ((rv != 0), "'%v' should be invalid", url);
|
||||
vec_free (url);
|
||||
|
||||
url = format (0, "http://example.org/a[b]cd");
|
||||
rv = http_parse_absolute_form (url, &parsed_url);
|
||||
HTTP_TEST ((rv != 0), "'%v' should be invalid", url);
|
||||
vec_free (url);
|
||||
|
||||
url = format (0, "http://exa[m]ple.org/abcd");
|
||||
rv = http_parse_absolute_form (url, &parsed_url);
|
||||
HTTP_TEST ((rv != 0), "'%v' should be invalid", url);
|
||||
vec_free (url);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static clib_error_t *
|
||||
test_http_command_fn (vlib_main_t *vm, unformat_input_t *input,
|
||||
vlib_cli_command_t *cmd)
|
||||
{
|
||||
int res = 0;
|
||||
while (unformat_check_input (input) != UNFORMAT_END_OF_INPUT)
|
||||
{
|
||||
if (unformat (input, "authority-form"))
|
||||
res = http_test_authority_form (vm);
|
||||
else if (unformat (input, "absolute-form"))
|
||||
res = http_test_absolute_form (vm);
|
||||
else if (unformat (input, "all"))
|
||||
{
|
||||
if ((res = http_test_authority_form (vm)))
|
||||
goto done;
|
||||
if ((res = http_test_absolute_form (vm)))
|
||||
goto done;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
done:
|
||||
if (res)
|
||||
return clib_error_return (0, "HTTP unit test failed");
|
||||
return 0;
|
||||
}
|
||||
|
||||
VLIB_CLI_COMMAND (test_http_command) = {
|
||||
.path = "test http",
|
||||
.short_help = "http unit tests",
|
||||
.function = test_http_command_fn,
|
||||
};
|
||||
|
||||
VLIB_PLUGIN_REGISTER () = {
|
||||
.version = VPP_BUILD_VER,
|
||||
.description = "HTTP - Unit Test",
|
||||
.default_disabled = 1,
|
||||
};
|
Reference in New Issue
Block a user