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
+11 -12
View File
@@ -776,14 +776,12 @@ static void handle_client_read(connection_t *conn) {
clock_gettime(CLOCK_MONOTONIC, &ts);
conn->request_start_time = ts.tv_sec + ts.tv_nsec / 1e9;
#define DASHBOARD_PATH "/rproxy/dashboard"
#define STATS_PATH "/rproxy/api/stats"
if (http_uri_is_internal_route(conn->request.uri)) {
char normalized_uri[2048];
http_normalize_uri_path(conn->request.uri, normalized_uri, sizeof(normalized_uri));
if (strncmp(conn->request.uri, DASHBOARD_PATH, sizeof(DASHBOARD_PATH) - 1) == 0 ||
strncmp(conn->request.uri, STATS_PATH, sizeof(STATS_PATH) - 1) == 0) {
log_info("[ROUTING-INTERNAL] Serving internal route %s for fd=%d",
conn->request.uri, conn->fd);
log_info("[ROUTING-INTERNAL] Serving internal route %s (normalized: %s) for fd=%d",
conn->request.uri, normalized_uri, conn->fd);
if (conn->pair) {
connection_close(conn->pair->fd);
@@ -791,10 +789,14 @@ static void handle_client_read(connection_t *conn) {
}
conn->state = CLIENT_STATE_SERVING_INTERNAL;
if (strncmp(conn->request.uri, DASHBOARD_PATH, sizeof(DASHBOARD_PATH) - 1) == 0) {
if (strncmp(normalized_uri, "/rproxy/dashboard", 17) == 0) {
dashboard_serve(conn, data_start, headers_len);
} else {
} else if (strncmp(normalized_uri, "/rproxy/api/stats", 17) == 0) {
dashboard_serve_stats_api(conn, data_start, headers_len);
} else {
connection_send_error_response(conn, 404, "Not Found", "Internal route not found.");
buffer_consume(buf, total_request_len);
return;
}
buffer_consume(buf, total_request_len);
@@ -805,9 +807,6 @@ static void handle_client_read(connection_t *conn) {
return;
}
#undef DASHBOARD_PATH
#undef STATS_PATH
route_config_t *route = config_find_route(conn->request.host);
if (route && route->use_auth) {
char auth_header[1024] = "";
+68
View File
@@ -308,3 +308,71 @@ int http_extract_status_code(const char *data, size_t len) {
return (status >= 100 && status < 600) ? status : 0;
}
void http_normalize_uri_path(const char *uri, char *normalized, size_t normalized_size) {
if (!uri || !normalized || normalized_size == 0) return;
size_t uri_len = strlen(uri);
size_t out_pos = 0;
size_t i = 0;
const char *query = strchr(uri, '?');
size_t path_len = query ? (size_t)(query - uri) : uri_len;
while (i < path_len && out_pos < normalized_size - 1) {
if (uri[i] == '/') {
if (out_pos == 0 || normalized[out_pos - 1] != '/') {
normalized[out_pos++] = '/';
}
i++;
if (i < path_len && uri[i] == '.') {
if (i + 1 >= path_len || uri[i + 1] == '/' || uri[i + 1] == '?') {
i++;
continue;
}
if (uri[i + 1] == '.' && (i + 2 >= path_len || uri[i + 2] == '/' || uri[i + 2] == '?')) {
if (out_pos > 1) {
out_pos--;
while (out_pos > 0 && normalized[out_pos - 1] != '/') {
out_pos--;
}
}
i += 2;
continue;
}
}
} else {
normalized[out_pos++] = uri[i++];
}
}
if (query && out_pos < normalized_size - 1) {
size_t query_len = uri_len - (query - uri);
if (out_pos + query_len >= normalized_size) {
query_len = normalized_size - out_pos - 1;
}
memcpy(normalized + out_pos, query, query_len);
out_pos += query_len;
}
normalized[out_pos] = '\0';
if (out_pos == 0 && normalized_size > 1) {
normalized[0] = '/';
normalized[1] = '\0';
}
}
int http_uri_is_internal_route(const char *uri) {
if (!uri) return 0;
char normalized[2048];
http_normalize_uri_path(uri, normalized, sizeof(normalized));
if (strncmp(normalized, "/rproxy/", 8) == 0) {
return 1;
}
return 0;
}
+2
View File
@@ -13,5 +13,7 @@ int http_find_headers_end(const char *data, size_t len, size_t *headers_end);
int http_rewrite_content_length(char *headers, size_t *headers_len, size_t max_len, long new_length);
int http_find_header_line_bounds(const char* data, size_t len, const char* name, const char** line_start, const char** line_end);
int http_extract_status_code(const char *data, size_t len);
int http_uri_is_internal_route(const char *uri);
void http_normalize_uri_path(const char *uri, char *normalized, size_t normalized_size);
#endif