def _make_core_app(root, global_conf, full_stack=True, **app_conf): """ Set allura up with the settings found in the PasteDeploy configuration file used. :param root: The controller module containing the TG root :param global_conf: The global settings for allura (those defined under the ``[DEFAULT]`` section). :type global_conf: dict :param full_stack: Should the whole TG2 stack be set up? :type full_stack: str or bool :return: The allura application with all the relevant middleware loaded. This is the PasteDeploy factory for the allura application. ``app_conf`` contains all the application-specific settings (those defined under ``[app:main]``. """ # Run all the initialization code here mimetypes.init( [pkg_resources.resource_filename('allura', 'etc/mime.types')] + mimetypes.knownfiles) patches.apply() # Configure MongoDB ming.configure(**app_conf) # Configure ActivityStream activitystream.configure(**app_conf) # Configure EW variable provider ew.render.TemplateEngine.register_variable_provider(get_tg_vars) # Create base app base_config = ForgeConfig(root) load_environment = base_config.make_load_environment() # Code adapted from tg.configuration, replacing the following lines: # make_base_app = base_config.setup_tg_wsgi_app(load_environment) # app = make_base_app(global_conf, full_stack=True, **app_conf) # Configure the Pylons environment load_environment(global_conf, app_conf) if config.get('zarkov.host'): try: import zmq except ImportError: raise ImportError, "Unable to import the zmq library. Please"\ " check that zeromq is installed or comment out"\ " the zarkov.host setting in your ini file." app = tg.TGApp() if asbool(config.get('auth.method', 'local')=='sfx'): import sfx.middleware d = h.config_with_prefix(config, 'auth.') d.update(h.config_with_prefix(config, 'sfx.')) app = sfx.middleware.SfxMiddleware(app, d) # Required for pylons app = RoutesMiddleware(app, config['routes.map']) # Required for sessions app = SessionMiddleware(app, config) # Converts exceptions to HTTP errors, shows traceback in debug mode app = tg.error.ErrorHandler(app, global_conf, **config['pylons.errorware']) # Redirect some status codes to /error/document if asbool(config['debug']): app = StatusCodeRedirect(app, base_config.handle_status_codes) else: app = StatusCodeRedirect(app, base_config.handle_status_codes + [500]) # Redirect 401 to the login page app = LoginRedirectMiddleware(app) # Add instrumentation app = AlluraTimerMiddleware(app, app_conf) # Clear cookies when the CSRF field isn't posted if not app_conf.get('disable_csrf_protection'): app = CSRFMiddleware(app, '_session_id') # Setup the allura SOPs app = allura_globals_middleware(app) # Ensure https for logged in users, http for anonymous ones if asbool(app_conf.get('auth.method', 'local')=='sfx'): app = SSLMiddleware(app, app_conf.get('no_redirect.pattern')) # Setup resource manager, widget context SOP app = ew.WidgetMiddleware( app, compress=not asbool(global_conf['debug']), # compress=True, script_name=app_conf.get('ew.script_name', '/_ew_resources/'), url_base=app_conf.get('ew.url_base', '/_ew_resources/'), extra_headers=eval(app_conf.get('ew.extra_headers', 'None'))) # Make sure that the wsgi.scheme is set appropriately when we # have the funky HTTP_X_SFINC_SSL environ var if asbool(app_conf.get('auth.method', 'local')=='sfx'): app = set_scheme_middleware(app) # Handle static files (by tool) app = StaticFilesMiddleware(app, app_conf.get('static.script_name')) # Handle setup and flushing of Ming ORM sessions app = MingMiddleware(app) # Set up the registry for stacked object proxies (SOPs). # streaming=true ensures they won't be cleaned up till # the WSGI application's iterator is exhausted app = RegistryManager(app, streaming=True) return app
def make_app(global_conf, full_stack=True, static_files=True, **app_conf): """Create a Pylons WSGI application and return it ``global_conf`` The inherited configuration for this application. Normally from the [DEFAULT] section of the Paste ini file. ``full_stack`` Whether this application provides a full WSGI stack (by default, meaning it handles its own exceptions and errors). Disable full_stack when this application is "managed" by another WSGI middleware. ``static_files`` Whether this application serves its own static files; disable when another web server is responsible for serving them. ``app_conf`` The application's local configuration. Normally specified in the [app:<name>] section of the Paste ini file (where <name> defaults to main). """ # Configure the Pylons environment config = load_environment(global_conf, app_conf) # The Pylons WSGI app app = PylonsApp(config=config) # Set error handler, if we're customizing the full stack. This can't be merged # with the block below, because order is important with middleware. The # VariableErrorHandler relies on SessionMiddleware, so it needs to be wrapped tighter # (instantiated before, ergo called after). if asbool(full_stack): app = VariableErrorHandler(app, global_conf, **config['pylons.errorware']) # Routing/Session Middleware app = RoutesMiddleware(app, config['routes.map'], singleton=False) app = SessionMiddleware(app, config) # CUSTOM MIDDLEWARE HERE (filtered by error handling middlewares) if asbool(full_stack): # Display error documents for 401, 403, 404 status codes (and # 500 when debug is disabled) if asbool(config['debug']): app = StatusCodeRedirect(app) else: app = StatusCodeRedirect(app, [400, 401, 403, 404, 500]) # Establish the Registry for this application app = RegistryManager(app) if asbool(static_files): # Serve static files static_app = StaticURLParser(config['pylons.paths']['static_files']) app_list = [static_app, app] if config['files_storage'].startswith('file://'): images_app = StaticURLParser( config['files_storage'][len('file://'):]) app_list.insert(0, images_app) app = Cascade(app_list) app.config = config return app
def make_app(global_conf, full_stack=True, static_files=True, **app_conf): """Create a Pylons WSGI application and return it ``global_conf`` The inherited configuration for this application. Normally from the [DEFAULT] section of the Paste ini file. ``full_stack`` Whether this application provides a full WSGI stack (by default, meaning it handles its own exceptions and errors). Disable full_stack when this application is "managed" by another WSGI middleware. ``static_files`` Whether this application serves its own static files; disable when another web server is responsible for serving them. ``app_conf`` The application's local configuration. Normally specified in the [app:<name>] section of the Paste ini file (where <name> defaults to main). """ # Configure the Pylons environment config = load_environment(global_conf, app_conf) # The Pylons WSGI app app = PylonsApp(config=config) # Routing/Session/Cache Middleware app = RoutesMiddleware(app, config['routes.map']) app = SessionMiddleware(app, config) # CUSTOM MIDDLEWARE HERE (filtered by error handling middlewares) if asbool(full_stack): # Handle Python exceptions app = ErrorHandler(app, global_conf, **config['pylons.errorware']) # Display error documents for 401, 403, 404 status codes (and # 500 when debug is disabled) if asbool(config['debug']): app = StatusCodeRedirect(app) else: app = StatusCodeRedirect(app, [400, 401, 403, 404, 500]) from repoze.who.config import make_middleware_with_config app = make_middleware_with_config(app, global_conf, app_conf['who.config_file'], app_conf['who.log_file'], app_conf['who.log_level']) # Establish the Registry for this application app = RegistryManager(app) if asbool(static_files): # Serve static files static_app = StaticURLParser(config['pylons.paths']['static_files']) app = Cascade([static_app, app]) app.config = config return app
def make_app(conf, full_stack=True, static_files=True, **app_conf): """Create a Pylons WSGI application and return it ``conf`` The inherited configuration for this application. Normally from the [DEFAULT] section of the Paste ini file. ``full_stack`` Whether this application provides a full WSGI stack (by default, meaning it handles its own exceptions and errors). Disable full_stack when this application is "managed" by another WSGI middleware. ``static_files`` Whether this application serves its own static files; disable when another web server is responsible for serving them. ``app_conf`` The application's local configuration. Normally specified in the [app:<name>] section of the Paste ini file (where <name> defaults to main). """ # Configure the Pylons environment load_environment(conf, app_conf) # The Pylons WSGI app app = PylonsApp() # set pylons globals app_globals.reset() for plugin in PluginImplementations(IMiddleware): app = plugin.make_middleware(app, config) # Routing/Session/Cache Middleware app = RoutesMiddleware(app, config['routes.map']) # we want to be able to retrieve the routes middleware to be able to update # the mapper. We store it in the pylons config to allow this. config['routes.middleware'] = app app = SessionMiddleware(app, config) app = CacheMiddleware(app, config) # CUSTOM MIDDLEWARE HERE (filtered by error handling middlewares) #app = QueueLogMiddleware(app) # Fanstatic if asbool(config.get('debug', False)): fanstatic_config = { 'versioning': True, 'recompute_hashes': True, 'minified': False, 'bottom': True, 'bundle': False, } else: fanstatic_config = { 'versioning': True, 'recompute_hashes': False, 'minified': True, 'bottom': True, 'bundle': True, } app = Fanstatic(app, **fanstatic_config) if asbool(full_stack): # Handle Python exceptions app = ErrorHandler(app, conf, **config['pylons.errorware']) # Display error documents for 401, 403, 404 status codes (and # 500 when debug is disabled) if asbool(config['debug']): app = StatusCodeRedirect(app, [400, 404]) else: app = StatusCodeRedirect(app, [400, 404, 500]) # Initialize repoze.who who_parser = WhoConfig(conf['here']) who_parser.parse(open(app_conf['who.config_file'])) if asbool(config.get('openid_enabled', 'true')): from repoze.who.plugins.openid.identification import OpenIdIdentificationPlugin # Monkey patches for repoze.who.openid # Fixes #1659 - enable log-out when CKAN mounted at non-root URL from ckan.lib import repoze_patch OpenIdIdentificationPlugin.identify = repoze_patch.identify OpenIdIdentificationPlugin.redirect_to_logged_in = repoze_patch.redirect_to_logged_in OpenIdIdentificationPlugin._redirect_to_loginform = repoze_patch._redirect_to_loginform OpenIdIdentificationPlugin.challenge = repoze_patch.challenge who_parser.identifiers = [i for i in who_parser.identifiers if \ not isinstance(i, OpenIdIdentificationPlugin)] who_parser.challengers = [i for i in who_parser.challengers if \ not isinstance(i, OpenIdIdentificationPlugin)] app = PluggableAuthenticationMiddleware( app, who_parser.identifiers, who_parser.authenticators, who_parser.challengers, who_parser.mdproviders, who_parser.request_classifier, who_parser.challenge_decider, logging.getLogger('repoze.who'), logging.WARN, # ignored who_parser.remote_user_key, ) # Establish the Registry for this application app = RegistryManager(app) app = I18nMiddleware(app, config) if asbool(static_files): # Serve static files static_max_age = None if not asbool(config.get('ckan.cache_enabled')) \ else int(config.get('ckan.static_max_age', 3600)) static_app = StaticURLParser(config['pylons.paths']['static_files'], cache_max_age=static_max_age) static_parsers = [static_app, app] storage_directory = uploader.get_storage_path() if storage_directory: path = os.path.join(storage_directory, 'storage') try: os.makedirs(path) except OSError, e: ## errno 17 is file already exists if e.errno != 17: raise storage_app = StaticURLParser(path, cache_max_age=static_max_age) static_parsers.insert(0, storage_app) # Configurable extra static file paths extra_static_parsers = [] for public_path in config.get('extra_public_paths', '').split(','): if public_path.strip(): extra_static_parsers.append( StaticURLParser(public_path.strip(), cache_max_age=static_max_age)) app = Cascade(extra_static_parsers + static_parsers)
def make_app(global_conf, full_stack=True, static_files=True, **app_conf): """Create a Pylons WSGI application and return it ``global_conf`` The inherited configuration for this application. Normally from the [DEFAULT] section of the Paste ini file. ``full_stack`` Whether this application provides a full WSGI stack (by default, meaning it handles its own exceptions and errors). Disable full_stack when this application is "managed" by another WSGI middleware. ``static_files`` Whether this application serves its own static files; disable when another web server is responsible for serving them. ``app_conf`` The application's local configuration. Normally specified in the [app:<name>] section of the Paste ini file (where <name> defaults to main). """ # Configure the Pylons environment log.debug('loading environment') config = load_environment(global_conf, app_conf) # The Pylons WSGI app app = PylonsApp(config=config) # Routing/Session Middleware app = RoutesMiddleware(app, config['routes.map']) app = SessionMiddleware(app, config) # FTS3 authentication/authorization middleware app = FTS3AuthMiddleware(app, config) # Trap timeouts and the like app = TimeoutHandler(app, config) # Convert errors to a json representation app = ErrorAsJson(app, config) # Request logging app = RequestLogger(app, config) # Error handling if asbool(full_stack): # Handle Python exceptions app = ErrorHandler(app, global_conf, **config['pylons.errorware']) # Establish the Registry for this application app = RegistryManager(app) if asbool(static_files): # Serve static files static_app = StaticURLParser(config['pylons.paths']['static_files']) app = Cascade([static_app, app]) app.config = config # Heartbeat thread Heartbeat('fts_rest', int(config.get('fts3.HeartBeatInterval', 60))).start() # Start OIDC clients if "fts3.Providers" in app.config and app.config["fts3.Providers"]: oidc_manager.setup(app.config) IAMTokenRefresher("fts_token_refresh_daemon", app.config).start() log.info("OpenID Connect support enabled.") else: log.info( "OpenID Connect support disabled. Providers not found in config") return app
def make_app(global_conf, full_stack=True, static_files=True, **app_conf): """Create a Pylons WSGI application and return it ``global_conf`` The inherited configuration for this application. Normally from the [DEFAULT] section of the Paste ini file. ``full_stack`` Whether this application provides a full WSGI stack (by default, meaning it handles its own exceptions and errors). Disable full_stack when this application is "managed" by another WSGI middleware. ``static_files`` Whether this application serves its own static files; disable when another web server is responsible for serving them. ``app_conf`` The application's local configuration. Normally specified in the [app:<name>] section of the Paste ini file (where <name> defaults to main). """ # Configure the Pylons environment config = load_environment(global_conf, app_conf) # The Pylons WSGI app app = PylonsApp(config=config) if config['profile']: # pragma: no cover - nightly profiles do the full stack from repoze.profiler import AccumulatingProfileMiddleware app = AccumulatingProfileMiddleware( app, log_filename='/tmp/cb-website.prof', discard_first_request=True, flush_at_shutdown=True, path='/__profile__' ) # Routing/Session/Cache Middleware app = RoutesMiddleware(app, config['routes.map']) app = SessionMiddleware(app, config) #app = CacheMiddleware(app, config) # Cache now setup in app_globals as suggested in http://pylonshq.com/docs/en/1.0/upgrading/ # CUSTOM MIDDLEWARE HERE (filtered by error handling middlewares) app = MobileDetectionMiddleware(app) app = EnvironMiddleware(app) app = SecurifyCookiesMiddleware(app) if asbool(full_stack): # Handle Python exceptions app = ErrorHandler(app, global_conf, **config['pylons.errorware']) # Establish the Registry for this application app = RegistryManager(app) if asbool(static_files): # Serve static files static_app = HeaderURLParser(config['pylons.paths']['static_files']) app = Cascade([static_app, app]) app.config = config return app
def __init__(self, mapper): self.map = mapper self.router = RoutesMiddleware(self.route, self.map)
def make_app(global_conf, full_stack=True, static_files=True, **app_conf): """Create a Pylons WSGI application and return it ``global_conf`` The inherited configuration for this application. Normally from the [DEFAULT] section of the Paste ini file. ``full_stack`` Whether this application provides a full WSGI stack (by default, meaning it handles its own exceptions and errors). Disable full_stack when this application is "managed" by another WSGI middleware. ``static_files`` Whether this application serves its own static files; disable when another web server is responsible for serving them. ``app_conf`` The application's local configuration. Normally specified in the [app:<name>] section of the Paste ini file (where <name> defaults to main). """ # Configure the Pylons environment config = load_environment(global_conf, app_conf) plugin_mgr = config['pylons.app_globals'].plugin_mgr # The Pylons WSGI app app = PylonsApp(config=config) # Allow the plugin manager to tweak our WSGI app app = plugin_mgr.wrap_pylons_app(app) # Routing/Session/Cache Middleware app = RoutesMiddleware(app, config['routes.map'], singleton=False) app = SessionMiddleware(app, config) # CUSTOM MIDDLEWARE HERE (filtered by error handling middlewares) # Set up repoze.what-quickstart authentication: # http://wiki.pylonshq.com/display/pylonscookbook/Authorization+with+repoze.what app = add_auth(app, config) # ToscaWidgets Middleware app = setup_tw_middleware(app, config) # Strip the name of the .fcgi script, if using one, from the SCRIPT_NAME app = FastCGIScriptStripperMiddleware(app) # If enabled, set up the proxy prefix for routing behind # fastcgi and mod_proxy based deployments. if config.get('proxy_prefix', None): app = setup_prefix_middleware(app, global_conf, config['proxy_prefix']) # END CUSTOM MIDDLEWARE if asbool(full_stack): # Handle Python exceptions app = ErrorHandler(app, global_conf, **config['pylons.errorware']) # Display error documents for 401, 403, 404 status codes (and # 500 when debug is disabled) if asbool(config['debug']): app = StatusCodeRedirect(app) else: app = StatusCodeRedirect(app, [400, 401, 403, 404, 500]) # Cleanup the DBSession only after errors are handled app = DBSessionRemoverMiddleware(app) # Establish the Registry for this application app = RegistryManager(app) if asbool(static_files): # Serve static files from our public directory public_app = StaticURLParser(config['pylons.paths']['static_files']) static_urlmap = URLMap() # Serve static files from all plugins for dir, path in plugin_mgr.public_paths().iteritems(): static_urlmap[dir] = StaticURLParser(path) # Serve static media and podcast images from outside our public directory for image_type in ('media', 'podcasts'): dir = '/images/' + image_type path = os.path.join(config['image_dir'], image_type) static_urlmap[dir] = StaticURLParser(path) # Serve appearance directory outside of public as well dir = '/appearance' path = os.path.join(config['app_conf']['cache_dir'], 'appearance') static_urlmap[dir] = StaticURLParser(path) # We want to serve goog closure code for debugging uncompiled js. if config['debug']: goog_path = os.path.join(config['pylons.paths']['root'], '..', 'closure-library', 'closure', 'goog') if os.path.exists(goog_path): static_urlmap['/scripts/goog'] = StaticURLParser(goog_path) app = Cascade([public_app, static_urlmap, app]) if asbool(config.get('enable_gzip', 'true')): app = setup_gzip_middleware(app, global_conf) app.config = config return app
def make_app(global_conf, full_stack=True, static_files=True, **app_conf): """Create a Pylons WSGI application and return it ``global_conf`` The inherited configuration for this application. Normally from the [DEFAULT] section of the Paste ini file. ``full_stack`` Whether this application provides a full WSGI stack (by default, meaning it handles its own exceptions and errors). Disable full_stack when this application is "managed" by another WSGI middleware. ``static_files`` Whether this application serves its own static files; disable when another web server is responsible for serving them. ``app_conf`` The application's local configuration. Normally specified in the [app:<name>] section of the Paste ini file (where <name> defaults to main). """ debug = (asbool(global_conf.get('debug', False)) or asbool(app_conf.get('debug', False))) # Configure the Pylons environment config = load_environment(global_conf, app_conf) # The Pylons WSGI app app = PylonsApp(config=config) if debug and asbool(app_conf.get('adhocracy.enable_profiling', False)): from werkzeug.contrib.profiler import ProfilerMiddleware app = ProfilerMiddleware(app, sort_by=('ncalls', ), restrictions=('src/adhocracy/.*', 25)) # Routing/Session/Cache Middleware app = RoutesMiddleware(app, config['routes.map']) if config.get('adhocracy.session.implementation', 'beaker') == 'cookie': app = CookieSessionMiddleware(app, config) else: app = beaker.middleware.SessionMiddleware(app, config) app = beaker.middleware.CacheMiddleware(app, config) # app = make_profile_middleware(app, config, # log_filename='profile.log.tmp') # CUSTOM MIDDLEWARE HERE (filtered by error handling middlewares) app = setup_auth(app, config) app = make_prefix_middleware(app, config, scheme=config.get('adhocracy.protocol', 'http')) app = setup_discriminator(app, config) if asbool(config.get('adhocracy.requestlog_active', 'False')): app = RequestLogger(app, config) if asbool(full_stack): # Handle Python exceptions if debug or aconfig.get_bool('adhocracy.send_error_emails', config=config): app = ErrorHandler(app, global_conf, **config['pylons.errorware']) # Display error documents for 401, 403, 404 status codes app = StatusCodeRedirect(app, [400, 401, 403, 404, 500]) if aconfig.get_bool('adhocracy.sentry.enabled', config=config): app = SentryMiddleware(app, config) # Establish the Registry for this application app = RegistryManager(app) if asbool(static_files): cache_age = int(config.get('adhocracy.static.age', 7200)) # Serve static files overlay_app = StaticURLParser( get_site_path('static', app_conf=config), cache_max_age=None if debug else cache_age) static_app = StaticURLParser( config['pylons.paths']['static_files'], cache_max_age=None if debug else cache_age) app = Cascade([overlay_app, static_app, app]) # Fanstatic inserts links for javascript and css ressources. # The required resources can be specified at runtime with <resource>.need() # and can will be delivered with version specifiers in the url and # minified when not in debug mode. fanstatic_base_url = base_url('', instance=None, config=config).rstrip('/') app = Fanstatic(app, minified=not (debug), versioning=True, recompute_hashes=debug, bundle=not (debug), base_url=fanstatic_base_url, bottom=True) if asbool(config.get('adhocracy.include_machine_name_in_header', 'false')): app = IncludeMachineName(app, config) app = CorsMiddleware(app, config) app.config = config return app
def make_app(global_conf, full_stack=True, static_files=True, **app_conf): """Create a Pylons WSGI application and return it ``global_conf`` The inherited configuration for this application. Normally from the [DEFAULT] section of the Paste ini file. ``full_stack`` Whether or not this application provides a full WSGI stack (by default, meaning it handles its own exceptions and errors). Disable full_stack when this application is "managed" by another WSGI middleware. ``static_files`` Whether this application serves its own static files; disable when another web server is responsible for serving them. ``app_conf`` The application's local configuration. Normally specified in the [app:<name>] section of the Paste ini file (where <name> defaults to main). """ # Configure the Pylons environment load_environment(global_conf, app_conf) # Add missing mime types for k, v in app_conf.iteritems(): if k.startswith('mimetype.'): mimetypes.add_type(v, k[8:]) # The Pylons WSGI app app = PylonsApp() # Routing/Session/Cache Middleware app = RoutesMiddleware(app, config['routes.map']) if asbool(config.get('etag.enable', True)): app = EtagMiddleware(app, config) if asbool(config.get('compact.enable', True)): app = CompactMiddleware(app, config) app = SessionMiddleware(app, config) app = CacheMiddleware(app, config) # CUSTOM MIDDLEWARE HERE (filtered by error handling middlewares) if asbool(full_stack): app = ErrorMiddleware(app, config) # Establish the Registry for this application app = RegistryManager(app) if asbool(static_files): # Serve static files max_age = asint(config.get('cache_max_age.staticmax', 1)) static_external_paths = config['pylons.paths']['static_external_paths'] static_development_paths = config['pylons.paths']['static_development_paths'] static_release_paths = config['pylons.paths']['static_release_paths'] static_viewer_paths = config['pylons.paths']['static_viewer_paths'] # Order is important for performance # file paths will be check sequentially the first time the file is requested if asbool(config.get('scripts.development', False)): all_path_items = [(path, 0) for path in static_development_paths] else: all_path_items = [(path, 28800) for path in static_development_paths] all_path_items.extend([(path, max_age) for path in static_external_paths]) all_path_items.extend([(path, max_age) for path in static_release_paths]) if asbool(config.get('viewer.development', 'false')): # We only need to supply the jslib files with the viewer in development mode all_path_items.extend([(path, 0) for path in static_viewer_paths]) all_path_items.extend([(os.path.join(path, 'jslib'), 0) for path in static_viewer_paths]) app = StaticFilesMiddleware(app, all_path_items) app = StaticGameFilesMiddleware(app, staticmax_max_age=max_age) app = GzipMiddleware(app, config) app = MetricsMiddleware(app, config) app = LoggingMiddleware(app, config) __add_customisations() __init_controllers() # Last middleware is the first middleware that gets executed for a request, and last for a response return app
def wrap_in_middleware(app, global_conf, **local_conf): """Based on the configuration wrap `app` in a set of common and useful middleware.""" # Merge the global and local configurations conf = global_conf.copy() conf.update(local_conf) debug = asbool(conf.get('debug', False)) # First put into place httpexceptions, which must be most closely # wrapped around the application (it can interact poorly with # other middleware): app = httpexceptions.make_middleware(app, conf) log.debug("Enabling 'httpexceptions' middleware") # Create a separate mapper for redirects to prevent conflicts. redirect_mapper = routes.Mapper() redirect_mapper = _map_redirects(redirect_mapper) # Load the Routes middleware which we use for redirecting app = RoutesMiddleware(app, redirect_mapper) log.debug("Enabling 'routes' middleware") # If we're using remote_user authentication, add middleware that # protects Galaxy from improperly configured authentication in the # upstream server if asbool(conf.get('use_remote_user', False)): from galaxy.webapps.tool_shed.framework.middleware.remoteuser import RemoteUser app = RemoteUser( app, maildomain=conf.get('remote_user_maildomain', None), display_servers=util.listify(conf.get('display_servers', '')), admin_users=conf.get('admin_users', '').split(','), remote_user_secret_header=conf.get('remote_user_secret', None)) log.debug("Enabling 'remote user' middleware") # The recursive middleware allows for including requests in other # requests or forwarding of requests, all on the server side. if asbool(conf.get('use_recursive', True)): from paste import recursive app = recursive.RecursiveMiddleware(app, conf) log.debug("Enabling 'recursive' middleware") if debug and asbool(conf.get('use_interactive', False)) and not process_is_uwsgi: # Interactive exception debugging, scary dangerous if publicly # accessible, if not enabled we'll use the regular error printing # middleware. from weberror import evalexception app = evalexception.EvalException( app, conf, templating_formatters=build_template_error_formatters()) log.debug("Enabling 'eval exceptions' middleware") else: if debug and asbool(conf.get('use_interactive', False)) and process_is_uwsgi: log.error( "Interactive debugging middleware is enabled in your configuration " "but this is a uwsgi process. Refusing to wrap in interactive error middleware." ) # Not in interactive debug mode, just use the regular error middleware import galaxy.web.framework.middleware.error app = galaxy.web.framework.middleware.error.ErrorMiddleware(app, conf) log.debug("Enabling 'error' middleware") # Transaction logging (apache access.log style) if asbool(conf.get('use_translogger', True)): from paste.translogger import TransLogger app = TransLogger(app) log.debug("Enabling 'trans logger' middleware") # If sentry logging is enabled, log here before propogating up to # the error middleware # TODO sentry config is duplicated between tool_shed/galaxy, refactor this. sentry_dsn = conf.get('sentry_dsn', None) if sentry_dsn: from galaxy.web.framework.middleware.sentry import Sentry log.debug("Enabling 'sentry' middleware") app = Sentry(app, sentry_dsn) # X-Forwarded-Host handling from galaxy.web.framework.middleware.xforwardedhost import XForwardedHostMiddleware app = XForwardedHostMiddleware(app) log.debug("Enabling 'x-forwarded-host' middleware") # Various debug middleware that can only be turned on if the debug # flag is set, either because they are insecure or greatly hurt # performance. The print debug middleware needs to be loaded last, # since there is a quirk in its behavior that breaks some (but not # all) subsequent middlewares. if debug: # Middleware to check for WSGI compliance if asbool(conf.get('use_lint', True)): from paste import lint app = lint.make_middleware(app, conf) log.debug("Enabling 'lint' middleware") # Middleware to run the python profiler on each request if asbool(conf.get('use_profile', False)): import profile app = profile.ProfileMiddleware(app, conf) log.debug("Enabling 'profile' middleware") # Middleware that intercepts print statements and shows them on the # returned page if asbool(conf.get('use_printdebug', True)): from paste.debug import prints app = prints.PrintDebugMiddleware(app, conf) log.debug("Enabling 'print debug' middleware") return app
def make_app(global_conf, full_stack=True, static_files=True, **app_conf): """Create a Pylons WSGI application and return it ``global_conf`` The inherited configuration for this application. Normally from the [DEFAULT] section of the Paste ini file. ``full_stack`` Whether this application provides a full WSGI stack (by default, meaning it handles its own exceptions and errors). Disable full_stack when this application is "managed" by another WSGI middleware. ``static_files`` Whether this application serves its own static files; disable when another web server is responsible for serving them. ``app_conf`` The application's local configuration. Normally specified in the [app:<name>] section of the Paste ini file (where <name> defaults to main). """ # Configure the Pylons environment config = load_environment(global_conf, app_conf) alembic_migrations = MediaDropMigrator.from_config(config, log=log) db_is_current = True if not alembic_migrations.is_db_scheme_current(): log.warn( 'Running with an outdated database scheme. Please upgrade your database.' ) db_is_current = False plugin_mgr = config['pylons.app_globals'].plugin_mgr db_current_for_plugins = plugin_mgr.is_db_scheme_current_for_all_plugins() if db_is_current and not db_current_for_plugins: log.warn(db_current_for_plugins.message) db_is_current = False if db_is_current: events.Environment.database_ready() # The Pylons WSGI app app = PylonsApp(config=config) # Allow the plugin manager to tweak our WSGI app app = plugin_mgr.wrap_pylons_app(app) # Routing/Session/Cache Middleware app = RoutesMiddleware(app, config['routes.map'], singleton=False) app = SessionMiddleware(app, config) # CUSTOM MIDDLEWARE HERE (filtered by error handling middlewares) # add repoze.who middleware with our own authorization library app = add_auth(app, config) # ToscaWidgets Middleware app = setup_tw_middleware(app, config) # Strip the name of the .fcgi script, if using one, from the SCRIPT_NAME app = FastCGIScriptStripperMiddleware(app) # If enabled, set up the proxy prefix for routing behind # fastcgi and mod_proxy based deployments. if config.get('proxy_prefix', None): app = setup_prefix_middleware(app, global_conf, config['proxy_prefix']) # END CUSTOM MIDDLEWARE if asbool(full_stack): # Handle Python exceptions app = ErrorHandler(app, global_conf, **config['pylons.errorware']) # by default Apache uses a global alias for "/error" in the httpd.conf # which means that users can not send error reports through MediaDrop's # error page (because that POSTs to /error/report). # To make things worse Apache (at least up to 2.4) has no "unalias" # functionality. So we work around the issue by using the "/errors" # prefix (extra "s" at the end) error_path = '/errors/document' # Display error documents for 401, 403, 404 status codes (and # 500 when debug is disabled) if asbool(config['debug']): app = StatusCodeRedirect(app, path=error_path) else: app = StatusCodeRedirect(app, errors=(400, 401, 403, 404, 500), path=error_path) # Cleanup the DBSession only after errors are handled app = DBSessionRemoverMiddleware(app) # Establish the Registry for this application app = RegistryManager(app) app = setup_db_sanity_checks(app, config) if asbool(static_files): # Serve static files from our public directory public_app = StaticURLParser(config['pylons.paths']['static_files']) static_urlmap = URLMap() # Serve static files from all plugins for dir, path in plugin_mgr.public_paths().iteritems(): static_urlmap[dir] = StaticURLParser(path) # Serve static media and podcast images from outside our public directory for image_type in ('media', 'podcasts'): dir = '/images/' + image_type path = os.path.join(config['image_dir'], image_type) static_urlmap[dir] = StaticURLParser(path) # Serve appearance directory outside of public as well dir = '/appearance' path = os.path.join(config['app_conf']['cache_dir'], 'appearance') static_urlmap[dir] = StaticURLParser(path) # We want to serve goog closure code for debugging uncompiled js. if config['debug']: goog_path = os.path.join(config['pylons.paths']['root'], '..', 'closure-library', 'closure', 'goog') if os.path.exists(goog_path): static_urlmap['/scripts/goog'] = StaticURLParser(goog_path) app = Cascade([public_app, static_urlmap, app]) if asbool(config.get('enable_gzip', 'true')): app = setup_gzip_middleware(app, global_conf) app.config = config return app
def make_app(global_conf, full_stack=True, static_files=True, **app_conf): """Create a Pylons WSGI application and return it ``global_conf`` The inherited configuration for this application. Normally from the [DEFAULT] section of the Paste ini file. ``full_stack`` Whether this application provides a full WSGI stack (by default, meaning it handles its own exceptions and errors). Disable full_stack when this application is "managed" by another WSGI middleware. ``static_files`` Whether this application serves its own static files; disable when another web server is responsible for serving them. ``app_conf`` The application's local configuration. Normally specified in the [app:<name>] section of the Paste ini file (where <name> defaults to main). """ # Configure the Pylons environment load_environment(global_conf, app_conf) # The Pylons WSGI app app = PylonsApp() # Undefer POST parsing by undoing DeferPOSTParsing middleware work. app = kwmo.lib.middlewares.UnDeferPOSTParsing(app) # KWMO session middleware app = KwmoSessionMiddleware(app, config) # KWMO middleware - wrap kwmo application. app = kwmo.lib.middlewares.KWMOMiddleware(app) # Routing/Session/Cache Middleware app = RoutesMiddleware(app, config['routes.map']) app = CacheMiddleware(app, config) # Catch KJsonifyException exceptions and send a json exception in the body. app = kwmo.lib.middlewares.JSONErrorMiddleware(app) # Teambox debugging. if config['debug']: app = kwmo.lib.middlewares.TeamboxDebugMiddleware(app) # Production setup. else: app = ErrorHandler(app, global_conf, **config['pylons.errorware']) # Handle special status codes. app = StatusCodeRedirect(app, [400, 401, 403, 404, 500]) # Establish the Registry for this application app = RegistryManager(app) if asbool(static_files): # Serve static files static_app = StaticURLParser(config['pylons.paths']['static_files']) app = Cascade([static_app, app]) app = kwmo.lib.middlewares.ContentLengthMiddleware(app) # Defer POST parsing by hiding the real input body file object and providing an empty StringIO() instead. app = kwmo.lib.middlewares.DeferPOSTParsing(app) # Change the url scheme when needed. if config.has_key('url_scheme'): app = kwmo.lib.middlewares.UrlSchemeMiddleware(app, config['url_scheme']) return app
def make_app(global_conf, full_stack=True, static_files=True, **app_conf): """ Create a Pylons WSGI application and return it ``global_conf`` The inherited configuration for this application. Normally from the [DEFAULT] section of the Paste ini file. ``full_stack`` Whether this application provides a full WSGI stack (by default, meaning it handles its own exceptions and errors). Disable full_stack when this application is "managed" by another WSGI middleware. ``static_files`` Whether this application serves its own static files; disable when another web server is responsible for serving them. ``app_conf`` The application's local configuration. Normally specified in the [app:<name>] section of the Paste ini file (where <name> defaults to main). """ # Configure the Pylons environment config = load_environment(global_conf, app_conf) # The Pylons WSGI app app = PylonsApp() # Profiling Middleware if profile_load: if asbool(config['profile']): app = AccumulatingProfileMiddleware( app, log_filename='/var/log/linotp/profiling.log', cachegrind_filename='/var/log/linotp/cachegrind.out', discard_first_request=True, flush_at_shutdown=True, path='/__profile__') # Routing/Session/Cache Middleware app = RoutesMiddleware(app, config['routes.map']) app = SessionMiddleware(app, config) app = CacheMiddleware(app, config) g = config['pylons.app_globals'] g.cache_manager = app.cache_manager # CUSTOM MIDDLEWARE HERE (filtered by error handling middlewares) if asbool(full_stack): # Handle Python exceptions app = ErrorHandler(app, global_conf, **config['pylons.errorware']) # Display error documents for 401, 403, 404 status codes (and # 500 when debug is disabled) if asbool(config['debug']): app = StatusCodeRedirect(app) else: app = StatusCodeRedirect(app, [400, 401, 403, 404, 500]) # Establish the Registry for this application app = RegistryManager(app) if asbool(static_files): # Serve static files static_app = StaticURLParser(config['pylons.paths']['static_files']) app = Cascade([static_app, app]) # repoze.who if repoze_load: if 'who.generate_random_secret' in app_conf and not app_conf[ 'who.generate_random_secret']: app = make_who_with_config(app, global_conf, app_conf['who.config_file'], app_conf['who.log_file'], app_conf['who.log_level']) else: # Read the current configuration file and replace "secret" keys in every line who_config_lines = [] secret = binascii.hexlify(os.urandom(16)) if len(secret) != 32: raise RuntimeError( 'Could not generate random repoze.who secret, no os.urandom support?' ) with open(app_conf['who.config_file']) as f: for line in f.readlines(): who_config_lines.append( re.sub(r'^(secret)\s*=\s*.*$', r'\1 = %s' % secret, line)) with tempinput(''.join(who_config_lines)) as who_config_file: app = make_who_with_config(app, global_conf, who_config_file, app_conf['who.log_file'], app_conf['who.log_level']) # this is a compatibility hack for pylons > 1.0!!! conf = PyConf(config) conf['global_conf'] = global_conf conf['app_conf'] = app_conf conf['__file__'] = global_conf['__file__'] conf['FILE'] = global_conf['__file__'] conf['routes.map'] = config['routes.map'] if not hasattr(conf, 'init_app'): setattr(conf, 'init_app', config.init_app) app.config = conf return app
def make_app(global_conf, full_stack=True, static_files=True, **app_conf): """Create a Pylons WSGI application and return it ``global_conf`` The inherited configuration for this application. Normally from the [DEFAULT] section of the Paste ini file. ``full_stack`` Whether or not this application provides a full WSGI stack (by default, meaning it handles its own exceptions and errors). Disable full_stack when this application is "managed" by another WSGI middleware. ``app_conf`` The application's local configuration. Normally specified in the [app:<name>] section of the Paste ini file (where <name> defaults to main). """ # Configure the Pylons environment config = load_environment(global_conf, app_conf) # The Pylons WSGI app app = PylonsApp(config=config) # Routing/Session/Cache Middleware app = RoutesMiddleware(app, config['routes.map']) app = SessionMiddleware(app, config) # CUSTOM MIDDLEWARE HERE (filtered by error handling middlewares) if asbool(config['pdebug']): from rhodecode.lib.profiler import ProfilingMiddleware app = ProfilingMiddleware(app) if asbool(full_stack): from rhodecode.lib.middleware.sentry import Sentry from rhodecode.lib.middleware.errormator import Errormator if Errormator and asbool(config['app_conf'].get('errormator')): app = Errormator(app, config) elif Sentry: app = Sentry(app, config) # Handle Python exceptions app = ErrorHandler(app, global_conf, **config['pylons.errorware']) # we want our low level middleware to get to the request ASAP. We don't # need any pylons stack middleware in them app = SimpleHg(app, config) app = SimpleGit(app, config) app = RequestWrapper(app, config) # Display error documents for 401, 403, 404 status codes (and # 500 when debug is disabled) if asbool(config['debug']): app = StatusCodeRedirect(app) else: app = StatusCodeRedirect(app, [400, 401, 403, 404, 500]) #enable https redirets based on HTTP_X_URL_SCHEME set by proxy app = HttpsFixup(app, config) # Establish the Registry for this application app = RegistryManager(app) if asbool(static_files): # Serve static files static_app = StaticURLParser(config['pylons.paths']['static_files']) app = Cascade([static_app, app]) app = make_gzip_middleware(app, global_conf, compress_level=1) app.config = config return app
def make_app(global_conf, full_stack=True, **app_conf): """Create a Pylons WSGI application and return it `global_conf` The inherited configuration for this application. Normally from the [DEFAULT] section of the Paste ini file. `full_stack` Whether or not this application provides a full WSGI stack (by default, meaning it handles its own exceptions and errors). Disable full_stack when this application is "managed" by another WSGI middleware. `app_conf` The application's local configuration. Normally specified in the [app:<name>] section of the Paste ini file (where <name> defaults to main). """ # Configure the Pylons environment load_environment(global_conf, app_conf) g = config['pylons.g'] # The Pylons WSGI app app = RedditApp() app = RoutesMiddleware(app, config["routes.map"]) # CUSTOM MIDDLEWARE HERE (filtered by the error handling middlewares) # last thing first from here down app = CleanupMiddleware(app) app = LimitUploadSize(app) profile_directory = g.config.get('profile_directory') if profile_directory: app = ProfilingMiddleware(app, profile_directory) app = DomainListingMiddleware(app) app = SubredditMiddleware(app) app = ExtensionMiddleware(app) app = DomainMiddleware(app) if asbool(full_stack): # Handle Python exceptions app = ErrorHandler(app, global_conf, **config['pylons.errorware']) # Display error documents for 401, 403, 404 status codes (and 500 when # debug is disabled) app = ErrorDocuments(app, global_conf, mapper=error_mapper, **app_conf) # Establish the Registry for this application app = RegistryManager(app) # Static files static_app = StaticURLParser(config['pylons.paths']['static_files']) static_cascade = [static_app, app] if config['r2.plugins'] and g.config['uncompressedJS']: plugin_static_apps = Cascade([ StaticURLParser(plugin.static_dir) for plugin in config['r2.plugins'] ]) static_cascade.insert(0, plugin_static_apps) app = Cascade(static_cascade) #add the rewrite rules app = RewriteMiddleware(app) if not g.config['uncompressedJS'] and g.config['debug']: static_fallback = StaticTestMiddleware(static_app, g.config['static_path'], g.config['static_domain']) app = Cascade([static_fallback, app]) return app
def make_pylons_stack(conf, full_stack=True, static_files=True, **app_conf): """Create a Pylons WSGI application and return it ``conf`` The inherited configuration for this application. Normally from the [DEFAULT] section of the Paste ini file. ``full_stack`` Whether this application provides a full WSGI stack (by default, meaning it handles its own exceptions and errors). Disable full_stack when this application is "managed" by another WSGI middleware. ``static_files`` Whether this application serves its own static files; disable when another web server is responsible for serving them. ``app_conf`` The application's local configuration. Normally specified in the [app:<name>] section of the Paste ini file (where <name> defaults to main). """ # The Pylons WSGI app app = pylons_app = CKANPylonsApp() for plugin in PluginImplementations(IMiddleware): app = plugin.make_middleware(app, config) app = common_middleware.RootPathMiddleware(app, config) # Routing/Session/Cache Middleware app = RoutesMiddleware(app, config['routes.map']) # we want to be able to retrieve the routes middleware to be able to update # the mapper. We store it in the pylons config to allow this. config['routes.middleware'] = app app = SessionMiddleware(app, config) app = CacheMiddleware(app, config) # CUSTOM MIDDLEWARE HERE (filtered by error handling middlewares) # app = QueueLogMiddleware(app) if asbool(config.get('ckan.use_pylons_response_cleanup_middleware', True)): app = execute_on_completion(app, config, cleanup_pylons_response_string) # Fanstatic if asbool(config.get('debug', False)): fanstatic_config = { 'versioning': True, 'recompute_hashes': True, 'minified': False, 'bottom': True, 'bundle': False, } else: fanstatic_config = { 'versioning': True, 'recompute_hashes': False, 'minified': True, 'bottom': True, 'bundle': True, } app = Fanstatic(app, **fanstatic_config) for plugin in PluginImplementations(IMiddleware): try: app = plugin.make_error_log_middleware(app, config) except AttributeError: log.critical('Middleware class {0} is missing the method' 'make_error_log_middleware.' .format(plugin.__class__.__name__)) if asbool(full_stack): # Handle Python exceptions app = ErrorHandler(app, conf, **config['pylons.errorware']) # Display error documents for 400, 403, 404 status codes (and # 500 when debug is disabled) if asbool(config['debug']): app = StatusCodeRedirect(app, [400, 403, 404]) else: app = StatusCodeRedirect(app, [400, 403, 404, 500]) # Initialize repoze.who who_parser = WhoConfig(conf['here']) who_parser.parse(open(app_conf['who.config_file'])) app = PluggableAuthenticationMiddleware( app, who_parser.identifiers, who_parser.authenticators, who_parser.challengers, who_parser.mdproviders, who_parser.request_classifier, who_parser.challenge_decider, logging.getLogger('repoze.who'), logging.WARN, # ignored who_parser.remote_user_key ) # Establish the Registry for this application app = RegistryManager(app) app = common_middleware.I18nMiddleware(app, config) if asbool(static_files): # Serve static files static_max_age = None if not asbool( config.get('ckan.cache_enabled')) \ else int(config.get('ckan.static_max_age', 3600)) static_app = StaticURLParser( config['pylons.paths']['static_files'], cache_max_age=static_max_age) static_parsers = [static_app, app] storage_directory = uploader.get_storage_path() if storage_directory: path = os.path.join(storage_directory, 'storage') try: os.makedirs(path) except OSError, e: # errno 17 is file already exists if e.errno != 17: raise storage_app = StaticURLParser(path, cache_max_age=static_max_age) static_parsers.insert(0, storage_app) # Configurable extra static file paths extra_static_parsers = [] for public_path in config.get( 'extra_public_paths', '').split(','): if public_path.strip(): extra_static_parsers.append( StaticURLParser(public_path.strip(), cache_max_age=static_max_age) ) app = Cascade(extra_static_parsers + static_parsers)
def make_pylons_stack(conf, full_stack=True, static_files=True, **app_conf): """Create a Pylons WSGI application and return it ``conf`` The inherited configuration for this application. Normally from the [DEFAULT] section of the Paste ini file. ``full_stack`` Whether this application provides a full WSGI stack (by default, meaning it handles its own exceptions and errors). Disable full_stack when this application is "managed" by another WSGI middleware. ``static_files`` Whether this application serves its own static files; disable when another web server is responsible for serving them. ``app_conf`` The application's local configuration. Normally specified in the [app:<name>] section of the Paste ini file (where <name> defaults to main). """ # The Pylons WSGI app app = pylons_app = CKANPylonsApp() for plugin in PluginImplementations(IMiddleware): app = plugin.make_middleware(app, config) app = common_middleware.CloseWSGIInputMiddleware(app, config) app = common_middleware.RootPathMiddleware(app, config) # Routing/Session/Cache Middleware app = RoutesMiddleware(app, config['routes.map']) # we want to be able to retrieve the routes middleware to be able to update # the mapper. We store it in the pylons config to allow this. config['routes.middleware'] = app app = SessionMiddleware(app, config) app = CacheMiddleware(app, config) # CUSTOM MIDDLEWARE HERE (filtered by error handling middlewares) # app = QueueLogMiddleware(app) if asbool(config.get('ckan.use_pylons_response_cleanup_middleware', True)): app = execute_on_completion(app, config, cleanup_pylons_response_string) # Fanstatic fanstatic_enable_rollup = asbool(app_conf.get('fanstatic_enable_rollup', False)) if asbool(config.get('debug', False)): fanstatic_config = { 'versioning': True, 'recompute_hashes': True, 'minified': False, 'bottom': True, 'bundle': False, 'rollup': fanstatic_enable_rollup, } else: fanstatic_config = { 'versioning': True, 'recompute_hashes': False, 'minified': True, 'bottom': True, 'bundle': True, 'rollup': fanstatic_enable_rollup, } root_path = config.get('ckan.root_path', None) if root_path: root_path = re.sub('/{{LANG}}', '', root_path) fanstatic_config['base_url'] = root_path app = Fanstatic(app, **fanstatic_config) for plugin in PluginImplementations(IMiddleware): try: app = plugin.make_error_log_middleware(app, config) except AttributeError: log.critical('Middleware class {0} is missing the method' 'make_error_log_middleware.' .format(plugin.__class__.__name__)) if asbool(full_stack): # Handle Python exceptions app = ErrorHandler(app, conf, **config['pylons.errorware']) # Display error documents for 400, 403, 404 status codes (and # 500 when debug is disabled) if asbool(config['debug']): app = StatusCodeRedirect(app, [400, 403, 404]) else: app = StatusCodeRedirect(app, [400, 403, 404, 500]) # Initialize repoze.who who_parser = WhoConfig(conf['here']) who_parser.parse(open(app_conf['who.config_file'])) app = PluggableAuthenticationMiddleware( app, who_parser.identifiers, who_parser.authenticators, who_parser.challengers, who_parser.mdproviders, who_parser.request_classifier, who_parser.challenge_decider, logging.getLogger('repoze.who'), logging.WARN, # ignored who_parser.remote_user_key ) # Establish the Registry for this application app = RegistryManager(app, streaming=False) if asbool(static_files): # Serve static files static_max_age = None if not asbool( config.get('ckan.cache_enabled')) \ else int(config.get('ckan.static_max_age', 3600)) static_app = StaticURLParser( config['pylons.paths']['static_files'], cache_max_age=static_max_age) static_parsers = [static_app, app] storage_directory = uploader.get_storage_path() if storage_directory: path = os.path.join(storage_directory, 'storage') try: os.makedirs(path) except OSError as e: # errno 17 is file already exists if e.errno != 17: raise storage_app = StaticURLParser(path, cache_max_age=static_max_age) static_parsers.insert(0, storage_app) # Configurable extra static file paths extra_static_parsers = [] for public_path in config.get( 'extra_public_paths', '').split(','): if public_path.strip(): extra_static_parsers.append( StaticURLParser(public_path.strip(), cache_max_age=static_max_age) ) app = Cascade(extra_static_parsers + static_parsers) # Tracking if asbool(config.get('ckan.tracking_enabled', 'false')): app = common_middleware.TrackingMiddleware(app, config) # Add a reference to the actual Pylons app so it's easier to access app._wsgi_app = pylons_app return app
def make_app(global_conf, full_stack=True, static_files=True, **app_conf): """Create a Pylons WSGI application and return it ``global_conf`` The inherited configuration for this application. Normally from the [DEFAULT] section of the Paste ini file. ``full_stack`` Whether this application provides a full WSGI stack (by default, meaning it handles its own exceptions and errors). Disable full_stack when this application is "managed" by another WSGI middleware. ``static_files`` Whether this application serves its own static files; disable when another web server is responsible for serving them. ``app_conf`` The application's local configuration. Normally specified in the [app:<name>] section of the Paste ini file (where <name> defaults to main). """ debug = (asbool(global_conf.get('debug', False)) or asbool(app_conf.get('debug', False))) # Configure the Pylons environment load_environment(global_conf, app_conf) # The Pylons WSGI app app = PylonsApp() # Routing/Session/Cache Middleware app = RoutesMiddleware(app, config['routes.map']) app = SessionMiddleware(app, config) app = CacheMiddleware(app, config) #app = make_profile_middleware(app, config, log_filename='profile.log.tmp') # CUSTOM MIDDLEWARE HERE (filtered by error handling middlewares) app = setup_auth(app, config) app = setup_discriminator(app, config) if asbool(full_stack): # Handle Python exceptions app = ErrorHandler(app, global_conf, **config['pylons.errorware']) # Display error documents for 401, 403, 404 status codes (and # 500 when debug is disabled) if debug: app = StatusCodeRedirect(app) else: app = StatusCodeRedirect(app, [400, 401, 403, 404, 500]) # Establish the Registry for this application app = RegistryManager(app) if asbool(static_files): cache_age = int(config.get('adhocracy.static.age', 7200)) # Serve static files overlay_app = StaticURLParser( get_site_path('static'), cache_max_age=None if debug else cache_age) static_app = StaticURLParser( config['pylons.paths']['static_files'], cache_max_age=None if debug else cache_age) app = Cascade([overlay_app, static_app, app]) # Fanstatic inserts links for javascript and css ressources. # The required resources can be specified at runtime with <resource>.need() # and can will be delivered with version specifiers in the url and # minified when not in debug mode. app = Fanstatic( app, minified=not (debug), versioning=True, recompute_hashes=debug, bundle=not (debug), base_url=base_url(None).rstrip( '/'), # fanstatic's URL path already starts with / bottom=True) if asbool(config.get('adhocracy.include_machine_name_in_header', 'false')): app = IncludeMachineName(app, config) return app