Handle conditional GET operations. If the response has an ETag or Last-Modified header and the request has If-None-Match or If-Modified-Since, replace the response with HttpNotModified. Add an ETag header if needed.
| 4 | |
| 5 | |
| 6 | class ConditionalGetMiddleware(MiddlewareMixin): |
| 7 | """ |
| 8 | Handle conditional GET operations. If the response has an ETag or |
| 9 | Last-Modified header and the request has If-None-Match or |
| 10 | If-Modified-Since, replace the response with HttpNotModified. Add an ETag |
| 11 | header if needed. |
| 12 | """ |
| 13 | |
| 14 | 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) |
no outgoing calls