From f22a523b45857c3952c9812c7a0d8f8a7f6ffb5f Mon Sep 17 00:00:00 2001 From: Stephen Seo Date: Tue, 24 Sep 2024 14:53:28 +0900 Subject: [PATCH] backport: remove extra '/' in URI, config changes --- example_config/example.config | 36 +++++++++++++++++ example_config/inner.html | 3 +- src/http.c | 73 +++++++++++++++++++++++++++++++++++ 3 files changed, 111 insertions(+), 1 deletion(-) diff --git a/example_config/example.config b/example_config/example.config index 77b8d17..768af8c 100644 --- a/example_config/example.config +++ b/example_config/example.config @@ -38,3 +38,39 @@ HTML_FILE='''example_config/inner.html''' VAR_FILE='''example_config/var.html''' PATH=/error + +PATH=/inner/further +HTML=''' + + + + + +

Nested inner: further

+ {{{VAR}}} +
+ back + + +''' +VAR='''yep''' diff --git a/example_config/inner.html b/example_config/inner.html index 7de1791..cdf8566 100644 --- a/example_config/inner.html +++ b/example_config/inner.html @@ -28,6 +28,7 @@ {{{VAR_FILE}}}
-Back. +further
+Back. diff --git a/src/http.c b/src/http.c index 710ea73..93761dd 100644 --- a/src/http.c +++ b/src/http.c @@ -200,6 +200,14 @@ char *c_simple_http_request_response( } char *c_simple_http_strip_path(const char *path, size_t path_size) { + if (path_size == 1 && path[0] == '/') { + // Edge case: root path. + char *buf = malloc(2); + buf[0] = '/'; + buf[1] = 0; + return buf; + } + size_t idx = 0; for (; idx < path_size && path[idx] != 0; ++idx) { if (path[idx] == '?' || path[idx] == '#') { @@ -211,7 +219,72 @@ char *c_simple_http_strip_path(const char *path, size_t path_size) { memcpy(stripped_path, path, idx); stripped_path[idx] = 0; + // Strip multiple '/' into one. + __attribute((cleanup(simple_archiver_list_free))) + SDArchiverLinkedList *parts = simple_archiver_list_init(); + + idx = 0; + size_t prev_idx = 0; + size_t size; + char *buf; + uint_fast8_t slash_visited = 0; + + for (; stripped_path[idx] != 0; ++idx) { + if (stripped_path[idx] == '/') { + if (slash_visited) { + // Intentionally left blank. + } else { + slash_visited = 1; + + if (idx > prev_idx) { + size = idx - prev_idx + 1; + buf = malloc(size); + memcpy(buf, stripped_path + prev_idx, size - 1); + buf[size - 1] = 0; + + c_simple_http_add_string_part(parts, buf, 0); + free(buf); + } + } + } else { + if (slash_visited) { + buf = malloc(2); + buf[0] = '/'; + buf[1] = 0; + + c_simple_http_add_string_part(parts, buf, 0); + free(buf); + + prev_idx = idx; + } + + slash_visited = 0; + } + } + + if (!slash_visited && idx > prev_idx) { + size = idx - prev_idx + 1; + buf = malloc(size); + memcpy(buf, stripped_path + prev_idx, size - 1); + buf[size - 1] = 0; + + c_simple_http_add_string_part(parts, buf, 0); + free(buf); + } else if (slash_visited && prev_idx == 0) { + buf = malloc(2); + buf[0] = '/'; + buf[1] = 0; + + c_simple_http_add_string_part(parts, buf, 0); + free(buf); + } + + free(stripped_path); + + stripped_path = c_simple_http_combine_string_parts(parts); + // Strip trailing '/'. + idx = strlen(stripped_path); while (idx-- > 1) { if (stripped_path[idx] == '/' || stripped_path[idx] == 0) { stripped_path[idx] = 0;