1
0
Fork 0
mirror of https://github.com/Kozea/Radicale.git synced 2025-06-26 16:45:52 +00:00

remove base prefix from path (required for proper handling if called by reverse proxy)

This commit is contained in:
Peter Bieringer 2025-03-02 09:06:30 +01:00
parent 7b4da3a128
commit 280968e694
2 changed files with 29 additions and 14 deletions

View file

@ -222,24 +222,37 @@ class Application(ApplicationPartDelete, ApplicationPartHead,
# SCRIPT_NAME is already removed from PATH_INFO, according to the # SCRIPT_NAME is already removed from PATH_INFO, according to the
# WSGI specification. # WSGI specification.
# Reverse proxies can overwrite SCRIPT_NAME with X-SCRIPT-NAME header # Reverse proxies can overwrite SCRIPT_NAME with X-SCRIPT-NAME header
base_prefix_src = ("HTTP_X_SCRIPT_NAME" if "HTTP_X_SCRIPT_NAME" in if self._script_name and (reverse_proxy is True):
environ else "SCRIPT_NAME") base_prefix_src = "config"
base_prefix = environ.get(base_prefix_src, "") base_prefix = self._script_name
if base_prefix and base_prefix[0] != "/": else:
logger.error("Base prefix (from %s) must start with '/': %r", base_prefix_src = ("HTTP_X_SCRIPT_NAME" if "HTTP_X_SCRIPT_NAME" in
base_prefix_src, base_prefix) environ else "SCRIPT_NAME")
if base_prefix_src == "HTTP_X_SCRIPT_NAME": base_prefix = environ.get(base_prefix_src, "")
return response(*httputils.BAD_REQUEST) if base_prefix and base_prefix[0] != "/":
return response(*httputils.INTERNAL_SERVER_ERROR) logger.error("Base prefix (from %s) must start with '/': %r",
if base_prefix.endswith("/"): base_prefix_src, base_prefix)
logger.warning("Base prefix (from %s) must not end with '/': %r", if base_prefix_src == "HTTP_X_SCRIPT_NAME":
base_prefix_src, base_prefix) return response(*httputils.BAD_REQUEST)
base_prefix = base_prefix.rstrip("/") return response(*httputils.INTERNAL_SERVER_ERROR)
logger.debug("Base prefix (from %s): %r", base_prefix_src, base_prefix) if base_prefix.endswith("/"):
logger.warning("Base prefix (from %s) must not end with '/': %r",
base_prefix_src, base_prefix)
base_prefix = base_prefix.rstrip("/")
if base_prefix:
logger.debug("Base prefix (from %s): %r", base_prefix_src, base_prefix)
# Sanitize request URI (a WSGI server indicates with an empty path, # Sanitize request URI (a WSGI server indicates with an empty path,
# that the URL targets the application root without a trailing slash) # that the URL targets the application root without a trailing slash)
path = pathutils.sanitize_path(unsafe_path) path = pathutils.sanitize_path(unsafe_path)
logger.debug("Sanitized path: %r", path) logger.debug("Sanitized path: %r", path)
if (reverse_proxy is True) and (len(base_prefix) > 0):
if path.startswith(base_prefix):
path_new = path.removeprefix(base_prefix)
logger.debug("Called by reverse proxy, remove base prefix %r from path: %r => %r", base_prefix, path, path_new)
path = path_new
else:
logger.warning("Called by reverse proxy, cannot removed base prefix %r from path: %r as not matching", base_prefix, path)
# Get function corresponding to method # Get function corresponding to method
function = getattr(self, "do_%s" % request_method, None) function = getattr(self, "do_%s" % request_method, None)

View file

@ -66,6 +66,8 @@ class ApplicationPartGet(ApplicationBase):
if path == "/.web" or path.startswith("/.web/"): if path == "/.web" or path.startswith("/.web/"):
# Redirect to sanitized path for all subpaths of /.web # Redirect to sanitized path for all subpaths of /.web
unsafe_path = environ.get("PATH_INFO", "") unsafe_path = environ.get("PATH_INFO", "")
if len(base_prefix) > 0:
unsafe_path = unsafe_path.removeprefix(base_prefix)
if unsafe_path != path: if unsafe_path != path:
location = base_prefix + path location = base_prefix + path
logger.info("Redirecting to sanitized path: %r ==> %r", logger.info("Redirecting to sanitized path: %r ==> %r",