1 # -*- coding: utf-8 -*-
4 # Etalage -- Open Data POIs portal
5 # By: Emmanuel Raviart <eraviart@easter-eggs.com>
7 # Copyright (C) 2011, 2012 Easter-eggs
8 # http://gitorious.org/infos-pratiques/etalage
10 # This file is part of Etalage.
12 # Etalage is free software; you can redistribute it and/or modify
13 # it under the terms of the GNU Affero General Public License as
14 # published by the Free Software Foundation, either version 3 of the
15 # License, or (at your option) any later version.
17 # Etalage is distributed in the hope that it will be useful,
18 # but WITHOUT ANY WARRANTY; without even the implied warranty of
19 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 # GNU Affero General Public License for more details.
22 # You should have received a copy of the GNU Affero General Public License
23 # along with this program. If not, see <http://www.gnu.org/licenses/>.
26 """Middleware initialization"""
32 from beaker.middleware import SessionMiddleware
33 from paste.cascade import Cascade
34 from paste.urlparser import StaticURLParser
35 from weberror.errormiddleware import ErrorMiddleware
37 from . import conf, contexts, controllers, environment, urls, wsgihelpers
40 lang_re = re.compile('^/(?P<lang>en|fr)(?=/|$)')
41 percent_encoding_re = re.compile('%[\dA-Fa-f]{2}')
44 @wsgihelpers.wsgify.middleware
45 def environment_setter(req, app):
46 """WSGI middleware that sets request-dependant environment."""
47 urls.application_url = req.application_url
51 @wsgihelpers.wsgify.middleware
52 def language_detector(req, app):
53 """WSGI middleware that detect language symbol in requested URL or otherwise in Accept-Language header."""
54 ctx = contexts.Ctx(req)
55 match = lang_re.match(req.path_info)
58 #req.accept_language.best_match([('en-US', 1), ('en', 1), ('fr-FR', 1), ('fr', 1)],
59 # default_match = 'en').split('-', 1)[0],
63 ctx.lang = [match.group('lang')]
64 req.script_name += req.path_info[:match.end()]
65 req.path_info = req.path_info[match.end():]
66 return req.get_response(app)
69 def make_app(global_conf, **app_conf):
70 """Create a WSGI application and return it
73 The inherited configuration for this application. Normally from
74 the [DEFAULT] section of the Paste ini file.
77 The application's local configuration. Normally specified in
78 the [app:<name>] section of the Paste ini file (where <name>
81 # Configure the environment and fill conf dictionary.
82 environment.load_environment(global_conf, app_conf)
84 # Dispatch request to controllers.
85 app = controllers.make_router()
88 app = SessionMiddleware(app, conf)
90 # Init request-dependant environment
91 app = environment_setter(app)
92 app = language_detector(app)
94 # Repair badly encoded query in request URL.
95 app = request_query_encoding_fixer(app)
97 # CUSTOM MIDDLEWARE HERE (filtered by error handling middlewares)
99 # Handle Python exceptions
100 if not conf['debug']:
101 app = ErrorMiddleware(app, global_conf, **conf['errorware'])
103 if conf['static_files']:
104 # Serve static files.
106 if conf['custom_static_files_dir'] is not None:
107 cascaded_apps.append(StaticURLParser(conf['custom_static_files_dir']))
108 cascaded_apps.append(StaticURLParser(conf['static_files_dir']))
109 cascaded_apps.append(app)
110 app = Cascade(cascaded_apps)
115 @wsgihelpers.wsgify.middleware
116 def request_query_encoding_fixer(req, app):
117 """WSGI middleware that repairs a badly encoded query in request URL."""
118 query_string = req.query_string
119 if query_string is not None:
121 urllib.unquote(query_string).decode('utf-8')
122 except UnicodeDecodeError:
123 req.query_string = percent_encoding_re.sub(
124 lambda match: urllib.quote(urllib.unquote(match.group(0)).decode('iso-8859-1').encode('utf-8')),
126 return req.get_response(app)