Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 104 lines (91 sloc) 4.628 kB
8ecf49e @ericholscher Added an NGINX SSI processing middleware. Might break yo' shit.
ericholscher authored
1 import re
7462962 @ericholscher Removed adns dependency for pure python dnspython. Also cache dns
ericholscher authored
2
8bb2184 @ericholscher Allow people to use any hostname while in DEBUG
ericholscher authored
3 from django.conf import settings
7462962 @ericholscher Removed adns dependency for pure python dnspython. Also cache dns
ericholscher authored
4 from django.core.cache import cache
8ecf49e @ericholscher Added an NGINX SSI processing middleware. Might break yo' shit.
ericholscher authored
5 from django.core.urlresolvers import get_urlconf, get_resolver, Resolver404
22c7c05 @ericholscher Added language support to our urls/subdomains.
ericholscher authored
6 from django.http import Http404
d0b2cba @ericholscher Added logo to uploaded html docs.
ericholscher authored
7 from django.utils.encoding import smart_unicode
8ecf49e @ericholscher Added an NGINX SSI processing middleware. Might break yo' shit.
ericholscher authored
8
4f4d380 @ericholscher Start storing CNAMEs seen in redis.
ericholscher authored
9 import redis
10
11
22c7c05 @ericholscher Added language support to our urls/subdomains.
ericholscher authored
12 from projects.views.public import slug_detail, subdomain_handler
5c69fac @ericholscher Allow for project subdomains.
ericholscher authored
13
d0b2cba @ericholscher Added logo to uploaded html docs.
ericholscher authored
14 #Thanks to debug-toolbar for the response-replacing code.
15 _HTML_TYPES = ('text/html', 'application/xhtml+xml')
16
17 OUR_CODE = """
18 <hr> <!-- End original user content -->
19 <script type="text/javascript">
20 var _gaq = _gaq || [];
21 _gaq.push(['_setAccount', 'UA-17997319-1']);
22 _gaq.push(['_trackPageview']);
23 (function() {
24 var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
25 ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
26 var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
27 })();
28 </script>
29
30 <style type="text/css">
31 .badge { position: fixed; display: block; bottom: 5px; height: 40px; text-indent: -9999em; border-radius: 3px; -moz-border-radius: 3px; -webkit-border-radius: 3px; box-shadow: 0 1px 0 rgba(0, 0, 0, 0.2), 0 1px 0 rgba(255, 255, 255, 0.2) inset; -moz-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.2), 0 1px 0 rgba(255, 255, 255, 0.2) inset; -webkit-box-shadow: 0 1px 0 rgba(0, 0, 0, 0.2), 0 1px 0 rgba(255, 255, 255, 0.2) inset; }
32 .badge.rtd { background: #257597 url(http://media.readthedocs.org/images/badge-rtd.png) top left no-repeat; border: 1px solid #282E32; width: 160px; right: 5px; }
33 </style>
34
35 <a href="http://readthedocs.org?fromdocs=middleware" class="badge rtd">Brought to you by Read the Docs</a>
36 """
37
38 def replace_insensitive(string, target, replacement):
39 """
40 Similar to string.replace() but is case insensitive
41 Code borrowed from: http://forums.devshed.com/python-programming-11/case-insensitive-string-replace-490921.html
42 """
43 no_case = string.lower()
44 index = no_case.rfind(target.lower())
45 if index >= 0:
46 return string[:index] + replacement + string[index + len(target):]
47 else: # no results so return the original string
48 return string
49
50
5c69fac @ericholscher Allow for project subdomains.
ericholscher authored
51 class SubdomainMiddleware(object):
52 def process_request(self, request):
76899b5 @ericholscher Fix middleware to query dns and generally be awesome.
ericholscher authored
53 host = request.get_host()
54 if ':' in host:
55 host = host.split(':')[0]
56 domain_parts = host.split('.')
0aec26d @ericholscher Once more try and fix this.
ericholscher authored
57 #Google was finding crazy www.blah.readthedocs.org domains.
a795c68 @ericholscher I should learn that whenever I touch this middleware I break stuff.
ericholscher authored
58 if len(domain_parts) > 3:
566a22b @ericholscher Fix IP based hostnames.
ericholscher authored
59 if not settings.DEBUG:
60 raise Http404('Invalid hostname')
a795c68 @ericholscher I should learn that whenever I touch this middleware I break stuff.
ericholscher authored
61 if len(domain_parts) == 3:
76899b5 @ericholscher Fix middleware to query dns and generally be awesome.
ericholscher authored
62 subdomain = domain_parts[0]
9ece0e4 @ericholscher Add slug onto request for subdomains/CNAMEs
ericholscher authored
63 request.slug = subdomain
ec7ebad @ericholscher One more place :)
ericholscher authored
64 if not (subdomain.lower() == 'www') and 'readthedocs.org' in host:
dfe4443 @ericholscher Make home a relative link when CNAME'd. Fixes issue #9.
ericholscher authored
65 request.subdomain = True
22c7c05 @ericholscher Added language support to our urls/subdomains.
ericholscher authored
66 return subdomain_handler(request, subdomain, request.path.lstrip('/'))
ec00dbc @ericholscher Let people CNAME with readthedocs subdomain.
ericholscher authored
67 if 'readthedocs.org' not in host \
7aadb96 @ericholscher Added a super basic API with tastypie.
ericholscher authored
68 and 'localhost' not in host \
69 and 'testserver' not in host:
dfe4443 @ericholscher Make home a relative link when CNAME'd. Fixes issue #9.
ericholscher authored
70 request.cname = True
e0009ba @ericholscher Clean up middleware and subdomain header.
ericholscher authored
71 try:
4f4d380 @ericholscher Start storing CNAMEs seen in redis.
ericholscher authored
72 redis_conn = redis.Redis(**settings.REDIS)
7462962 @ericholscher Removed adns dependency for pure python dnspython. Also cache dns
ericholscher authored
73 slug = cache.get(host)
74 if not slug:
75 from dns import resolver
76 answer = [ans for ans in resolver.query(host, 'CNAME')][0]
77 domain = answer.target.to_unicode()
78 slug = domain.split('.')[0]
79 cache.set(host, slug, 60*60)
4f4d380 @ericholscher Start storing CNAMEs seen in redis.
ericholscher authored
80 #Cache the slug -> host mapping permanently.
81 redis_conn.sadd("rtd_slug:v1:%s" % slug, host)
9ece0e4 @ericholscher Add slug onto request for subdomains/CNAMEs
ericholscher authored
82 request.slug = slug
22c7c05 @ericholscher Added language support to our urls/subdomains.
ericholscher authored
83 return subdomain_handler(request,
84 slug,
85 request.path.lstrip('/'))
7462962 @ericholscher Removed adns dependency for pure python dnspython. Also cache dns
ericholscher authored
86 except:
22c7c05 @ericholscher Added language support to our urls/subdomains.
ericholscher authored
87 #Some crazy person is CNAMEing to us. 404.
8bb2184 @ericholscher Allow people to use any hostname while in DEBUG
ericholscher authored
88 if not settings.DEBUG:
89 raise Http404('Invalid Host Name.')
22c7c05 @ericholscher Added language support to our urls/subdomains.
ericholscher authored
90 #Normal request.
76899b5 @ericholscher Fix middleware to query dns and generally be awesome.
ericholscher authored
91 return None
d0b2cba @ericholscher Added logo to uploaded html docs.
ericholscher authored
92
93 def process_response(self, request, response):
94 #Try and make this match as little as possible.
3150461 @ericholscher Fix.
ericholscher authored
95 if response.status_code == 200 and '_static' not in request.path and '_images' not in request.path:
222b7fc @ericholscher Make middleware not slow and crappy.
ericholscher authored
96 if getattr(request, 'add_badge', False):
1066c0b @ericholscher Make middleware much faster.
ericholscher authored
97 response.content = replace_insensitive(
98 smart_unicode(response.content),
99 "</body>",
100 smart_unicode(OUR_CODE + "</body>"))
d0b2cba @ericholscher Added logo to uploaded html docs.
ericholscher authored
101 if response.get('Content-Length', None):
102 response['Content-Length'] = len(response.content)
103 return response
Something went wrong with that request. Please try again.