Ticket #3700: middleware.py

File middleware.py, 3.1 KB (added by Dave Hodder <dmh@…>, 17 years ago)

django.contrib.xhtmldegrader.middleware.py

Line 
1"""
2XHTML Degrader Middleware.
3
4When sending contents with the XHTML media type, application/xhtml+xml, this
5module checks to ensure that the user agent (web browser) is capable of
6rendering it. If not, it changes the media type to text/html and makes the
7contents more "HTML-friendly" (as per the XHTML 1.0 HTML Compatibility
8Guidelines).
9"""
10
11import re
12
13_MEDIA_TYPE_RE = re.compile(r'application\/xhtml\+xml')
14
15_EMPTY_TAG_END_RE = re.compile(r'(?<=\S)\/\>')
16
17_PROCESSING_INSTRUCTION_RE = re.compile(r'\<\?.*\?\>')
18
19def _supports_xhtml(request):
20 """Examines an HTTP request header to determine whether the user agent
21 supports the XHTML media type (application/xhtml+xml). Returns True or
22 False."""
23 if 'HTTP_ACCEPT' in request.META:
24 accept_header = request.META['HTTP_ACCEPT'].strip().lower()
25 else:
26 # No 'Accept' header; assume XHTML media type is preferable.
27 return True
28 if accept_header == '' or '/xhtml+xml' in accept_header \
29 or 'application/*' in accept_header \
30 or (accept_header == '*/*' and not \
31 ('HTTP_USER_AGENT' in request.META and \
32 request.META['HTTP_USER_AGENT'][0:10] == 'Mozilla/4.')):
33 # User agent probably supports XHTML media type.
34 return True
35 else:
36 # No reference to XHTML support.
37 return False
38
39class XhtmlDegraderMiddleware(object):
40 """Django middleware that "degrades" any contents sent as XHTML if the
41 requesting browser doesn't support the XHTML media type. Degrading involves
42 switching the content type to text/html, removing XML processing
43 instructions, etc.
44
45 If the HTTP response is already set to text/html, or set to any media type
46 other than application/xhtml+xml, this middleware will have no effect.
47 """
48
49 def process_response(self, request, response):
50 # Check if this is XHTML, and check if the user agent supports XHTML.
51 if response['Content-Type'].split(';')[0] != 'application/xhtml+xml' \
52 or _supports_xhtml(request):
53 # The content is fine, simply return it.
54 return response
55 # The content is XHTML, and the user agent doesn't support it.
56 # Fix the media type:
57 response['Content-Type'] = _MEDIA_TYPE_RE.sub('text/html',
58 response['Content-Type'], 1)
59 if 'charset' not in response['Content-Type']:
60 response['Content-Type'] += '; charset=utf-8'
61 # Modify the response contents as required:
62 # Remove any XML processing instructions:
63 response.content = _PROCESSING_INSTRUCTION_RE.sub('',
64 response.content)
65 # Ensure there's a space before the trailing '/>' of empty elements:
66 response.content = _EMPTY_TAG_END_RE.sub(' />',
67 response.content)
68 # Lose any excess whitespace:
69 response.content = response.content.strip()
70 if response.content[0:9] != '<!DOCTYPE':
71 # Add a DOCTYPE, so that the user agent isn't in "quirks" mode.
72 response.content = '<!DOCTYPE html>\n' + response.content
73 return response
Back to Top