0001"""
0002WSGI proxy application that applies a deliverance theme while
0003passing the request to another HTTP server
0004"""
0005
0006import urlparse
0007from cStringIO import StringIO
0008import threading
0009import sys
0010from paste.proxy import TransparentProxy
0011
0012class ForcedProxy(object):
0013
0014 def __init__(self, remote, force_host=True):
0015 self.remote = remote
0016 self.remote_parts = urlparse.urlsplit(remote, 'http')
0017 self.force_host = force_host
0018 if force_host:
0019 proxy_force_host = self.remote_parts[1]
0020 else:
0021 proxy_force_host = None
0022 self.proxy_app = TransparentProxy(
0023 force_host=proxy_force_host)
0024
0025 def __repr__(self):
0026 return '<%s %s remote=%r force_host=%r>' % (
0027 self.__class__.__name__,
0028 hex(id(self)),
0029 self.remote,
0030 self.force_host)
0031
0032 def __call__(self, environ, start_response):
0033 if self.force_host:
0034 environ['HTTP_X_FORWARDED_SERVER'] = environ.get('HTTP_HOST', '')
0035 environ['HTTP_HOST'] = self.remote_parts[1]
0036 environ['HTTP_X_FORWARDED_SCHEME'] = environ['wsgi.url_scheme']
0037 remote_netloc = self.remote_parts[1]
0038 if ':' in remote_netloc:
0039 remote_host, remote_port = remote_netloc.split(':', 1)
0040 else:
0041 remote_host = remote_netloc
0042 if environ['wsgi.url_scheme'] == 'http':
0043 remote_port = '80'
0044 else:
0045 remote_port = '443'
0046 environ['SERVER_NAME'] = remote_host
0047 environ['SERVER_PORT'] = remote_port
0048 environ['wsgi.url_scheme'] = self.remote_parts[0]
0049 remote_qs = self.remote_parts[4]
0050 if remote_qs:
0051 cur = environ.get('QUERY_STRING', '')
0052 if cur:
0053 cur += '&' + remote_qs
0054 else:
0055 cur = remote_qs
0056 environ['QUERY_STRING'] = remote_qs
0057 environ['SCRIPT_NAME'] = self.remote_parts[2]
0058
0059
0060 return self.proxy_app(environ, start_response)
0061
0062
0063class DebugHeaders(object):
0064
0065 translate_keys = {
0066 'CONTENT_LENGTH': 'HTTP_CONTENT_LENGTH',
0067 'CONTENT_TYPE': 'HTTP_CONTENT_TYPE',
0068 }
0069
0070 def __init__(self, app, show_body=False, output=sys.stdout):
0071 self.app = app
0072 self.show_body = show_body
0073 self.output = output or sys.stdout
0074
0075 def __call__(self, environ, start_response):
0076 from paste.request import construct_url
0077 self.output.write(
0078 'Incoming headers: (%s %s)\n' %
0079 (environ['REQUEST_METHOD'], construct_url(environ)))
0080 for name, value in sorted(environ.items()):
0081 name = self.translate_keys.get(name, name)
0082 if not name.startswith('HTTP_'):
0083 continue
0084 name = name[5:].replace('_', '-').title()
0085 self.output.write(' %s: %s\n' % (name, value))
0086 if self.show_body:
0087 self.show_request_body(environ)
0088 def repl_start_response(status, headers, exc_info=None):
0089 self.output.write('Outgoing headers: (%s)\n' % status)
0090 for name, value in headers:
0091 self.output.write(' %s: %s\n' % (name.title(), value))
0092 start_response(status, headers, exc_info)
0093 return self.app(environ, repl_start_response)
0094
0095 def show_request_body(self, environ):
0096 length = int(environ.get('CONTENT_LENGTH') or '0')
0097 body = environ['wsgi.input'].read(length)
0098 environ['wsgi.input'] = StringIO(body)
0099 if body:
0100 for line in body.splitlines():
0101
0102 self.output.write(line.encode('string_escape')+'\n')
0103 self.output.write('-'*70+'\n')
0104
0105def make_debug_headers(app, global_conf, show_body=False,
0106 stderr=False):
0107 """
0108 Show all the headers that come to the application.
0109
0110 These are printed to sys.stdout, or sys.stderr if stderr=True. If
0111 show_body is true, then the body of all requests is also
0112 displayed.
0113 """
0114 from paste.deploy.converters import asbool
0115 if asbool(stderr):
0116 output = sys.stderr
0117 else:
0118 output = sys.stdout
0119 return DebugHeaders(app, show_body=asbool(show_body),
0120 output=output)