Coverage for jutil/middleware.py : 78%

Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1import logging
2import traceback
3from typing import Dict, Optional
4from urllib.parse import urlencode
5from django.conf import settings
6from django.http import HttpRequest
7from django.utils import timezone
8from ipware import get_client_ip # type: ignore
9from jutil.email import send_email
11logger = logging.getLogger(__name__)
14class EnsureOriginMiddleware:
15 """
16 Ensures that request META 'HTTP_ORIGIN' is set.
17 Uses request get_host() to set it if missing.
18 """
20 def __init__(self, get_response=None):
21 self.get_response = get_response
23 def __call__(self, request):
24 # Code to be executed for each request before
25 # the view (and later middleware) are called.
26 if not request.META.get('HTTP_ORIGIN', None): 26 ↛ 30line 26 didn't jump to line 30, because the condition on line 26 was never false
27 request.META['HTTP_ORIGIN'] = request.get_host()
29 # get response
30 response = self.get_response(request)
32 # Code to be executed for each request/response after
33 # the view is called.
34 return response
37class LogExceptionMiddleware:
38 """
39 Logs exception and sends email to admins about it.
40 Uses list of emails from settings.ADMINS.
41 """
43 def __init__(self, get_response=None):
44 self.get_response = get_response
46 def __call__(self, request):
47 return self.get_response(request)
49 def process_exception(self, request, e):
50 """
51 Logs exception error message and sends email to ADMINS if hostname is not testserver and DEBUG=False.
52 :param request: HttpRequest
53 :param e: Exception
54 """
55 assert isinstance(request, HttpRequest)
56 full_path = request.get_full_path()
57 user = request.user
58 msg = '{full_path}\n{err} (IP={ip}, user={user}) {trace}'.format(full_path=full_path, user=user,
59 ip=get_client_ip(request)[0], err=e,
60 trace=str(traceback.format_exc()))
61 logger.error(msg)
62 hostname = request.get_host()
63 if not settings.DEBUG and hostname != 'testserver': 63 ↛ 64line 63 didn't jump to line 64, because the condition on line 63 was never true
64 send_email(settings.ADMINS, 'Error @ {}'.format(hostname), msg)
67class EnsureLanguageCookieMiddleware:
68 """
69 Ensures language cookie (by name settings.LANGUAGE_COOKIE_NAME) is set.
70 Sets it as settings.LANGUAGE_CODE if missing.
71 Allows changing settings by passing querystring parameter named settings.LANGUAGE_COOKIE_NAME
72 (default: django_language).
74 Order of preference for the language (must be one of settings.LANGUAGES to be used):
75 1) Explicit querystring GET parameter (e.g. ?lang=en)
76 2) Previously stored cookie
77 3) settings.LANGUAGE_CODE
78 """
79 _languages: Optional[Dict[str, str]]
81 def __init__(self, get_response=None):
82 self.get_response = get_response
83 self._languages = None
85 @property
86 def languages(self) -> Dict[str, str]:
87 if self._languages is None:
88 self._languages = dict(settings.LANGUAGES)
89 return self._languages
91 def __call__(self, request):
92 lang_cookie_name = settings.LANGUAGE_COOKIE_NAME if hasattr(settings, 'LANGUAGE_COOKIE_NAME') else 'django_language'
93 lang_cookie = request.COOKIES.get(lang_cookie_name)
94 lang = request.GET.get(lang_cookie_name)
95 if not lang:
96 lang = lang_cookie
97 if not lang or lang not in self.languages:
98 lang = settings.LANGUAGE_CODE if hasattr(settings, 'LANGUAGE_CODE') else 'en'
99 request.COOKIES[lang_cookie_name] = lang
101 res = self.get_response(request)
103 if lang_cookie is None or lang != lang_cookie:
104 secure = hasattr(settings, 'LANGUAGE_COOKIE_SECURE') and settings.LANGUAGE_COOKIE_SECURE
105 httponly = hasattr(settings, 'LANGUAGE_COOKIE_HTTPONLY') and settings.LANGUAGE_COOKIE_HTTPONLY
106 res.set_cookie(lang_cookie_name, lang, secure=secure, httponly=httponly)
107 return res
110class ActivateUserProfileTimezoneMiddleware:
111 """
112 Uses 'timezone' string in request.user.profile to activate user-specific timezone.
113 """
114 def __init__(self, get_response=None):
115 self.get_response = get_response
117 def __call__(self, request):
118 # Code to be executed for each request before
119 # the view (and later middleware) are called.
120 activated = False
121 if request.user.is_authenticated: 121 ↛ 134line 121 didn't jump to line 134, because the condition on line 121 was never false
122 user = request.user
123 if hasattr(user, 'profile') and user.profile: 123 ↛ 131line 123 didn't jump to line 131, because the condition on line 123 was never false
124 up = user.profile
125 if hasattr(up, 'timezone') and up.timezone: 125 ↛ 129line 125 didn't jump to line 129, because the condition on line 125 was never false
126 timezone.activate(up.timezone)
127 activated = True
128 else:
129 logger.warning('User profile timezone missing so user.profile.timezone could not be activated')
130 else:
131 logger.warning('User profile missing so user.profile.timezone could not be activated')
133 # get response
134 response = self.get_response(request)
136 # Code to be executed for each request/response after
137 # the view is called.
138 if activated: 138 ↛ 140line 138 didn't jump to line 140, because the condition on line 138 was never false
139 timezone.deactivate()
140 return response
143class TestClientLogger:
144 """
145 Logs requests for Django test client.
146 """
147 ignored_paths = {
148 '/admin/jsi18n/',
149 '/favicon.ico',
150 }
152 def __init__(self, get_response=None):
153 self.get_response = get_response
155 def __call__(self, request):
156 if settings.DEBUG:
157 assert isinstance(request, HttpRequest)
158 if request.path not in self.ignored_paths:
159 url = request.path
160 qs = request.GET.dict()
161 if qs:
162 url += '?' + urlencode(request.GET.dict())
163 logger.debug('[TestClientLogger] self.client.%s("%s", data=%s)', request.method.lower(), url, request.POST.dict())
164 response = self.get_response(request)
165 return response