http: URL pattern matcher fixes.

This commit is contained in:
Cory McWilliams 2024-11-02 20:10:55 -04:00
parent a09fefab5e
commit 30d108fc35
4 changed files with 35 additions and 25 deletions

View File

@ -918,19 +918,6 @@ async function useAppHandler(
* @returns * @returns
*/ */
async function blobHandler(request, response, blobId, uri) { 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 process;
let data; let data;
let match; let match;
@ -1072,13 +1059,15 @@ loadSettings()
httpd.set_http_redirect(settings.http_redirect); httpd.set_http_redirect(settings.http_redirect);
} }
httpd.all('/app/socket', app.socket); 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; let match;
if ((match = /^(\/~[^\/]+\/[^\/]+)(\/?.*)$/.exec(request.uri))) { if ((match = /^(\/~[^\/]+\/[^\/]+)(\/?.*)$/.exec(request.uri))) {
return blobHandler(request, response, match[1], match[2]); 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]); return blobHandler(request, response, match[1], match[2]);
} }
}); });

View File

@ -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) bool tf_http_pattern_matches(const char* pattern, const char* path)
{ {
if (!pattern || !*pattern) if (!*pattern && !*path)
{ {
return true; return true;
} }
@ -156,12 +156,14 @@ bool tf_http_pattern_matches(const char* pattern, const char* path)
{ {
while (true) while (true)
{ {
if (((path[j] >= 'a' && path[j] <= 'z') || (path[j] >= 'A' && path[j] <= 'Z') || (path[j] >= '0' && path[j] <= '9')) && 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 (tf_http_pattern_matches(pattern + i + k_word_len, path + j + 1))
{ {
return true; return true;
} }
if (!path[j]) }
else
{ {
break; break;
} }

View File

@ -968,6 +968,22 @@ static void _httpd_endpoint_static(tf_http_request_t* request)
tf_file_stat(task, path, _httpd_endpoint_static_stat, 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 typedef struct _user_app_t
{ {
const char* user; 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, "/speedscope/*", _httpd_endpoint_static, NULL, task);
tf_http_add_handler(http, "/static/*", _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, "/.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, "/&*.sha256/", _httpd_endpoint_static, NULL, task);
tf_http_add_handler(http, "/*/view", _httpd_endpoint_view, 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, "/~{word}/{word}/", _httpd_endpoint_static, NULL, task);
tf_http_add_handler(http, "/~*/*/delete", _httpd_endpoint_delete, 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, "/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, "/robots.txt", _httpd_endpoint_robots_txt, NULL, NULL);
tf_http_add_handler(http, "/debug", _httpd_endpoint_debug, NULL, task); tf_http_add_handler(http, "/debug", _httpd_endpoint_debug, NULL, task);

View File

@ -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}/*", "/~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}", "/~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) static void _test_auto_process_exit(uv_process_t* process, int64_t status, int termination_signal)