def request(url, method='GET', body=None, headers=None, **kwargs): """ Quick shortcut method to pass a request :param url: str, url string :param method: str, by default GET. http verbs :param body: the body, could be a string, an iterator or a file-like object :param headers: dict or list of tupple, http headers Client parameters ~~~~~~~~~~~~~~~~~ :param follow_redirect: follow redirection, by default False :param max_ollow_redirect: number of redirections available :filters: http filters to pass :param decompress: allows the client to decompress the response body :param max_status_line_garbage: defines the maximum number of ignorable lines before we expect a HTTP response's status line. With HTTP/1.1 persistent connections, the problem arises that broken scripts could return a wrong Content-Length (there are more bytes sent than specified). Unfortunately, in some cases, this cannot be detected after the bad response, but only before the next one. So the client is abble to skip bad lines using this limit. 0 disable garbage collection, None means unlimited number of tries. :param max_header_count: determines the maximum HTTP header count allowed. by default no limit. :param manager: the manager to use. By default we use the global one. :parama response_class: the response class to use :param timeout: the default timeout of the connection (SO_TIMEOUT) :param max_tries: the number of tries before we give up a connection :param wait_tries: number of time we wait between each tries. :param ssl_args: ssl named arguments, See http://docs.python.org/library/ssl.html informations """ # detect credentials from url u = urlparse.urlparse(url) if u.username is not None: password = u.password or "" filters = kwargs.get('filters') or [] url = urlparse.urlunparse((u.scheme, u.netloc.split("@")[-1], u.path, u.params, u.query, u.fragment)) filters.append(BasicAuth(u.username, password)) kwargs['filters'] = filters http_client = Client(**kwargs) return http_client.request(url, method=method, body=body, headers=headers)
class Proxy(object): """A proxy wich redirect the request to SERVER_NAME:SERVER_PORT and send HTTP_HOST header""" def __init__(self, manager=None, allowed_methods=ALLOWED_METHODS, strip_script_name=True, **kwargs): self.allowed_methods = allowed_methods self.strip_script_name = strip_script_name self.client = Client(**kwargs) def extract_uri(self, environ): port = None scheme = environ['wsgi.url_scheme'] if 'SERVER_NAME' in environ: host = environ['SERVER_NAME'] else: host = environ['HTTP_HOST'] if ':' in host: host, port = host.split(':') if not port: if 'SERVER_PORT' in environ: port = environ['SERVER_PORT'] else: port = scheme == 'https' and '443' or '80' uri = '%s://%s:%s' % (scheme, host, port) return uri def __call__(self, environ, start_response): method = environ['REQUEST_METHOD'] if method not in self.allowed_methods: start_response('403 Forbidden', ()) return [''] if self.strip_script_name: path_info = '' else: path_info = environ['SCRIPT_NAME'] path_info += environ['PATH_INFO'] query_string = environ['QUERY_STRING'] if query_string: path_info += '?' + query_string host_uri = self.extract_uri(environ) uri = host_uri + path_info new_headers = {} for k, v in environ.items(): if k.startswith('HTTP_'): k = k[5:].replace('_', '-').title() new_headers[k] = v ctype = environ.get("CONTENT_TYPE") if ctype and ctype is not None: new_headers['Content-Type'] = ctype clen = environ.get('CONTENT_LENGTH') te = environ.get('transfer-encoding', '').lower() if not clen and te != 'chunked': new_headers['transfer-encoding'] = 'chunked' elif clen: new_headers['Content-Length'] = clen if new_headers.get('Content-Length', '0') == '-1': raise ValueError(WEBOB_ERROR) response = self.client.request(uri, method, body=environ['wsgi.input'], headers=new_headers) if 'location' in response: if self.strip_script_name: prefix_path = environ['SCRIPT_NAME'] new_location = rewrite_location(host_uri, response.location, prefix_path=prefix_path) headers = [] for k, v in response.headerslist: if k.lower() == 'location': v = new_location headers.append((k, v)) else: headers = response.headerslist start_response(response.status, headers) if method == "HEAD": return StringIO() return response.tee()
class Proxy(object): """A proxy wich redirect the request to SERVER_NAME:SERVER_PORT and send HTTP_HOST header""" def __init__(self, manager=None, allowed_methods=ALLOWED_METHODS, strip_script_name=True, **kwargs): self.allowed_methods = allowed_methods self.strip_script_name = strip_script_name self.client = Client(**kwargs) def extract_uri(self, environ): port = None scheme = environ["wsgi.url_scheme"] if "SERVER_NAME" in environ: host = environ["SERVER_NAME"] else: host = environ["HTTP_HOST"] if ":" in host: host, port = host.split(":") if not port: if "SERVER_PORT" in environ: port = environ["SERVER_PORT"] else: port = scheme == "https" and "443" or "80" uri = "%s://%s:%s" % (scheme, host, port) return uri def __call__(self, environ, start_response): method = environ["REQUEST_METHOD"] if method not in self.allowed_methods: start_response("403 Forbidden", ()) return [""] if self.strip_script_name: path_info = "" else: path_info = environ["SCRIPT_NAME"] path_info += environ["PATH_INFO"] query_string = environ["QUERY_STRING"] if query_string: path_info += "?" + query_string host_uri = self.extract_uri(environ) uri = host_uri + path_info new_headers = {} for k, v in environ.items(): if k.startswith("HTTP_"): k = k[5:].replace("_", "-").title() new_headers[k] = v for k, v in (("CONTENT_TYPE", None), ("CONTENT_LENGTH", "0")): v = environ.get(k, None) if v is not None: new_headers[k.replace("_", "-").title()] = v if new_headers.get("Content-Length", "0") == "-1": raise ValueError(WEBOB_ERROR) response = self.client.request(uri, method, body=environ["wsgi.input"], headers=new_headers) if "location" in response: if self.strip_script_name: prefix_path = environ["SCRIPT_NAME"] new_location = rewrite_location(host_uri, response.location, prefix_path=prefix_path) headers = [] for k, v in response.headerslist: if k.lower() == "location": v = new_location headers.append((k, v)) else: headers = response.headerslist start_response(response.status, headers) if method == "HEAD": return StringIO() return response.tee()
class Resource(object): """A class that can be instantiated for access to a RESTful resource, including authentication. """ charset = 'utf-8' encode_keys = True safe = "/:" basic_auth_url = True response_class = Response def __init__(self, uri, **client_opts): """Constructor for a `Resource` object. Resource represent an HTTP resource. - uri: str, full uri to the server. - client_opts: `restkit.client.Client` Options """ client_opts = client_opts or {} self.initial = dict(uri=uri, client_opts=client_opts.copy()) # set default response_class if self.response_class is not None and \ not 'response_class' in client_opts: client_opts['response_class'] = self.response_class self.filters = client_opts.get('filters') or [] self.uri = uri if self.basic_auth_url: # detect credentials from url u = urllib.parse.urlparse(uri) if u.username: password = u.password or "" # add filters filters = copy(self.filters) filters.append(BasicAuth(u.username, password)) client_opts['filters'] = filters # update uri self.uri = urllib.parse.urlunparse( (u.scheme, u.netloc.split("@")[-1], u.path, u.params, u.query, u.fragment)) self.client_opts = client_opts self.client = Client(**self.client_opts) def __repr__(self): return '<%s %s>' % (self.__class__.__name__, self.uri) def clone(self): """if you want to add a path to resource uri, you can do: .. code-block:: python resr2 = res.clone() """ obj = self.__class__(self.initial['uri'], **self.initial['client_opts']) return obj def __call__(self, path): """if you want to add a path to resource uri, you can do: .. code-block:: python Resource("/path").get() """ uri = self.initial['uri'] new_uri = util.make_uri(uri, path, charset=self.charset, safe=self.safe, encode_keys=self.encode_keys) obj = type(self)(new_uri, **self.initial['client_opts']) return obj def get(self, path=None, headers=None, params_dict=None, **params): """ HTTP GET - path: string additionnal path to the uri - headers: dict, optionnal headers that will be added to HTTP request. - params: Optionnal parameterss added to the request. """ return self.request("GET", path=path, headers=headers, params_dict=params_dict, **params) def head(self, path=None, headers=None, params_dict=None, **params): """ HTTP HEAD see GET for params description. """ return self.request("HEAD", path=path, headers=headers, params_dict=params_dict, **params) def delete(self, path=None, headers=None, params_dict=None, **params): """ HTTP DELETE see GET for params description. """ return self.request("DELETE", path=path, headers=headers, params_dict=params_dict, **params) def post(self, path=None, payload=None, headers=None, params_dict=None, **params): """ HTTP POST - payload: string passed to the body of the request - path: string additionnal path to the uri - headers: dict, optionnal headers that will be added to HTTP request. - params: Optionnal parameterss added to the request """ return self.request("POST", path=path, payload=payload, headers=headers, params_dict=params_dict, **params) def put(self, path=None, payload=None, headers=None, params_dict=None, **params): """ HTTP PUT see POST for params description. """ return self.request("PUT", path=path, payload=payload, headers=headers, params_dict=params_dict, **params) def make_params(self, params): return params or {} def make_headers(self, headers): return headers or [] def unauthorized(self, response): return True def request(self, method, path=None, payload=None, headers=None, params_dict=None, **params): """ HTTP request This method may be the only one you want to override when subclassing `restkit.rest.Resource`. - payload: string or File object passed to the body of the request - path: string additionnal path to the uri - headers: dict, optionnal headers that will be added to HTTP request. :params_dict: Options parameters added to the request as a dict - params: Optionnal parameterss added to the request """ params = params or {} params.update(params_dict or {}) while True: uri = util.make_uri(self.uri, path, charset=self.charset, safe=self.safe, encode_keys=self.encode_keys, **self.make_params(params)) # make request resp = self.client.request(uri, method=method, body=payload, headers=self.make_headers(headers)) if resp is None: # race condition raise ValueError("Unkown error: response object is None") if resp.status_int >= 400: if resp.status_int == 404: raise ResourceNotFound(resp.body_string(), response=resp) elif resp.status_int in (401, 403): if self.unauthorized(resp): raise Unauthorized(resp.body_string(), http_code=resp.status_int, response=resp) elif resp.status_int == 410: raise ResourceGone(resp.body_string(), response=resp) else: raise RequestFailed(resp.body_string(), http_code=resp.status_int, response=resp) else: break return resp def update_uri(self, path): """ to set a new uri absolute path """ self.uri = util.make_uri(self.uri, path, charset=self.charset, safe=self.safe, encode_keys=self.encode_keys) self.initial['uri'] = util.make_uri(self.initial['uri'], path, charset=self.charset, safe=self.safe, encode_keys=self.encode_keys)
class Proxy(object): """A proxy wich redirect the request to SERVER_NAME:SERVER_PORT and send HTTP_HOST header""" def __init__(self, manager=None, allowed_methods=ALLOWED_METHODS, strip_script_name=True, **kwargs): self.allowed_methods = allowed_methods self.strip_script_name = strip_script_name self.client = Client(**kwargs) def extract_uri(self, environ): port = None scheme = environ['wsgi.url_scheme'] if 'SERVER_NAME' in environ: host = environ['SERVER_NAME'] else: host = environ['HTTP_HOST'] if ':' in host: host, port = host.split(':') if not port: if 'SERVER_PORT' in environ: port = environ['SERVER_PORT'] else: port = scheme == 'https' and '443' or '80' uri = '%s://%s:%s' % (scheme, host, port) return uri def __call__(self, environ, start_response): method = environ['REQUEST_METHOD'] if method not in self.allowed_methods: start_response('403 Forbidden', ()) return [''] if self.strip_script_name: path_info = '' else: path_info = environ['SCRIPT_NAME'] path_info += environ['PATH_INFO'] query_string = environ['QUERY_STRING'] if query_string: path_info += '?' + query_string host_uri = self.extract_uri(environ) uri = host_uri + path_info new_headers = {} for k, v in list(environ.items()): if k.startswith('HTTP_'): k = k[5:].replace('_', '-').title() new_headers[k] = v ctype = environ.get("CONTENT_TYPE") if ctype and ctype is not None: new_headers['Content-Type'] = ctype clen = environ.get('CONTENT_LENGTH') te = environ.get('transfer-encoding', '').lower() if not clen and te != 'chunked': new_headers['transfer-encoding'] = 'chunked' elif clen: new_headers['Content-Length'] = clen if new_headers.get('Content-Length', '0') == '-1': raise ValueError(WEBOB_ERROR) response = self.client.request(uri, method, body=environ['wsgi.input'], headers=new_headers) if 'location' in response: if self.strip_script_name: prefix_path = environ['SCRIPT_NAME'] new_location = rewrite_location(host_uri, response.location, prefix_path=prefix_path) headers = [] for k, v in response.headerslist: if k.lower() == 'location': v = new_location headers.append((k, v)) else: headers = response.headerslist start_response(response.status, headers) if method == "HEAD": return StringIO() return response.tee()
class Resource(object): """A class that can be instantiated for access to a RESTful resource, including authentication. """ charset = 'utf-8' encode_keys = True safe = "/:" basic_auth_url = True response_class = Response def __init__(self, uri, **client_opts): """Constructor for a `Resource` object. Resource represent an HTTP resource. :param uri: str, full uri to the server. :param client_opts: `restkit.client.Client` Options """ client_opts = client_opts or {} self.initial = dict( uri = uri, client_opts = client_opts.copy() ) # set default response_class if self.response_class is not None and \ not 'response_class' in client_opts: client_opts['response_class'] = self.response_class self.filters = client_opts.get('filters') or [] self.uri = uri if self.basic_auth_url: # detect credentials from url u = urlparse.urlparse(uri) if u.username: password = u.password or "" # add filters filters = copy(self.filters) filters.append(BasicAuth(u.username, password)) client_opts['filters'] = filters # update uri self.uri = urlparse.urlunparse((u.scheme, u.netloc.split("@")[-1], u.path, u.params, u.query, u.fragment)) self.client_opts = client_opts self.client = Client(**self.client_opts) def __repr__(self): return '<%s %s>' % (self.__class__.__name__, self.uri) def clone(self): """if you want to add a path to resource uri, you can do: .. code-block:: python resr2 = res.clone() """ obj = self.__class__(self.initial['uri'], **self.initial['client_opts']) return obj def __call__(self, path): """if you want to add a path to resource uri, you can do: .. code-block:: python Resource("/path").get() """ uri = self.initial['uri'] new_uri = util.make_uri(uri, path, charset=self.charset, safe=self.safe, encode_keys=self.encode_keys) obj = type(self)(new_uri, **self.initial['client_opts']) return obj def get(self, path=None, headers=None, params_dict=None, **params): """ HTTP GET :param path: string additionnal path to the uri :param headers: dict, optionnal headers that will be added to HTTP request. :param params: Optionnal parameterss added to the request. """ return self.request("GET", path=path, headers=headers, params_dict=params_dict, **params) def head(self, path=None, headers=None, params_dict=None, **params): """ HTTP HEAD see GET for params description. """ return self.request("HEAD", path=path, headers=headers, params_dict=params_dict, **params) def delete(self, path=None, headers=None, params_dict=None, **params): """ HTTP DELETE see GET for params description. """ return self.request("DELETE", path=path, headers=headers, params_dict=params_dict, **params) def post(self, path=None, payload=None, headers=None, params_dict=None, **params): """ HTTP POST :param payload: string passed to the body of the request :param path: string additionnal path to the uri :param headers: dict, optionnal headers that will be added to HTTP request. :param params: Optionnal parameterss added to the request """ return self.request("POST", path=path, payload=payload, headers=headers, params_dict=params_dict, **params) def put(self, path=None, payload=None, headers=None, params_dict=None, **params): """ HTTP PUT see POST for params description. """ return self.request("PUT", path=path, payload=payload, headers=headers, params_dict=params_dict, **params) def make_params(self, params): return params or {} def make_headers(self, headers): return headers or [] def unauthorized(self, response): return True def request(self, method, path=None, payload=None, headers=None, params_dict=None, **params): """ HTTP request This method may be the only one you want to override when subclassing `restkit.rest.Resource`. :param payload: string or File object passed to the body of the request :param path: string additionnal path to the uri :param headers: dict, optionnal headers that will be added to HTTP request. :params_dict: Options parameters added to the request as a dict :param params: Optionnal parameterss added to the request """ params = params or {} params.update(params_dict or {}) while True: uri = util.make_uri(self.uri, path, charset=self.charset, safe=self.safe, encode_keys=self.encode_keys, **self.make_params(params)) # make request resp = self.client.request(uri, method=method, body=payload, headers=self.make_headers(headers)) if resp is None: # race condition raise ValueError("Unkown error: response object is None") if resp.status_int >= 400: if resp.status_int == 404: raise ResourceNotFound(resp.body_string(), response=resp) elif resp.status_int in (401, 403): if self.unauthorized(resp): raise Unauthorized(resp.body_string(), http_code=resp.status_int, response=resp) elif resp.status_int == 410: raise ResourceGone(resp.body_string(), response=resp) else: raise RequestFailed(resp.body_string(), http_code=resp.status_int, response=resp) else: break return resp def update_uri(self, path): """ to set a new uri absolute path """ self.uri = util.make_uri(self.uri, path, charset=self.charset, safe=self.safe, encode_keys=self.encode_keys) self.initial['uri'] = util.make_uri(self.initial['uri'], path, charset=self.charset, safe=self.safe, encode_keys=self.encode_keys)