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