_log = logging.getLogger(__name__)
+class Context(object):
+ """
+ MediaGoblin context object.
+
+ If a web request is being used, a Flask Request object is used
+ instead, otherwise (celery tasks, etc), attach things to this
+ object.
+
+ Usually appears as "ctx" in utilities as first argument.
+ """
+ pass
+
+
class MediaGoblinApp(object):
"""
WSGI application of MediaGoblin
self.meddleware = [common.import_component(m)(self)
for m in meddleware.ENABLED_MEDDLEWARE]
- def call_backend(self, environ, start_response):
- request = Request(environ)
-
- # Compatibility with django, use request.args preferrably
- request.GET = request.args
+ def gen_context(self, ctx=None):
+ """
+ Attach contextual information to request, or generate a context object
- ## Routing / controller loading stuff
- map_adapter = self.url_map.bind_to_environ(request.environ)
+ This avoids global variables; various utilities and contextual
+ information (current translation, etc) are attached to this
+ object.
+ """
+ # Set up context
+ # --------------
- # By using fcgi, mediagoblin can run under a base path
- # like /mediagoblin/. request.path_info contains the
- # path inside mediagoblin. If the something needs the
- # full path of the current page, that should include
- # the basepath.
- # Note: urlgen and routes are fine!
- request.full_path = environ["SCRIPT_NAME"] + request.path
- # python-routes uses SCRIPT_NAME. So let's use that too.
- # The other option would be:
- # request.full_path = environ["SCRIPT_URL"]
+ # Is a context provided?
+ if ctx is not None:
+ # Do special things if this is a request
+ if isinstance(ctx, Request):
+ ctx = self._request_only_gen_context(ctx)
- # Fix up environ for urlgen
- # See bug: https://bitbucket.org/bbangert/routes/issue/55/cache_hostinfo-breaks-on-https-off
- if environ.get('HTTPS', '').lower() == 'off':
- environ.pop('HTTPS')
+ else:
+ ctx = Context()
+
+ # Attach utilities
+ # ----------------
- ## Attach utilities to the request object
- # Do we really want to load this via middleware? Maybe?
- session_manager = self.session_manager
- request.session = session_manager.load_session_from_cookie(request)
# Attach self as request.app
# Also attach a few utilities from request.app for convenience?
- request.app = self
+ ctx.app = self
- request.db = self.db
- request.staticdirect = self.staticdirector
+ ctx.db = self.db
+ ctx.staticdirect = self.staticdirector
+
+ return ctx
+
+ def _request_only_gen_context(self, request):
+ """
+ Requests get some extra stuff attached to them that's not relevant
+ otherwise.
+ """
+ # Do we really want to load this via middleware? Maybe?
+ request.session = self.session_manager.load_session_from_cookie(request)
request.locale = translate.get_locale_from_request(request)
+
+ # This should be moved over for certain, but how to deal with
+ # request.locale?
request.template_env = template.get_jinja_env(
self.template_loader, request.locale)
+ mg_request.setup_user_in_request(request)
+
+ ## Routing / controller loading stuff
+ request.map_adapter = self.url_map.bind_to_environ(request.environ)
+
def build_proxy(endpoint, **kw):
try:
qualified = kw.pop('qualified')
except KeyError:
qualified = False
- return map_adapter.build(
+ return request.map_adapter.build(
endpoint,
values=dict(**kw),
force_external=qualified)
request.urlgen = build_proxy
+ return request
+
+ def call_backend(self, environ, start_response):
+ request = Request(environ)
+
+ # Compatibility with django, use request.args preferrably
+ request.GET = request.args
+
+ # By using fcgi, mediagoblin can run under a base path
+ # like /mediagoblin/. request.path_info contains the
+ # path inside mediagoblin. If the something needs the
+ # full path of the current page, that should include
+ # the basepath.
+ # Note: urlgen and routes are fine!
+ request.full_path = environ["SCRIPT_NAME"] + request.path
+ # python-routes uses SCRIPT_NAME. So let's use that too.
+ # The other option would be:
+ # request.full_path = environ["SCRIPT_URL"]
+
+ # Fix up environ for urlgen
+ # See bug: https://bitbucket.org/bbangert/routes/issue/55/cache_hostinfo-breaks-on-https-off
+ if environ.get('HTTPS', '').lower() == 'off':
+ environ.pop('HTTPS')
+
+ ## Attach utilities to the request object
+ request = self.gen_context(request)
+
# Log user out if authentication_disabled
no_auth_logout(request)
- mg_request.setup_user_in_request(request)
-
request.controller_name = None
try:
- found_rule, url_values = map_adapter.match(return_rule=True)
+ found_rule, url_values = request.map_adapter.match(return_rule=True)
request.matchdict = url_values
except RequestRedirect as response:
# Deal with 301 responses eg due to missing final slash
# used for lazy context modification
request.controller_name = found_rule.endpoint
+ ## TODO: get rid of meddleware, turn it into hooks only
# pass the request through our meddleware classes
try:
for m in self.meddleware:
response = render_http_exception(
request, e, e.get_description(environ))
- session_manager.save_session_to_cookie(request.session,
- request, response)
+ self.session_manager.save_session_to_cookie(
+ request.session,
+ request, response)
return response(environ, start_response)