Ticket #3700: middleware.3.py

File middleware.3.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 '/xhtml+xml' in request.META.get('HTTP_ACCEPT', '').lower():
24 # User agent claims to support the XHTML media type.
25 return True
26 else:
27 # No reference to XHTML support.
28 return False
29
30class XhtmlDegraderMiddleware(object):
31 """Django middleware that "degrades" any contents sent as XHTML if the
32 requesting browser doesn't support the XHTML media type. Degrading involves
33 switching the content type to text/html, removing XML processing
34 instructions, etc.
35
36 If the HTTP response is already set to text/html, or set to any media type
37 other than application/xhtml+xml, this middleware will have no effect.
38 """
39
40 def process_response(self, request, response):
41 # Check if this is XHTML, and check if the user agent supports XHTML.
42 if response['Content-Type'].split(';')[0] != 'application/xhtml+xml' \
43 or _supports_xhtml(request):
44 # The content is fine, simply return it.
45 return response
46 # If the response has already been compressed we can't modify it
47 # further, so just return it. (N.B. if you use GZipMiddleware, you
48 # should ensure that it's listed in MIDDLEWARE_CLASSES before
49 # XhtmlDegraderMiddleware, to allow the XHTML Degrader to act first.)
50 if response.has_header('Content-Encoding'):
51 # Already compressed, so we can't do anything useful with it.
52 return response
53 # The content is XHTML, and the user agent doesn't support it.
54 # Fix the media type:
55 response['Content-Type'] = _MEDIA_TYPE_RE.sub('text/html',
56 response['Content-Type'], 1)
57 if 'charset' not in response['Content-Type']:
58 response['Content-Type'] += '; charset=utf-8'
59 # Modify the response contents as required:
60 # Remove any XML processing instructions:
61 response.content = _PROCESSING_INSTRUCTION_RE.sub('',
62 response.content)
63 # Ensure there's a space before the trailing '/>' of empty elements:
64 response.content = _EMPTY_TAG_END_RE.sub(' />',
65 response.content)
66 # Lose any excess whitespace:
67 response.content = response.content.strip()
68 if response.content[0:9] != '<!DOCTYPE':
69 # Add a DOCTYPE, so that the user agent isn't in "quirks" mode.
70 response.content = '<!DOCTYPE html>\n' + response.content
71 return response
Back to Top