Permalink
Browse files

Allow static files to be served from other domains.

  • Loading branch information...
1 parent 97c14e0 commit 50a5daa60c1888daff22cdcc587d68abe82cc727 @spladug spladug committed Oct 19, 2011
Showing with 87 additions and 26 deletions.
  1. +9 −1 r2/example.ini
  2. +2 −0 r2/r2/lib/app_globals.py
  3. +3 −5 r2/r2/lib/js.py
  4. +73 −20 r2/r2/lib/template_helpers.py
View
@@ -64,7 +64,7 @@ admins = reddit
# the default subreddit for submissions
default_sr = reddit.com
# default header image url
-default_header_url = /static/reddit.com.header.png
+default_header_url = reddit.com.header.png
# time for the page cache (for unlogged in users)
page_cache_time = 90
@@ -285,6 +285,14 @@ stylesheet = reddit.css
stylesheet_rtl = reddit-rtl.css
# location of the static directory
static_path = /static/
+# if set, these are the domains used for static files served over http and https
+# if not set, no domain will be specified
+static_domain =
+static_secure_domain =
+# if this is true, append .gz to CSS and JS files served from the static domain
+# this is for hosts that don't do on-the-fly gzipping (e.g. s3)
+static_pre_gzipped = false
+static_secure_pre_gzipped = false
# make frontpage 100% dart
frontpage_dart = false
View
@@ -95,6 +95,8 @@ class Globals(object):
's3_media_direct',
'disable_captcha',
'disable_ads',
+ 'static_pre_gzipped',
+ 'static_secure_pre_gzipped',
]
tuple_props = ['stalecaches',
View
@@ -91,8 +91,7 @@ def use(self):
if g.uncompressedJS:
return "".join(source.use() for source in self.sources)
else:
- url = os.path.join(g.static_path, self.name)
- return script_tag.format(src=static(url))
+ return script_tag.format(src=static(self.name))
class StringsSource(Source):
"""A virtual source consisting of localized strings from r2.lib.strings."""
@@ -157,7 +156,7 @@ def use(self):
return embed + StringsSource().use()
else:
name, ext = os.path.splitext(self.name)
- url = os.path.join(g.static_path, name + "." + get_lang()[0] + ext)
+ url = name + "." + get_lang()[0] + ext
return script_tag.format(src=static(url))
class JQuery(Module):
@@ -171,8 +170,7 @@ def build(self, closure):
def use(self):
from r2.lib.template_helpers import static
if c.secure or c.user.pref_local_js:
- path = os.path.join(g.static_path, self.name)
- return script_tag.format(src=static(path))
+ return script_tag.format(src=static(self.name))
else:
ext = ".js" if g.uncompressedJS else ".min.js"
return script_tag.format(src=self.cdn_src+ext)
@@ -30,10 +30,36 @@
import os.path
from copy import copy
import random
+import urlparse
from pylons import g, c
from pylons.i18n import _, ungettext
-def static(path):
+def is_encoding_acceptable(encoding_to_check):
+ """"Check if a content encoding is acceptable to the user agent.
+
+ An encoding is determined acceptable if the encoding (or the special '*' encoding)
+ is specified in the Accept-Encoding header with a quality value > 0.
+ """
+ header = request.headers.get('Accept-Encoding', '')
+ encodings = header.split(',')
+
+ for value in encodings:
+ if ';' not in value:
+ name = value.strip()
+ else:
+ coding_name, quality = value.split(';')
+ if '=' not in quality:
+ continue
+ q, value = quality.split('=')
+ if float(value) == 0:
+ continue
+ name = coding_name.strip()
+
+ if name in (encoding_to_check, '*'):
+ return True
+ return False
+
+def static(path, allow_gzip=True):
"""
Simple static file maintainer which automatically paths and
versions files being served out of static.
@@ -42,29 +68,56 @@ def static(path):
version of the file is set to be random to prevent caching and it
mangles the path to point to the uncompressed versions.
"""
-
- dirname, fname = os.path.split(path)
- fname = fname.split('?')[0]
- query = ""
-
- # if uncompressed, randomize a url query to bust caches
- if g.uncompressedJS:
- query = "?v=" + str(random.random()).split(".")[-1]
+ dirname, filename = os.path.split(path)
+ extension = os.path.splitext(filename)[1]
+ is_text = extension in ('.js', '.css')
+ can_gzip = is_text and is_encoding_acceptable('gzip')
+ should_gzip = allow_gzip and can_gzip
+
+ path_components = []
+ actual_filename = None
+
+ if not c.secure and g.static_domain:
+ scheme = 'http'
+ domain = g.static_domain
+ query = None
+ suffix = '.gz' if should_gzip and g.static_pre_gzipped else ''
+ elif c.secure and g.static_secure_domain:
+ scheme = 'https'
+ domain = g.static_secure_domain
+ query = None
+ suffix = '.gz' if should_gzip and g.static_secure_pre_gzipped else ''
else:
- if fname in g.static_names:
- fname = g.static_names[fname]
- path = os.path.join(dirname, fname)
+ path_components.append(c.site.static_path)
+ query = None
+
+ if g.uncompressedJS:
+ query = 'v=' + str(random.randint(1, 1000000))
+
+ # unminified static files are in type-specific subdirectories
+ if not dirname and is_text:
+ path_components.append(extension[1:])
+
+ actual_filename = filename
+
+ scheme = None
+ domain = None
+ suffix = ''
- # don't mangle paths
- if dirname:
- return path + query
+ path_components.append(dirname)
+ if not actual_filename:
+ actual_filename = g.static_names.get(filename, filename)
+ path_components.append(actual_filename + suffix)
- if g.uncompressedJS:
- extension = path.split(".")[1:]
- if extension and extension[-1] in ("js", "css"):
- return os.path.join(c.site.static_path, extension[-1], path) + query
+ actual_path = os.path.join(*path_components)
+ return urlparse.urlunsplit((
+ scheme,
+ domain,
+ actual_path,
+ query,
+ None
+ ))
- return os.path.join(c.site.static_path, path) + query
def s3_https_if_secure(url):
# In the event that more media sources (other than s3) are added, this function should be corrected

0 comments on commit 50a5daa

Please sign in to comment.