예제 #1
0
 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)
예제 #2
0
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)
예제 #3
0
파일: __init__.py 프로젝트: bjornua/dna
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)
예제 #4
0
    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 = 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)
예제 #5
0
    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)
예제 #6
0
파일: wsgi_proxy.py 프로젝트: Leits/restkit
 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)
예제 #7
0
파일: wsgi_proxy.py 프로젝트: Leits/restkit
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()
예제 #8
0
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()
예제 #9
0
파일: resource.py 프로젝트: madron/restkit
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)
예제 #10
0
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()
예제 #11
0
 def run():
     cli = Client(timeout=300)
     func(self.url, cli)
예제 #12
0
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)