Coverage for ivatar/middleware.py: 95%

22 statements  

« prev     ^ index     » next       coverage.py v7.15.4, created at 2026-08-21 11:51 +0000

1""" 

2Middleware classes 

3""" 

4 

5import hashlib 

6from django.utils.deprecation import MiddlewareMixin 

7from django.middleware.locale import LocaleMiddleware 

8 

9 

10class CustomLocaleMiddleware(LocaleMiddleware): 

11 """ 

12 Middleware that extends LocaleMiddleware to skip Vary header processing for image URLs 

13 """ 

14 

15 def process_response(self, request, response): 

16 # Check if this is an image-related URL 

17 path = request.path 

18 if any( 

19 path.startswith(prefix) 

20 for prefix in ["/avatar/", "/gravatarproxy/", "/blueskyproxy/"] 

21 ): 

22 # Delete Vary from header if exists 

23 if "Vary" in response: 

24 del response["Vary"] 

25 

26 # Extract hash from URL path for ETag 

27 # URLs are like /avatar/{hash}, /gravatarproxy/{hash}, /blueskyproxy/{hash} 

28 path_parts = path.strip("/").split("/") 

29 if len(path_parts) >= 2: 

30 hash_value = path_parts[1] # Get the hash part 

31 # Sanitize hash_value to remove newlines and other control characters 

32 # that would cause BadHeaderError 

33 hash_value = "".join( 

34 c for c in hash_value if c.isprintable() and c not in "\r\n" 

35 ) 

36 response["Etag"] = f'"{hash_value}"' 

37 else: 

38 # Fallback to content hash if we can't extract from URL 

39 # Use hashlib.md5 for stable hash across processes 

40 content_hash = hashlib.md5(response.content).hexdigest() 

41 response["Etag"] = f'"{content_hash}"' 

42 

43 # Skip the parent's process_response to avoid adding Accept-Language to Vary 

44 return response 

45 

46 # For all other URLs, use the parent's behavior 

47 return super().process_response(request, response) 

48 

49 

50class MultipleProxyMiddleware( 

51 MiddlewareMixin 

52): # pylint: disable=too-few-public-methods 

53 """ 

54 Middleware to rewrite proxy headers for deployments 

55 with multiple proxies 

56 """ 

57 

58 def process_request(self, request): # pylint: disable=no-self-use 

59 """ 

60 Rewrites the proxy headers so that forwarded server is 

61 used if available. 

62 """ 

63 if "HTTP_X_FORWARDED_SERVER" in request.META: 

64 request.META["HTTP_X_FORWARDED_HOST"] = request.META[ 

65 "HTTP_X_FORWARDED_SERVER" 

66 ]