Skip to content

Commit e952449

Browse files
committed
implemented async-only http middleware
1 parent 93f2cce commit e952449

File tree

1 file changed

+41
-0
lines changed
  • django_async_extensions/amiddleware

1 file changed

+41
-0
lines changed
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
from django.utils.cache import cc_delim_re, get_conditional_response, set_response_etag
2+
from django.utils.http import parse_http_date_safe
3+
4+
from django_async_extensions.amiddleware.base import AsyncMiddlewareMixin
5+
6+
7+
class AsyncConditionalGetMiddleware(AsyncMiddlewareMixin):
8+
"""
9+
Handle conditional GET operations. If the response has an ETag or
10+
Last-Modified header and the request has If-None-Match or If-Modified-Since,
11+
replace the response with HttpNotModified. Add an ETag header if needed.
12+
"""
13+
14+
async def process_response(self, request, response):
15+
# It's too late to prevent an unsafe request with a 412 response, and
16+
# for a HEAD request, the response body is always empty so computing
17+
# an accurate ETag isn't possible.
18+
if request.method != "GET":
19+
return response
20+
21+
if self.needs_etag(response) and not response.has_header("ETag"):
22+
set_response_etag(response)
23+
24+
etag = response.get("ETag")
25+
last_modified = response.get("Last-Modified")
26+
last_modified = last_modified and parse_http_date_safe(last_modified)
27+
28+
if etag or last_modified:
29+
return get_conditional_response(
30+
request,
31+
etag=etag,
32+
last_modified=last_modified,
33+
response=response,
34+
)
35+
36+
return response
37+
38+
def needs_etag(self, response):
39+
"""Return True if an ETag header should be added to response."""
40+
cache_control_headers = cc_delim_re.split(response.get("Cache-Control", ""))
41+
return all(header.lower() != "no-store" for header in cache_control_headers)

0 commit comments

Comments
 (0)