static asset management, thanks Niphlod

This commit is contained in:
mdipierro
2012-09-28 17:06:11 -05:00
parent bd27df8fa5
commit e18f38d4da
4 changed files with 47 additions and 46 deletions
+1 -1
View File
@@ -1 +1 @@
Version 2.0.9 (2012-09-28 12:47:32) dev Version 2.0.9 (2012-09-28 17:06:03) dev
+2 -5
View File
@@ -274,6 +274,8 @@ class Response(Storage):
for item in files: for item in files:
if isinstance(item,str): if isinstance(item,str):
f = item.lower().split('?')[0] f = item.lower().split('?')[0]
if self.static_version:
item = item.replace('/static/', '/static/_%s/' % self.static_version, 1)
if f.endswith('.css'): s += css_template % item if f.endswith('.css'): s += css_template % item
elif f.endswith('.js'): s += js_template % item elif f.endswith('.js'): s += js_template % item
elif f.endswith('.coffee'): s += coffee_template % item elif f.endswith('.coffee'): s += coffee_template % item
@@ -714,8 +716,3 @@ class Session(Storage):
del response.session_file del response.session_file
except: except:
pass pass
+5 -2
View File
@@ -402,7 +402,7 @@ def wsgibase(environ, responder):
# ################################################## # ##################################################
fixup_missing_path_info(environ) fixup_missing_path_info(environ)
(static_file, environ) = url_in(request, environ) (static_file, version, environ) = url_in(request, environ)
response.status = env.web2py_status_code or response.status response.status = env.web2py_status_code or response.status
if static_file: if static_file:
@@ -410,13 +410,16 @@ def wsgibase(environ, responder):
'attachment'): 'attachment'):
response.headers['Content-Disposition'] \ response.headers['Content-Disposition'] \
= 'attachment' = 'attachment'
if version:
response.headers['Cache-Control'] = 'max-age=315360000'
response.headers['Expires'] = 'Thu, 31 Dec 2037 23:59:59 GMT'
response.stream(static_file, request=request) response.stream(static_file, request=request)
# ################################################## # ##################################################
# fill in request items # fill in request items
# ################################################## # ##################################################
app = request.application ## must go after url_in! app = request.application ## must go after url_in!
http_host = env.http_host.split(':',1)[0] http_host = env.http_host.split(':',1)[0]
local_hosts = [http_host,'::1','127.0.0.1', local_hosts = [http_host,'::1','127.0.0.1',
'::ffff:127.0.0.1'] '::ffff:127.0.0.1']
+39 -38
View File
@@ -39,6 +39,7 @@ regex_at = re.compile(r'(?<!\\)\$[a-zA-Z]\w*')
regex_anything = re.compile(r'(?<!\\)\$anything') regex_anything = re.compile(r'(?<!\\)\$anything')
regex_redirect = re.compile(r'(\d+)->(.*)') regex_redirect = re.compile(r'(\d+)->(.*)')
regex_full_url = re.compile(r'^(?P<scheme>http|https|HTTP|HTTPS)\://(?P<host>[^/]*)(?P<uri>.*)') regex_full_url = re.compile(r'^(?P<scheme>http|https|HTTP|HTTPS)\://(?P<host>[^/]*)(?P<uri>.*)')
regex_version = re.compile(r'^(_[\d]+\.[\d]+\.[\d]+)$')
def _router_default(): def _router_default():
"return new copy of default base router" "return new copy of default base router"
@@ -107,16 +108,16 @@ def log_rewrite(string):
logger.debug(string) logger.debug(string)
ROUTER_KEYS = set( ROUTER_KEYS = set(
('default_application', 'applications', ('default_application', 'applications',
'default_controller', 'controllers', 'default_controller', 'controllers',
'default_function', 'functions', 'default_function', 'functions',
'default_language', 'languages', 'default_language', 'languages',
'domain', 'domains', 'root_static', 'path_prefix', 'domain', 'domains', 'root_static', 'path_prefix',
'exclusive_domain', 'map_hyphen', 'map_static', 'exclusive_domain', 'map_hyphen', 'map_static',
'acfe_match', 'file_match', 'args_match')) 'acfe_match', 'file_match', 'args_match'))
ROUTER_BASE_KEYS = set( ROUTER_BASE_KEYS = set(
('applications', 'default_application', ('applications', 'default_application',
'domains', 'path_prefix')) 'domains', 'path_prefix'))
# The external interface to rewrite consists of: # The external interface to rewrite consists of:
@@ -140,8 +141,8 @@ def fixup_missing_path_info(environ):
path_info = eget('PATH_INFO') path_info = eget('PATH_INFO')
request_uri = eget('REQUEST_URI') request_uri = eget('REQUEST_URI')
if not path_info and request_uri: if not path_info and request_uri:
# for fcgi, get path_info and # for fcgi, get path_info and
# query_string from request_uri # query_string from request_uri
items = request_uri.split('?') items = request_uri.split('?')
path_info = environ['PATH_INFO'] = items[0] path_info = environ['PATH_INFO'] = items[0]
environ['QUERY_STRING'] = items[1] if len(items) > 1 else '' environ['QUERY_STRING'] = items[1] if len(items) > 1 else ''
@@ -154,15 +155,15 @@ def fixup_missing_path_info(environ):
if not eget('HTTP_HOST'): if not eget('HTTP_HOST'):
environ['HTTP_HOST'] = \ environ['HTTP_HOST'] = \
'%s:%s' % (eget('SERVER_NAME'),eget('SERVER_PORT')) '%s:%s' % (eget('SERVER_NAME'),eget('SERVER_PORT'))
def url_in(request, environ): def url_in(request, environ):
"parse and rewrite incoming URL" "parse and rewrite incoming URL"
if routers: if routers:
return map_url_in(request, environ) return map_url_in(request, environ)
return regex_url_in(request, environ) return regex_url_in(request, environ)
def url_out(request, env, application, controller, function, def url_out(request, env, application, controller, function,
args, other, scheme, host, port): args, other, scheme, host, port):
"assemble and rewrite outgoing URL" "assemble and rewrite outgoing URL"
if routers: if routers:
@@ -555,7 +556,7 @@ def regex_filter_in(e):
query = e.get('QUERY_STRING', None) query = e.get('QUERY_STRING', None)
e['WEB2PY_ORIGINAL_URI'] = e['PATH_INFO'] + (query and ('?' + query) or '') e['WEB2PY_ORIGINAL_URI'] = e['PATH_INFO'] + (query and ('?' + query) or '')
if thread.routes.routes_in: if thread.routes.routes_in:
path = regex_uri(e, thread.routes.routes_in, path = regex_uri(e, thread.routes.routes_in,
"routes_in", e['PATH_INFO']) "routes_in", e['PATH_INFO'])
rmatch = regex_redirect.match(path) rmatch = regex_redirect.match(path)
if rmatch: if rmatch:
@@ -587,10 +588,11 @@ regex_space = re.compile('(\+|\s|%20)+')
# apps in routes_apps_raw must parse raw_args into args # apps in routes_apps_raw must parse raw_args into args
regex_static = re.compile(r''' regex_static = re.compile(r'''
(^ # static pages (^ # static pages
/(?P<b> \w+) # b=app /(?P<b> \w+) # b=app
/static # /b/static /static # /b/static
/(?P<x> (\w[\-\=\./]?)* ) # x=file (/(?P<v>_[\d]+\.[\d]+\.[\d]+))? # version ?
/(?P<x> (\w[\-\=\./]?)* ) # x=file
$) $)
''', re.X) ''', re.X)
@@ -639,7 +641,7 @@ def regex_url_in(request, environ):
if thread.routes.routes_in: if thread.routes.routes_in:
environ = regex_filter_in(environ) environ = regex_filter_in(environ)
request.env.update((sluggify(k),v) for k,v in environ.iteritems()) request.env.update((sluggify(k),v) for k,v in environ.iteritems())
path = request.env.path_info.replace('\\', '/') path = request.env.path_info.replace('\\', '/')
@@ -650,10 +652,11 @@ def regex_url_in(request, environ):
match = regex_static.match(regex_space.sub('_', path)) match = regex_static.match(regex_space.sub('_', path))
if match and match.group('x'): if match and match.group('x'):
version = match.group('v')
static_file = pjoin(request.env.applications_parent, static_file = pjoin(request.env.applications_parent,
'applications', match.group('b'), 'applications', match.group('b'),
'static', match.group('x')) 'static', match.group('x'))
return (static_file, environ) return (static_file, version, environ)
# ################################################## # ##################################################
# parse application, controller and function # parse application, controller and function
@@ -692,7 +695,7 @@ def regex_url_in(request, environ):
raise HTTP(400, raise HTTP(400,
thread.routes.error_message % 'invalid request', thread.routes.error_message % 'invalid request',
web2py_error='invalid path (args)') web2py_error='invalid path (args)')
return (None, environ) return (None, None, environ)
def regex_filter_out(url, e=None): def regex_filter_out(url, e=None):
@@ -723,9 +726,9 @@ def regex_filter_out(url, e=None):
return url return url
def filter_url(url, method='get', remote='0.0.0.0', def filter_url(url, method='get', remote='0.0.0.0',
out=False, app=False, lang=None, out=False, app=False, lang=None,
domain=(None,None), env=False, scheme=None, domain=(None,None), env=False, scheme=None,
host=None, port=None): host=None, port=None):
""" """
doctest/unittest interface to regex_filter_in() and regex_filter_out() doctest/unittest interface to regex_filter_in() and regex_filter_out()
@@ -794,7 +797,7 @@ def filter_url(url, method='get', remote='0.0.0.0',
# rewrite inbound URL # rewrite inbound URL
# #
(static, e) = url_in(request, e) (static, version, e) = url_in(request, e)
if static: if static:
return static return static
result = "/%s/%s/%s" % (request.application, request.controller, request.function) result = "/%s/%s/%s" % (request.application, request.controller, request.function)
@@ -957,14 +960,15 @@ class MapUrlIn(object):
a root-static file is one whose incoming URL expects it to be at the root, a root-static file is one whose incoming URL expects it to be at the root,
typically robots.txt & favicon.ico typically robots.txt & favicon.ico
''' '''
if len(self.args) == 1 and self.arg0 in self.router.root_static: if len(self.args) == 1 and self.arg0 in self.router.root_static:
self.controller = self.request.controller = 'static' self.controller = self.request.controller = 'static'
root_static_file = pjoin(self.request.env.applications_parent, root_static_file = pjoin(self.request.env.applications_parent,
'applications', self.application, 'applications', self.application,
self.controller, self.arg0) self.controller, self.arg0)
log_rewrite("route: root static=%s" % root_static_file) log_rewrite("route: root static=%s" % root_static_file)
return root_static_file return root_static_file, None
return None return None, None
def map_language(self): def map_language(self):
"handle language (no hyphen mapping)" "handle language (no hyphen mapping)"
@@ -999,8 +1003,12 @@ class MapUrlIn(object):
file_match but no hyphen mapping file_match but no hyphen mapping
''' '''
if self.controller != 'static': if self.controller != 'static':
return None return None, None
file = '/'.join(self.args) version = regex_version.match(self.args(0))
if self.args and version:
file = '/'.join(self.args[1:])
else:
file = '/'.join(self.args)
if len(self.args) == 0: if len(self.args) == 0:
bad_static = True # require a file name bad_static = True # require a file name
elif '/' in self.file_match: elif '/' in self.file_match:
@@ -1031,7 +1039,7 @@ class MapUrlIn(object):
'static', file) 'static', file)
self.extension = None self.extension = None
log_rewrite("route: static=%s" % static_file) log_rewrite("route: static=%s" % static_file)
return static_file return static_file, version
def map_function(self): def map_function(self):
"handle function.extension" "handle function.extension"
@@ -1075,7 +1083,7 @@ class MapUrlIn(object):
"" ""
self.request.env.update( self.request.env.update(
(sluggify(k),v) for k,v in self.env.iteritems()) (sluggify(k),v) for k,v in self.env.iteritems())
def update_request(self): def update_request(self):
''' '''
update request from self update request from self
@@ -1099,7 +1107,7 @@ class MapUrlIn(object):
if self.language: if self.language:
uri = '/%s%s' % (self.language, uri) uri = '/%s%s' % (self.language, uri)
uri = '/%s%s%s%s' % ( uri = '/%s%s%s%s' % (
app, app,
uri, uri,
urllib.quote('/'+'/'.join(str(x) for x in self.args)) if self.args else '', urllib.quote('/'+'/'.join(str(x) for x in self.args)) if self.args else '',
('?' + self.query) if self.query else '') ('?' + self.query) if self.query else '')
@@ -1307,10 +1315,10 @@ def map_url_in(request, env, app=False):
if app: if app:
return map.application return map.application
root_static_file = map.map_root_static() # handle root-static files root_static_file, version = map.map_root_static() # handle root-static files
if root_static_file: if root_static_file:
map.update_request() map.update_request()
return (root_static_file, map.env) return (root_static_file, version, map.env)
# handle mapping of lang/static to static/lang in externally-rewritten URLs # handle mapping of lang/static to static/lang in externally-rewritten URLs
# in case we have to handle them ourselves # in case we have to handle them ourselves
if map.languages and map.map_static is False and map.arg0 == 'static' and map.args(1) in map.languages: if map.languages and map.map_static is False and map.arg0 == 'static' and map.args(1) in map.languages:
@@ -1319,14 +1327,14 @@ def map_url_in(request, env, app=False):
else: else:
map.map_language() map.map_language()
map.map_controller() map.map_controller()
static_file = map.map_static() static_file, version = map.map_static()
if static_file: if static_file:
map.update_request() map.update_request()
return (static_file, map.env) return (static_file, version, map.env)
map.map_function() map.map_function()
map.validate_args() map.validate_args()
map.update_request() map.update_request()
return (None, map.env) return (None, None, map.env)
def map_url_out(request, env, application, controller, def map_url_out(request, env, application, controller,
function, args, other, scheme, host, port): function, args, other, scheme, host, port):
@@ -1364,10 +1372,3 @@ def get_effective_router(appname):
if not routers or appname not in routers: if not routers or appname not in routers:
return None return None
return Storage(routers[appname]) # return a copy return Storage(routers[appname]) # return a copy