Coverage for /var/srv/projects/api.amasfac.comuna18.com/tmp/venv/lib/python3.9/site-packages/django/core/handlers/exception.py: 25%
76 statements
« prev ^ index » next coverage.py v6.4.4, created at 2023-07-17 14:22 -0600
« prev ^ index » next coverage.py v6.4.4, created at 2023-07-17 14:22 -0600
1import asyncio
2import logging
3import sys
4from functools import wraps
6from asgiref.sync import sync_to_async
8from django.conf import settings
9from django.core import signals
10from django.core.exceptions import (
11 BadRequest,
12 PermissionDenied,
13 RequestDataTooBig,
14 SuspiciousOperation,
15 TooManyFieldsSent,
16)
17from django.http import Http404
18from django.http.multipartparser import MultiPartParserError
19from django.urls import get_resolver, get_urlconf
20from django.utils.log import log_response
21from django.views import debug
24def convert_exception_to_response(get_response):
25 """
26 Wrap the given get_response callable in exception-to-response conversion.
28 All exceptions will be converted. All known 4xx exceptions (Http404,
29 PermissionDenied, MultiPartParserError, SuspiciousOperation) will be
30 converted to the appropriate response, and all other exceptions will be
31 converted to 500 responses.
33 This decorator is automatically applied to all middleware to ensure that
34 no middleware leaks an exception and that the next middleware in the stack
35 can rely on getting a response instead of an exception.
36 """
37 if asyncio.iscoroutinefunction(get_response): 37 ↛ 39line 37 didn't jump to line 39, because the condition on line 37 was never true
39 @wraps(get_response)
40 async def inner(request):
41 try:
42 response = await get_response(request)
43 except Exception as exc:
44 response = await sync_to_async(
45 response_for_exception, thread_sensitive=False
46 )(request, exc)
47 return response
49 return inner
50 else:
52 @wraps(get_response)
53 def inner(request):
54 try:
55 response = get_response(request)
56 except Exception as exc:
57 response = response_for_exception(request, exc)
58 return response
60 return inner
63def response_for_exception(request, exc):
64 if isinstance(exc, Http404):
65 if settings.DEBUG:
66 response = debug.technical_404_response(request, exc)
67 else:
68 response = get_exception_response(
69 request, get_resolver(get_urlconf()), 404, exc
70 )
72 elif isinstance(exc, PermissionDenied):
73 response = get_exception_response(
74 request, get_resolver(get_urlconf()), 403, exc
75 )
76 log_response(
77 "Forbidden (Permission denied): %s",
78 request.path,
79 response=response,
80 request=request,
81 exc_info=sys.exc_info(),
82 )
84 elif isinstance(exc, MultiPartParserError):
85 response = get_exception_response(
86 request, get_resolver(get_urlconf()), 400, exc
87 )
88 log_response(
89 "Bad request (Unable to parse request body): %s",
90 request.path,
91 response=response,
92 request=request,
93 exc_info=sys.exc_info(),
94 )
96 elif isinstance(exc, BadRequest):
97 if settings.DEBUG:
98 response = debug.technical_500_response(
99 request, *sys.exc_info(), status_code=400
100 )
101 else:
102 response = get_exception_response(
103 request, get_resolver(get_urlconf()), 400, exc
104 )
105 log_response(
106 "%s: %s",
107 str(exc),
108 request.path,
109 response=response,
110 request=request,
111 exc_info=sys.exc_info(),
112 )
113 elif isinstance(exc, SuspiciousOperation):
114 if isinstance(exc, (RequestDataTooBig, TooManyFieldsSent)):
115 # POST data can't be accessed again, otherwise the original
116 # exception would be raised.
117 request._mark_post_parse_error()
119 # The request logger receives events for any problematic request
120 # The security logger receives events for all SuspiciousOperations
121 security_logger = logging.getLogger(
122 "django.security.%s" % exc.__class__.__name__
123 )
124 security_logger.error(
125 str(exc),
126 extra={"status_code": 400, "request": request},
127 )
128 if settings.DEBUG:
129 response = debug.technical_500_response(
130 request, *sys.exc_info(), status_code=400
131 )
132 else:
133 response = get_exception_response(
134 request, get_resolver(get_urlconf()), 400, exc
135 )
137 else:
138 signals.got_request_exception.send(sender=None, request=request)
139 response = handle_uncaught_exception(
140 request, get_resolver(get_urlconf()), sys.exc_info()
141 )
142 log_response(
143 "%s: %s",
144 response.reason_phrase,
145 request.path,
146 response=response,
147 request=request,
148 exc_info=sys.exc_info(),
149 )
151 # Force a TemplateResponse to be rendered.
152 if not getattr(response, "is_rendered", True) and callable(
153 getattr(response, "render", None)
154 ):
155 response = response.render()
157 return response
160def get_exception_response(request, resolver, status_code, exception):
161 try:
162 callback = resolver.resolve_error_handler(status_code)
163 response = callback(request, exception=exception)
164 except Exception:
165 signals.got_request_exception.send(sender=None, request=request)
166 response = handle_uncaught_exception(request, resolver, sys.exc_info())
168 return response
171def handle_uncaught_exception(request, resolver, exc_info):
172 """
173 Processing for any otherwise uncaught exceptions (those that will
174 generate HTTP 500 responses).
175 """
176 if settings.DEBUG_PROPAGATE_EXCEPTIONS:
177 raise
179 if settings.DEBUG:
180 return debug.technical_500_response(request, *exc_info)
182 # Return an HttpResponse that displays a friendly error message.
183 callback = resolver.resolve_error_handler(500)
184 return callback(request)