From 30d108fc3538ad017ab2c6740a6276b01fae6654 Mon Sep 17 00:00:00 2001 From: Cory McWilliams Date: Sat, 2 Nov 2024 20:10:55 -0400 Subject: [PATCH] http: URL pattern matcher fixes. --- core/core.js | 23 ++++++----------------- src/http.c | 12 +++++++----- src/httpd.js.c | 24 +++++++++++++++++++++--- src/tests.c | 1 + 4 files changed, 35 insertions(+), 25 deletions(-) diff --git a/core/core.js b/core/core.js index 76e69ef1..92c64068 100644 --- a/core/core.js +++ b/core/core.js @@ -918,19 +918,6 @@ async function useAppHandler( * @returns */ async function blobHandler(request, response, blobId, uri) { - if (!uri) { - response.writeHead(303, { - Location: - (request.client.tls ? 'https://' : 'http://') + - (request.headers['x-forwarded-host'] ?? request.headers.host) + - blobId + - '/', - 'Content-Length': '0', - }); - response.end(); - return; - } - let process; let data; let match; @@ -1072,13 +1059,15 @@ loadSettings() httpd.set_http_redirect(settings.http_redirect); } httpd.all('/app/socket', app.socket); - httpd.all('', function default_http_handler(request, response) { + httpd.all('/~{word}/{word}/*', function default_http_handler(request, response) { let match; if ((match = /^(\/~[^\/]+\/[^\/]+)(\/?.*)$/.exec(request.uri))) { return blobHandler(request, response, match[1], match[2]); - } else if ( - (match = /^\/([&\%][^\.]{44}(?:\.\w+)?)(\/?.*)/.exec(request.uri)) - ) { + } + }); + httpd.all('/&*.sha256/*', function default_http_handler(request, response) { + let match; + if ((match = /^\/([&\%][^\.]{44}(?:\.\w+)?)(\/?.*)/.exec(request.uri))) { return blobHandler(request, response, match[1], match[2]); } }); diff --git a/src/http.c b/src/http.c index 947535d0..a99d6840 100644 --- a/src/http.c +++ b/src/http.c @@ -130,7 +130,7 @@ static void _http_allocate_buffer(uv_handle_t* handle, size_t suggested_size, uv bool tf_http_pattern_matches(const char* pattern, const char* path) { - if (!pattern || !*pattern) + if (!*pattern && !*path) { return true; } @@ -156,12 +156,14 @@ bool tf_http_pattern_matches(const char* pattern, const char* path) { while (true) { - if (((path[j] >= 'a' && path[j] <= 'z') || (path[j] >= 'A' && path[j] <= 'Z') || (path[j] >= '0' && path[j] <= '9')) && - tf_http_pattern_matches(pattern + i + k_word_len, path + j + 1)) + if ((path[j] >= 'a' && path[j] <= 'z') || (path[j] >= 'A' && path[j] <= 'Z') || (path[j] >= '0' && path[j] <= '9')) { - return true; + if (tf_http_pattern_matches(pattern + i + k_word_len, path + j + 1)) + { + return true; + } } - if (!path[j]) + else { break; } diff --git a/src/httpd.js.c b/src/httpd.js.c index c824fc3f..40f2b0aa 100644 --- a/src/httpd.js.c +++ b/src/httpd.js.c @@ -968,6 +968,22 @@ static void _httpd_endpoint_static(tf_http_request_t* request) tf_file_stat(task, path, _httpd_endpoint_static_stat, request); } +static void _httpd_endpoint_add_slash(tf_http_request_t* request) +{ + const char* host = tf_http_request_get_header(request, "x-forwarded-host"); + if (!host) + { + host = tf_http_request_get_header(request, "host"); + } + char url[1024]; + snprintf(url, sizeof(url), "%s%s%s/", request->is_tls ? "https://" : "http://", host, request->path); + const char* headers[] = { + "Location", + url, + }; + tf_http_respond(request, 303, headers, tf_countof(headers) / 2, "", 0); +} + typedef struct _user_app_t { const char* user; @@ -2101,12 +2117,14 @@ void tf_httpd_register(JSContext* context) tf_http_add_handler(http, "/speedscope/*", _httpd_endpoint_static, NULL, task); tf_http_add_handler(http, "/static/*", _httpd_endpoint_static, NULL, task); tf_http_add_handler(http, "/.well-known/*", _httpd_endpoint_static, NULL, task); - tf_http_add_handler(http, "/~*/*/", _httpd_endpoint_static, NULL, task); tf_http_add_handler(http, "/&*.sha256/", _httpd_endpoint_static, NULL, task); tf_http_add_handler(http, "/*/view", _httpd_endpoint_view, NULL, task); - tf_http_add_handler(http, "/~*/*/save", _httpd_endpoint_save, NULL, task); - tf_http_add_handler(http, "/~*/*/delete", _httpd_endpoint_delete, NULL, task); + tf_http_add_handler(http, "/~{word}/{word}/", _httpd_endpoint_static, NULL, task); + tf_http_add_handler(http, "/~{word}/{word}/save", _httpd_endpoint_save, NULL, task); + tf_http_add_handler(http, "/~{word}/{word}/delete", _httpd_endpoint_delete, NULL, task); tf_http_add_handler(http, "/save", _httpd_endpoint_save, NULL, task); + tf_http_add_handler(http, "/~{word}/{word}", _httpd_endpoint_add_slash, NULL, task); + tf_http_add_handler(http, "/&*.sha256", _httpd_endpoint_add_slash, NULL, task); tf_http_add_handler(http, "/robots.txt", _httpd_endpoint_robots_txt, NULL, NULL); tf_http_add_handler(http, "/debug", _httpd_endpoint_debug, NULL, task); diff --git a/src/tests.c b/src/tests.c index b7df802b..f508b6c7 100644 --- a/src/tests.c +++ b/src/tests.c @@ -915,6 +915,7 @@ static void _test_pattern(const tf_test_options_t* options) assert(tf_http_pattern_matches("/~{word}/*", "/~core/test")); assert(tf_http_pattern_matches("/~{word}/{word}/", "/~core/test/")); assert(tf_http_pattern_matches("/~{word}/{word}", "/~core/test")); + assert(!tf_http_pattern_matches("/~{word}/{word}", "/~foo/bar/baz")); } static void _test_auto_process_exit(uv_process_t* process, int64_t status, int termination_signal)