Package restkit :: Package ext :: Module wsgi_proxy
[hide private]
[frames] | no frames]

Source Code for Module restkit.ext.wsgi_proxy

  1  # -*- coding: utf-8 - 
  2  # 
  3  # This file is part of restkit released under the MIT license.  
  4  # See the NOTICE for more information. 
  5   
  6  import urlparse 
  7  from restkit import ConnectionPool, request 
  8  from restkit.sock import MAX_BODY 
  9   
 10  ALLOWED_METHODS = ['GET', 'HEAD'] 
 11   
 12  BLOCK_SIZE = 4096 * 16 
 13   
14 -class ResponseIter(object):
15
16 - def __init__(self, response):
17 response.CHUNK_SIZE = BLOCK_SIZE 18 self.body = response.body_file
19
20 - def next(self):
21 data = self.body.read(BLOCK_SIZE) 22 if not data: 23 raise StopIteration 24 return data
25
26 - def __iter__(self):
27 return self
28
29 -class Proxy(object):
30 """A proxy wich redirect the request to SERVER_NAME:SERVER_PORT 31 and send HTTP_HOST header""" 32
33 - def __init__(self, pool=None, allowed_methods=ALLOWED_METHODS, 34 strip_script_name=True, **kwargs):
35 self.pool = pool or ConnectionPool(**kwargs) 36 self.allowed_methods = allowed_methods 37 self.strip_script_name = strip_script_name
38
39 - def extract_uri(self, environ):
40 port = None 41 scheme = environ['wsgi.url_scheme'] 42 if 'SERVER_NAME' in environ: 43 host = environ['SERVER_NAME'] 44 else: 45 host = environ['HTTP_HOST'] 46 if ':' in host: 47 host, port = host.split(':') 48 49 if not port: 50 if 'SERVER_PORT' in environ: 51 port = environ['SERVER_PORT'] 52 else: 53 port = scheme == 'https' and '443' or '80' 54 55 uri = '%s://%s:%s' % (scheme, host, port) 56 return uri
57
58 - def __call__(self, environ, start_response):
59 method = environ['REQUEST_METHOD'] 60 if method not in self.allowed_methods: 61 start_response('403 Forbidden', ()) 62 return [''] 63 64 if self.strip_script_name: 65 path_info = '' 66 else: 67 path_info = environ['SCRIPT_NAME'] 68 path_info += environ['PATH_INFO'] 69 70 query_string = environ['QUERY_STRING'] 71 if query_string: 72 path_info += '?' + query_string 73 74 uri = self.extract_uri(environ)+path_info 75 76 new_headers = {} 77 for k, v in environ.items(): 78 if k.startswith('HTTP_'): 79 k = k[5:].replace('_', '-').title() 80 new_headers[k] = v 81 82 for k, v in (('CONTENT_TYPE', None), ('CONTENT_LENGTH', '0')): 83 v = environ.get(k, None) 84 if v is not None: 85 new_headers[k.replace('_', '-').title()] = v 86 87 response = request(uri, method, 88 body=environ['wsgi.input'], headers=new_headers, 89 pool_instance=self.pool) 90 91 start_response(response.status, response.headerslist) 92 93 if 'content-length' in response and \ 94 int(response['content-length']) <= MAX_BODY: 95 return [response.body] 96 97 return ResponseIter(response)
98
99 -class TransparentProxy(Proxy):
100 """A proxy based on HTTP_HOST environ variable""" 101
102 - def extract_uri(self, environ):
103 port = None 104 scheme = environ['wsgi.url_scheme'] 105 host = environ['HTTP_HOST'] 106 if ':' in host: 107 host, port = host.split(':') 108 109 if not port: 110 port = scheme == 'https' and '443' or '80' 111 112 uri = '%s://%s:%s' % (scheme, host, port) 113 return uri
114 115
116 -class HostProxy(Proxy):
117 """A proxy to redirect all request to a specific uri""" 118
119 - def __init__(self, uri, **kwargs):
120 super(HostProxy, self).__init__(**kwargs) 121 self.uri = uri.rstrip('/') 122 self.scheme, self.net_loc = urlparse.urlparse(self.uri)[0:2]
123
124 - def extract_uri(self, environ):
125 environ['HTTP_HOST'] = self.net_loc 126 return self.uri
127 128
129 -class CouchdbProxy(HostProxy):
130 """A proxy to redirect all request to CouchDB database"""
131 - def __init__(self, db_name='', uri='http://127.0.0.1:5984', 132 allowed_methods=['GET'], **kwargs):
133 uri = uri.rstrip('/') 134 if db_name: 135 uri += '/' + db_name.strip('/') 136 super(CouchdbProxy, self).__init__(uri, allowed_methods=allowed_methods, 137 **kwargs)
138
139 -def get_config(local_config):
140 """parse paste config""" 141 config = {} 142 allowed_methods = local_config.get('allowed_methods', None) 143 if allowed_methods: 144 config['allowed_methods'] = [m.upper() for m in allowed_methods.split()] 145 strip_script_name = local_config.get('strip_script_name', 'true') 146 if strip_script_name.lower() in ('false', '0'): 147 config['strip_script_name'] = False 148 config['max_connections'] = int(local_config.get('max_connections', '5')) 149 return config
150
151 -def make_proxy(global_config, **local_config):
152 """TransparentProxy entry_point""" 153 config = get_config(local_config) 154 print 'Running TransparentProxy with %s' % config 155 return TransparentProxy(**config)
156
157 -def make_host_proxy(global_config, uri=None, **local_config):
158 """HostProxy entry_point""" 159 uri = uri.rstrip('/') 160 config = get_config(local_config) 161 print 'Running HostProxy on %s with %s' % (uri, config) 162 return HostProxy(uri, **config)
163
164 -def make_couchdb_proxy(global_config, db_name='', uri='http://127.0.0.1:5984', 165 **local_config):
166 """CouchdbProxy entry_point""" 167 uri = uri.rstrip('/') 168 config = get_config(local_config) 169 print 'Running CouchdbProxy on %s/%s with %s' % (uri, db_name, config) 170 return CouchdbProxy(db_name=db_name, uri=uri, **config)
171