paivana

HTTP paywall reverse proxy
Log | Files | Refs | Submodules | README | LICENSE

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:
Msrc/backend/paivana-httpd.c | 49++++++++++++++++++++++++++++++++++++-------------
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 !=