Created
September 25, 2010 22:44
-
-
Save chrisgeo/597374 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
"""Combo Loader WSGI App | |
Variable location combo loader to import javascript and css files. | |
It will loader Javascript files into one JS and CSS into another much like YUI PHP Loader: | |
http://developer.yahoo.com/yui/phploader/ | |
TODO: | |
Build in caching beaker, sessions, and/or memcache. | |
""" | |
import sys | |
import webob | |
import webob.exc as exc | |
import json | |
import re | |
from comboloader.utils import HttpRequest, FileRequest | |
from beaker.middleware import SessionMiddleware | |
from paste.deploy.converters import asbool | |
import logging | |
log = logging.getLogger(__name__) | |
REQUEST_TYPES = { | |
'server': HttpRequest, | |
'file': FileRequest | |
} | |
required_config_keys = ['base', 'request_type', 'js_path', 'css_path', 'combo_base'] | |
def parse_json_confing(config_file): | |
"""Parse JSON for config | |
JSON will can look like this: | |
{ | |
"request_type": "server", | |
"comboBase": "www.cdn.com" | |
"base": "/base/path", //build directory | |
"js_path": "js", //path relative to base | |
"css_path": "path/to/css", //path relative to base; note: combo loader will try and search/replace images in CSS files | |
"filter": DEBUG|MIN | |
} | |
Otherwise uses the *.ini file to load the server config | |
""" | |
f = open(config_file, 'r') | |
content = f.read() | |
f.close() | |
config = json.loads(content) | |
#parse through options to load files by file name | |
missing_keys = [] | |
for key in required_config_keys: | |
if key not in config.keys(): | |
missing_keys.append(key) | |
if len(missing_keys) > 0: | |
raise Exception("Required keys are missing in config :: required are: %s ::: config is missing: %s" | |
% (required_config_keys, missing_keys)) | |
config['request_type'] = REQUEST_TYPES[config['request_type'].lower()] | |
return config | |
def parse_ini_config(config): | |
new_config = {} | |
new_config['request_type'] = REQUEST_TYPES['file'] | |
new_config['js_path'] = config['base_js_dir'] | |
new_config['css_path'] = config['base_css_dir'] | |
new_config['img_path'] = config['base_img_dir'] | |
new_config['filter'] = config.get('filter', 'min') | |
return new_config | |
def parse_config_file(config): | |
if asbool(config['use_config']): | |
new_config = parse_json_file(config['config_file']) | |
else: | |
new_config = parse_ini_config(config) | |
return new_config | |
class ComboLoaderApp(object): | |
"""ComboLoader WSGI App | |
Retrieves files from a filesystem or HTTP Request and concatenates them | |
into one file request | |
""" | |
def __init__(self, config): | |
self.config = parse_config_file(config) | |
self.js_regex = re.compile('^.+?\.js$', re.IGNORECASE) | |
self.css_regex = re.compile('^.+?\.css$', re.IGNORECASE) | |
def __call__(self, environ, start_response): | |
req = webob.Request(environ) | |
req.session = environ['beaker.session'] | |
self.js_regex = re.compile('^.+?\.js$', re.IGNORECASE) | |
self.css_regex = re.compile('^.+?\.css$', re.IGNORECASE) | |
#get files and munge together | |
#command line arguments | |
if not req.query_string: | |
return exc.HTTPBadRequest("Cannot have empty parameter list")(environ, start_response) | |
else: | |
files = dict(js=list(), css=list()) | |
#probably a more elegant way to do this. | |
for param in req.query_string.split('&'): | |
if(self.js_regex.match(param)): | |
files['js'].append(param) | |
elif(self.css_regex.match(param)): | |
files['css'].append(param) | |
return self.config['request_type'](request=req, config=self.config, files=files)(environ, start_response) | |
def make_app(config): | |
"""Construct WSGI App from JSON file""" | |
app = ComboLoaderApp(config) | |
app = SessionMiddleware(app, config) | |
return app | |
def make_loader_app(global_conf, **app_conf): | |
"""Construct a complete WSGI app ready to serve by Paste | |
Example INI file: | |
.. code-block:: ini | |
[server:main] | |
use = egg:Paste#http | |
host = 0.0.0.0 | |
port = 80 | |
[composite:main] | |
use = egg:Paste#urlmap | |
/ = YOURAPP | |
/loader = loader | |
[app:loader] | |
use = egg:comboloader | |
config_file = %(here)s/LOCATION_TO/CONFIG.json | |
beaker.session.data_dir = %(here)s/data/sdata | |
beaker.session.lock_dir = %(here)s/data/slock | |
beaker.session.key = comboloader | |
beaker.session.secret = somesecret | |
beaker.session.type = cookie | |
beaker.session.validate_key = STRONG_KEY_HERE | |
beaker.session.cookie_domain = .yourdomain.com | |
base_js_dir = %(here)s/js/ | |
base_css_dir = %(here)/css/ | |
use_config = False | |
[app:YOURAPP] | |
use = egg:YOURAPP | |
full_stack = true | |
static_files = true | |
""" | |
app = ComboLoaderApp(app_conf) | |
app = SessionMiddleware(app, app_conf) | |
return app |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment