11import logging
22
33from django .http import HttpRequest
4+ from django .urls import set_script_prefix
45
56
67class ProxyPrefixMiddleware :
78 """
89 Middleware that adds a prefix from the 'HTTP_X_FORWARDED_PREFIX' header
910 to the request's full path.
1011 This helps when the app is behind a proxy that uses URL prefixes.
11- It modifies the request's build_absolute_uri method to include the prefix.
12+ It modifies the request's build_absolute_uri and get_full_path methods to include the prefix.
1213 """
1314
1415 def __init__ (self , get_response ):
@@ -19,17 +20,27 @@ def __call__(self, request: HttpRequest):
1920 prefix = request .META .get ("HTTP_X_FORWARDED_PREFIX" , "" )
2021 self .logger .debug (f"HTTP_X_FORWARDED_PREFIX:{ prefix } " )
2122 if prefix :
22- # Set SCRIPT_NAME so Django generates all URLs with the prefix
2323 request .META ["SCRIPT_NAME" ] = prefix
24- # Remove prefix from path_info so Django can match URL patterns
25- if request .path_info .startswith (prefix ):
26- request .path_info = request .path_info [len (prefix ) :]
24+ set_script_prefix (prefix )
25+
26+ original_get_full_path = request .get_full_path
27+
28+ def patched_get_full_path (force_append_slash = False ):
29+ path = original_get_full_path (force_append_slash )
30+ if path .startswith (prefix ):
31+ return path
32+ return prefix + path
33+
34+ request .get_full_path = patched_get_full_path
2735
2836 original_build_absolute_uri = request .build_absolute_uri
2937
3038 def patched_build_absolute_uri (location = None ):
3139 uri = original_build_absolute_uri (location )
32- return uri .replace (request .get_host (), request .get_host () + prefix , 1 )
40+ host_with_prefix = request .get_host () + prefix
41+ if host_with_prefix in uri :
42+ return uri
43+ return uri .replace (request .get_host (), host_with_prefix , 1 )
3344
3445 request .build_absolute_uri = patched_build_absolute_uri
3546
0 commit comments