Coverage for /home/users/etudiant/django/django/middleware/common.py : 94%
71 statements
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 re
2from urllib.parse import urlparse
4from django.conf import settings
5from django.core.exceptions import PermissionDenied
6from django.core.mail import mail_managers
7from django.http import HttpResponsePermanentRedirect
8from django.urls import is_valid_path
9from django.utils.deprecation import MiddlewareMixin
10from django.utils.http import escape_leading_slashes
13class CommonMiddleware(MiddlewareMixin):
14 """
15 "Common" middleware for taking care of some basic operations:
17 - Forbid access to User-Agents in settings.DISALLOWED_USER_AGENTS
19 - URL rewriting: Based on the APPEND_SLASH and PREPEND_WWW settings,
20 append missing slashes and/or prepends missing "www."s.
22 - If APPEND_SLASH is set and the initial URL doesn't end with a
23 slash, and it is not found in urlpatterns, form a new URL by
24 appending a slash at the end. If this new URL is found in
25 urlpatterns, return an HTTP redirect to this new URL; otherwise
26 process the initial URL as usual.
28 This behavior can be customized by subclassing CommonMiddleware and
29 overriding the response_redirect_class attribute.
30 """
32 response_redirect_class = HttpResponsePermanentRedirect
34 def process_request(self, request):
35 """
36 Check for denied User-Agents and rewrite the URL based on
37 settings.APPEND_SLASH and settings.PREPEND_WWW
38 """
40 # Check for denied User-Agents
41 user_agent = request.META.get('HTTP_USER_AGENT')
42 if user_agent is not None:
43 for user_agent_regex in settings.DISALLOWED_USER_AGENTS:
44 if user_agent_regex.search(user_agent): 44 ↛ 43line 44 didn't jump to line 43, because the condition on line 44 was never false
45 raise PermissionDenied('Forbidden user agent')
47 # Check for a redirect based on settings.PREPEND_WWW
48 host = request.get_host()
49 must_prepend = settings.PREPEND_WWW and host and not host.startswith('www.')
50 redirect_url = ('%s://www.%s' % (request.scheme, host)) if must_prepend else ''
52 # Check if a slash should be appended
53 if self.should_redirect_with_slash(request):
54 path = self.get_full_path_with_slash(request)
55 else:
56 path = request.get_full_path()
58 # Return a redirect if necessary
59 if redirect_url or path != request.get_full_path():
60 redirect_url += path
61 return self.response_redirect_class(redirect_url)
63 def should_redirect_with_slash(self, request):
64 """
65 Return True if settings.APPEND_SLASH is True and appending a slash to
66 the request path turns an invalid path into a valid one.
67 """
68 if settings.APPEND_SLASH and not request.path_info.endswith('/'):
69 urlconf = getattr(request, 'urlconf', None)
70 if not is_valid_path(request.path_info, urlconf):
71 match = is_valid_path('%s/' % request.path_info, urlconf)
72 if match:
73 view = match.func
74 return getattr(view, 'should_append_slash', True)
75 return False
77 def get_full_path_with_slash(self, request):
78 """
79 Return the full path of the request with a trailing slash appended.
81 Raise a RuntimeError if settings.DEBUG is True and request.method is
82 POST, PUT, or PATCH.
83 """
84 new_path = request.get_full_path(force_append_slash=True)
85 # Prevent construction of scheme relative urls.
86 new_path = escape_leading_slashes(new_path)
87 if settings.DEBUG and request.method in ('POST', 'PUT', 'PATCH'):
88 raise RuntimeError(
89 "You called this URL via %(method)s, but the URL doesn't end "
90 "in a slash and you have APPEND_SLASH set. Django can't "
91 "redirect to the slash URL while maintaining %(method)s data. "
92 "Change your form to point to %(url)s (note the trailing "
93 "slash), or set APPEND_SLASH=False in your Django settings." % {
94 'method': request.method,
95 'url': request.get_host() + new_path,
96 }
97 )
98 return new_path
100 def process_response(self, request, response):
101 """
102 When the status code of the response is 404, it may redirect to a path
103 with an appended slash if should_redirect_with_slash() returns True.
104 """
105 # If the given URL is "Not Found", then check if we should redirect to
106 # a path with a slash appended.
107 if response.status_code == 404 and self.should_redirect_with_slash(request): 107 ↛ 108line 107 didn't jump to line 108, because the condition on line 107 was never true
108 return self.response_redirect_class(self.get_full_path_with_slash(request))
110 # Add the Content-Length header to non-streaming responses if not
111 # already set.
112 if not response.streaming and not response.has_header('Content-Length'):
113 response.headers['Content-Length'] = str(len(response.content))
115 return response
118class BrokenLinkEmailsMiddleware(MiddlewareMixin):
120 def process_response(self, request, response):
121 """Send broken link emails for relevant 404 NOT FOUND responses."""
122 if response.status_code == 404 and not settings.DEBUG: 122 ↛ 139line 122 didn't jump to line 139, because the condition on line 122 was never false
123 domain = request.get_host()
124 path = request.get_full_path()
125 referer = request.META.get('HTTP_REFERER', '')
127 if not self.is_ignorable_request(request, path, domain, referer):
128 ua = request.META.get('HTTP_USER_AGENT', '<none>')
129 ip = request.META.get('REMOTE_ADDR', '<none>')
130 mail_managers(
131 "Broken %slink on %s" % (
132 ('INTERNAL ' if self.is_internal_request(domain, referer) else ''),
133 domain
134 ),
135 "Referrer: %s\nRequested URL: %s\nUser agent: %s\n"
136 "IP address: %s\n" % (referer, path, ua, ip),
137 fail_silently=True,
138 )
139 return response
141 def is_internal_request(self, domain, referer):
142 """
143 Return True if the referring URL is the same domain as the current
144 request.
145 """
146 # Different subdomains are treated as different domains.
147 return bool(re.match("^https?://%s/" % re.escape(domain), referer))
149 def is_ignorable_request(self, request, uri, domain, referer):
150 """
151 Return True if the given request *shouldn't* notify the site managers
152 according to project settings or in situations outlined by the inline
153 comments.
154 """
155 # The referer is empty.
156 if not referer:
157 return True
159 # APPEND_SLASH is enabled and the referer is equal to the current URL
160 # without a trailing slash indicating an internal redirect.
161 if settings.APPEND_SLASH and uri.endswith('/') and referer == uri[:-1]:
162 return True
164 # A '?' in referer is identified as a search engine source.
165 if not self.is_internal_request(domain, referer) and '?' in referer: 165 ↛ 166line 165 didn't jump to line 166, because the condition on line 165 was never true
166 return True
168 # The referer is equal to the current URL, ignoring the scheme (assumed
169 # to be a poorly implemented bot).
170 parsed_referer = urlparse(referer)
171 if parsed_referer.netloc in ['', domain] and parsed_referer.path == uri:
172 return True
174 return any(pattern.search(uri) for pattern in settings.IGNORABLE_404_URLS)
When APPEND_SLASH is set to True, if we have a 404 error after process_request has been called, the condition should_redirect_with_slash can never be met.
So is there a need to do a check at the mentionned line or is there something Iam I not getting right?
You received this message because you are subscribed to the Google Groups "Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-users+unsubscribe@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/01b7df9e-ffb2-4015-be6b-27f7492a422en%40googlegroups.com.
No comments:
Post a Comment