0001"""Pylons' WSGI middlewares"""
0002import logging
0003import os.path
0004import urllib
0005
0006from paste.deploy.converters import asbool
0007from paste.errordocument import StatusBasedForward
0008from paste.recursive import RecursiveMiddleware
0009from paste.urlparser import StaticURLParser
0010
0011from webhelpers.rails.asset_tag import javascript_path
0012
0013__pudge_all__ = ['StaticJavascripts', 'ErrorHandler', 'ErrorDocuments']
0014
0015media_path = os.path.join(os.path.dirname(__file__), 'media')
0016
0017log = logging.getLogger(__name__)
0018
0019
0020class StaticJavascripts(object):
0021 """Middleware for intercepting requests for WebHelpers' included
0022 javascript files.
0023
0024 Triggered when PATH_INFO begins with '/javascripts/'.
0025 """
0026 def __init__(self):
0027 self.javascripts_app = StaticURLParser(os.path.dirname(javascript_path))
0029
0030 def __call__(self, environ, start_response):
0031 if environ.get('PATH_INFO', '').startswith('/javascripts/'):
0032 log.debug("Handling Javascript URL (Starts with /javascripts/)")
0033 return self.javascripts_app(environ, start_response)
0034 else:
0035 return self.javascripts_app.not_found(environ, start_response)
0036
0037
0038def ErrorHandler(app, global_conf, **errorware):
0039 """ErrorHandler Toggle
0040
0041 If debug is enabled, this function will return the app wrapped in
0042 our customized Paste EvalException middleware we have called the
0043 ``PylonsEvalException``.
0044
0045 Otherwise, the app will be wrapped in the Paste ErrorMiddleware, and
0046 the ``errorware`` dict will be passed into it.
0047 """
0048 if asbool(global_conf.get('debug')):
0049 from pylons.error import PylonsEvalException
0050 app = PylonsEvalException(app, global_conf, **errorware)
0051 else:
0052 from paste.exceptions.errormiddleware import ErrorMiddleware
0053 if 'error_template' in errorware:
0054 del errorware['error_template']
0055 app = ErrorMiddleware(app, global_conf, **errorware)
0056 return app
0057
0058
0059def error_mapper(code, message, environ, global_conf=None, **kw):
0060 if environ.get('pylons.error_call'):
0061 return None
0062 else:
0063 environ['pylons.error_call'] = True
0064
0065 if global_conf is None:
0066 global_conf = {}
0067 codes = [401, 403, 404]
0068 if not asbool(global_conf.get('debug')):
0069 codes.append(500)
0070 if code in codes:
0071 # StatusBasedForward expects a relative URL (no SCRIPT_NAME)
0072 url = '/error/document/?%s' % (urllib.urlencode({'message': message,
0073 'code': code}))
0074 return url
0075
0076
0077def ErrorDocuments(app, global_conf=None, mapper=None, **kw):
0078 """Wraps the app in error docs using Paste RecursiveMiddleware and
0079 ErrorDocumentsMiddleware
0080
0081 All the args are passed directly into the ErrorDocumentsMiddleware. If no
0082 mapper is given, a default error_mapper is passed in.
0083 """
0084 if global_conf is None:
0085 global_conf = {}
0086 if mapper is None:
0087 mapper = error_mapper
0088 return RecursiveMiddleware(StatusBasedForward(app, global_conf=global_conf,
0089 mapper=mapper, **kw))
0090
0091
0092error_document_template = """\
0093<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
0094<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
0095<head>
0096 <title>Server Error %(code)s</title>
0097
0098<style type="text/css">
0099body {
0100 font-family: Helvetica, sans-serif;
0101}
0102
0103table {
0104 width: 100%%;
0105}
0106
0107tr.header {
0108 background-color: #006;
0109 color: #fff;
0110}
0111
0112tr.even {
0113 background-color: #ddd;
0114}
0115
0116table.variables td {
0117 verticle-align: top;
0118 overflow: auto;
0119}
0120
0121a.button {
0122 background-color: #ccc;
0123 border: 2px outset #aaa;
0124 color: #000;
0125 text-decoration: none;
0126}
0127
0128a.button:hover {
0129 background-color: #ddd;
0130}
0131
0132code.source {
0133 color: #006;
0134}
0135
0136a.switch_source {
0137 color: #0990;
0138 text-decoration: none;
0139}
0140
0141a.switch_source:hover {
0142 background-color: #ddd;
0143}
0144
0145.source-highlight {
0146 background-color: #ff9;
0147}
0148
0149</style>
0150
0151<!-- CSS Imports -->
0152<link rel="stylesheet" href="%(prefix)s/error/style/orange.css" type="text/css" media="screen" />
0153
0154<!-- Favorite Icons -->
0155<link rel="icon" href="%(prefix)s/error/img/icon-16.png" type="image/png" />
0156
0157<style type="text/css">
0158 .red {
0159 color:#FF0000;
0160 }
0161 .bold {
0162 font-weight: bold;
0163 }
0164</style>
0165
0166</head>
0167
0168<body id="documentation">
0169<!-- We are only using a table to ensure old browsers see the message correctly -->
0170
0171<noscript>
0172<div style="border-bottom: 1px solid #808080">
0173<div style="border-bottom: 1px solid #404040">
0174<table width="100%%" border="0" cellpadding="0" bgcolor="#FFFFE1"><tr><td valign="middle"><img src="%(prefix)s/error/img/warning.gif" alt="Warning" /></td><td> </td><td><span style="padding: 0px; margin: 0px; font-family: Tahoma, sans-serif; font-size: 11px">Warning, your browser does not support JavaScript so you will not be able to use the interactive debugging on this page.</span></td></tr></table>
0175</div>
0176</div>
0177</noscript>
0178
0179 <!-- Top anchor -->
0180 <a name="top"></a>
0181
0182 <!-- Logo -->
0183 <h1 id="logo"><a class="no-underline" href="http://www.pylonshq.com"><img class="no-border" src="%(prefix)s/error/img/logo.gif" alt="Pylons" title="Pylons"/></a></h1>
0184 <p class="invisible"><a href="#content">Skip to content</a></p>
0185
0186 <!-- Main Content -->
0187
0188 <div id="nav-bar">
0189
0190 <!-- Section Navigation -->
0191 <h4 class="invisible">Section Links</h4>
0192
0193 <ul id="navlist">
0194 <li class="active"><a href="#" accesskey="1" class="active">Error %(code)s</a></li>
0195 </ul>
0196 </div>
0197 <div id="main-content">
0198
0199 <div class="hr"><hr class="hr" /></div>
0200
0201 <div class="content-padding">
0202
0203 <div id="main_data">
0204 <div style="float: left; width: 100%%; padding-bottom: 20px;">
0205 <h1 class="first"><a name="content"></a>Error %(code)s</h1>
0206 </div>
0207
0208 %(message)s
0209
0210 </div>
0211
0212 </div>
0213
0214
0215 <!-- Footer -->
0216
0217 <div class="hr"><hr class="clear" /></div>
0218 </div>
0219
0220 <div style=" background: #FFFF99; padding: 10px 10px 10px 6%%; clear: both;">
0221 The Pylons Team |
0222 <a href="#top" accesskey="9" title="Return to the top of the navigation links">Top</a>
0223 </div>
0224</body>
0225</html>
0226"""