commit 0c8d0361efefbf450f982074c9a49e2ed8820f0a
parent a210b2488186a221793a1b6d9a56123951eccf46
Author: Christian Grothoff <christian@grothoff.org>
Date: Wed, 5 Aug 2026 21:33:30 +0200
avoid trailing '/' in config causing '//' in constructed URLs when combining with path from MHD
Diffstat:
1 file changed, 36 insertions(+), 13 deletions(-)
diff --git a/src/backend/paivana-httpd.c b/src/backend/paivana-httpd.c
@@ -207,6 +207,40 @@ do_shutdown (void *cls)
/**
+ * Remove trailing slashes from the web URL @a url, in place.
+ *
+ * Our configuration syntax prefers base URLs to be written with a
+ * trailing '/', while everything we append to one -- a request path,
+ * a "/.well-known/..." endpoint -- brings a leading '/' of its own.
+ * Dropping them here is what keeps the concatenation from yielding
+ * "//", which would otherwise reach the upstream verbatim and, for
+ * BASE_URL, end up in the string the access cookie is keyed on and in
+ * the URL the templates' regular expressions are matched against.
+ *
+ * Never strips below "scheme://h", so that a URL consisting of
+ * nothing but a scheme and a host keeps its host.
+ *
+ * @param[in,out] url URL to canonicalize; must have passed
+ * TALER_is_web_url()
+ */
+static void
+strip_trailing_slashes (char *url)
+{
+ size_t len = strlen (url);
+ const char *sep;
+ size_t min_len;
+
+ sep = strstr (url,
+ "://");
+ GNUNET_assert (NULL != sep); /* was a web URL after all! */
+ min_len = (size_t) (sep - url) + strlen ("://") + 1;
+ while ( (len > min_len) &&
+ ('/' == url[len - 1]) )
+ url[--len] = '\0';
+}
+
+
+/**
* Main function that will be run. Main tasks are (1) init. the
* curl infrastructure (curl_global_init() / curl_multi_init()),
* then fetch the HTTP port where its Web service should listen at,
@@ -322,13 +356,7 @@ run (void *cls,
"paivana",
"DESTINATION_UNIXPATH",
&PH_target_server_unixpath);
- {
- size_t tlen = strlen (PH_target_server_base_url);
-
- if ( (tlen > 0) &&
- ('/' == PH_target_server_base_url[tlen - 1]) )
- PH_target_server_base_url[tlen - 1] = '\0';
- }
+ strip_trailing_slashes (PH_target_server_base_url);
if (! PH_no_check)
{
if (GNUNET_OK !=
@@ -433,8 +461,6 @@ run (void *cls,
}
if (NULL != PH_base_url)
{
- size_t blen;
-
if (! TALER_is_web_url (PH_base_url))
{
GNUNET_log_config_invalid (GNUNET_ERROR_TYPE_ERROR,
@@ -445,10 +471,7 @@ run (void *cls,
GNUNET_SCHEDULER_shutdown ();
return;
}
- blen = strlen (PH_base_url);
- GNUNET_assert (0 < blen); /* was a web_url after all! */
- if ('/' == PH_base_url[blen - 1])
- PH_base_url[blen - 1] = '\0';
+ strip_trailing_slashes (PH_base_url);
}
if (GNUNET_OK !=