1
2
3
4
5
6 import urlparse
7
8 try:
9 from cStringIO import StringIO
10 except ImportError:
11 from StringIO import StringIO
12
13 from restkit.client import Client
14 from restkit.conn import MAX_BODY
15 from restkit.util import rewrite_location
16
17 ALLOWED_METHODS = ['GET', 'HEAD', 'POST', 'PUT', 'DELETE']
18
19 BLOCK_SIZE = 4096 * 16
20
21 WEBOB_ERROR = ("Content-Length is set to -1. This usually mean that WebOb has "
22 "already parsed the content body. You should set the Content-Length "
23 "header to the correct value before forwarding your request to the "
24 "proxy: ``req.content_length = str(len(req.body));`` "
25 "req.get_response(proxy)")
26
28 """A proxy wich redirect the request to SERVER_NAME:SERVER_PORT
29 and send HTTP_HOST header"""
30
33 self.allowed_methods = allowed_methods
34 self.strip_script_name = strip_script_name
35 self.client = Client(**kwargs)
36
38 port = None
39 scheme = environ['wsgi.url_scheme']
40 if 'SERVER_NAME' in environ:
41 host = environ['SERVER_NAME']
42 else:
43 host = environ['HTTP_HOST']
44 if ':' in host:
45 host, port = host.split(':')
46
47 if not port:
48 if 'SERVER_PORT' in environ:
49 port = environ['SERVER_PORT']
50 else:
51 port = scheme == 'https' and '443' or '80'
52
53 uri = '%s://%s:%s' % (scheme, host, port)
54 return uri
55
56 - def __call__(self, environ, start_response):
57 method = environ['REQUEST_METHOD']
58 if method not in self.allowed_methods:
59 start_response('403 Forbidden', ())
60 return ['']
61
62 if self.strip_script_name:
63 path_info = ''
64 else:
65 path_info = environ['SCRIPT_NAME']
66 path_info += environ['PATH_INFO']
67
68 query_string = environ['QUERY_STRING']
69 if query_string:
70 path_info += '?' + query_string
71
72 host_uri = self.extract_uri(environ)
73 uri = host_uri + path_info
74
75 new_headers = {}
76 for k, v in environ.items():
77 if k.startswith('HTTP_'):
78 k = k[5:].replace('_', '-').title()
79 new_headers[k] = v
80
81 for k, v in (('CONTENT_TYPE', None), ('CONTENT_LENGTH', '0')):
82 v = environ.get(k, None)
83 if v is not None:
84 new_headers[k.replace('_', '-').title()] = v
85
86 if new_headers.get('Content-Length', '0') == '-1':
87 raise ValueError(WEBOB_ERROR)
88
89 response = self.client.request(uri, method, body=environ['wsgi.input'],
90 headers=new_headers)
91
92 if 'location' in response:
93 if self.strip_script_name:
94 prefix_path = environ['SCRIPT_NAME']
95
96 new_location = rewrite_location(host_uri, response.location,
97 prefix_path=prefix_path)
98
99 headers = []
100 for k, v in response.headerslist:
101 if k.lower() == 'location':
102 v = new_location
103 headers.append((k, v))
104 else:
105 headers = response.headerslist
106
107 start_response(response.status, headers)
108
109 if method == "HEAD":
110 return StringIO()
111
112 return response.tee()
113
115 """A proxy based on HTTP_HOST environ variable"""
116
118 port = None
119 scheme = environ['wsgi.url_scheme']
120 host = environ['HTTP_HOST']
121 if ':' in host:
122 host, port = host.split(':')
123
124 if not port:
125 port = scheme == 'https' and '443' or '80'
126
127 uri = '%s://%s:%s' % (scheme, host, port)
128 return uri
129
130
132 """A proxy to redirect all request to a specific uri"""
133
135 super(HostProxy, self).__init__(**kwargs)
136 self.uri = uri.rstrip('/')
137 self.scheme, self.net_loc = urlparse.urlparse(self.uri)[0:2]
138
140 environ['HTTP_HOST'] = self.net_loc
141 return self.uri
142
144 """parse paste config"""
145 config = {}
146 allowed_methods = local_config.get('allowed_methods', None)
147 if allowed_methods:
148 config['allowed_methods'] = [m.upper() for m in allowed_methods.split()]
149 strip_script_name = local_config.get('strip_script_name', 'true')
150 if strip_script_name.lower() in ('false', '0'):
151 config['strip_script_name'] = False
152 config['max_connections'] = int(local_config.get('max_connections', '5'))
153 return config
154
156 """TransparentProxy entry_point"""
157 config = get_config(local_config)
158 print 'Running TransparentProxy with %s' % config
159 return TransparentProxy(**config)
160
162 """HostProxy entry_point"""
163 uri = uri.rstrip('/')
164 config = get_config(local_config)
165 print 'Running HostProxy on %s with %s' % (uri, config)
166 return HostProxy(uri, **config)
167