chore: add http_uri_is_internal_route and http_normalize_uri_path with tests for internal routing

This commit is contained in:
2026-01-06 14:12:10 +00:00
parent a4438c6b60
commit f75581963a
5 changed files with 141 additions and 12 deletions
+52
View File
@@ -182,6 +182,56 @@ void test_http_malformed_requests(void) {
TEST_SUITE_END();
}
void test_http_uri_normalization(void) {
TEST_SUITE_BEGIN("HTTP URI Path Normalization");
char normalized[256];
http_normalize_uri_path("/rproxy/dashboard", normalized, sizeof(normalized));
TEST_ASSERT_STR_EQ("/rproxy/dashboard", normalized, "Normal path unchanged");
http_normalize_uri_path("//rproxy/dashboard", normalized, sizeof(normalized));
TEST_ASSERT_STR_EQ("/rproxy/dashboard", normalized, "Double slash at start collapsed");
http_normalize_uri_path("/rproxy//dashboard", normalized, sizeof(normalized));
TEST_ASSERT_STR_EQ("/rproxy/dashboard", normalized, "Double slash in middle collapsed");
http_normalize_uri_path("/./rproxy/dashboard", normalized, sizeof(normalized));
TEST_ASSERT_STR_EQ("/rproxy/dashboard", normalized, "Dot segment at start removed");
http_normalize_uri_path("/rproxy/./dashboard", normalized, sizeof(normalized));
TEST_ASSERT_STR_EQ("/rproxy/dashboard", normalized, "Dot segment in middle removed");
http_normalize_uri_path("/foo/../rproxy/dashboard", normalized, sizeof(normalized));
TEST_ASSERT_STR_EQ("/rproxy/dashboard", normalized, "Parent reference resolved");
http_normalize_uri_path("/rproxy/dashboard?foo=bar", normalized, sizeof(normalized));
TEST_ASSERT_STR_EQ("/rproxy/dashboard?foo=bar", normalized, "Query string preserved");
http_normalize_uri_path("///rproxy///dashboard///", normalized, sizeof(normalized));
TEST_ASSERT_STR_EQ("/rproxy/dashboard/", normalized, "Multiple slashes collapsed");
TEST_SUITE_END();
}
void test_http_internal_route_detection(void) {
TEST_SUITE_BEGIN("HTTP Internal Route Detection");
TEST_ASSERT_EQ(1, http_uri_is_internal_route("/rproxy/dashboard"), "Normal dashboard path detected");
TEST_ASSERT_EQ(1, http_uri_is_internal_route("/rproxy/api/stats"), "Normal stats path detected");
TEST_ASSERT_EQ(1, http_uri_is_internal_route("//rproxy/dashboard"), "Double slash bypass detected");
TEST_ASSERT_EQ(1, http_uri_is_internal_route("/./rproxy/dashboard"), "Dot segment bypass detected");
TEST_ASSERT_EQ(1, http_uri_is_internal_route("/foo/../rproxy/dashboard"), "Parent reference bypass detected");
TEST_ASSERT_EQ(1, http_uri_is_internal_route("/rproxy//dashboard"), "Slash in path bypass detected");
TEST_ASSERT_EQ(1, http_uri_is_internal_route("/rproxy/./api/stats"), "Dot in internal path detected");
TEST_ASSERT_EQ(0, http_uri_is_internal_route("/api/data"), "Non-internal path rejected");
TEST_ASSERT_EQ(0, http_uri_is_internal_route("/"), "Root path rejected");
TEST_ASSERT_EQ(0, http_uri_is_internal_route("/rproxynotreal"), "Similar prefix rejected");
TEST_ASSERT_EQ(0, http_uri_is_internal_route(NULL), "NULL path rejected");
TEST_SUITE_END();
}
void run_http_tests(void) {
test_http_parse_get_request();
test_http_parse_post_request();
@@ -193,4 +243,6 @@ void run_http_tests(void) {
test_http_parse_host_with_port();
test_http_is_request_start();
test_http_malformed_requests();
test_http_uri_normalization();
test_http_internal_route_detection();
}