Beispiel #1
0
 def _respond(self, http_code, extra_headers, body):
     self.send_response(http_code)
     for k, v in extra_headers:
         self.send_header(k, v)
     self.end_headers()
     self.wfile.write(to_bytestring(body))
     self.wfile.close()
Beispiel #2
0
    def request(self, url, method='GET', body=None, headers=None):
        body = body or ""
        headers = headers or {}
        headers.setdefault('User-Agent', "%s %s" % (
            USER_AGENT,
            pycurl.version,
        ))

        # by default turn off default pragma
        headers.setdefault('Cache-control', 'max-age=0')
        headers.setdefault('Pragma', 'no-cache')

        if method == 'PUT':
            headers.setdefault('Expect', '100-continue')

        # encode url
        origin_url = to_bytestring(url)
        url = iri2uri(origin_url)

        c = pycurl.Curl()
        try:
            # set curl options
            if self.timeout is not None:
                c.setopt(pycurl.TIMEOUT, self.timeout)
            else:  # no timeout by default
                c.setopt(pycurl.TIMEOUT, 0)

            data = StringIO.StringIO()
            header = StringIO.StringIO()
            c.setopt(pycurl.WRITEFUNCTION, data.write)
            c.setopt(pycurl.HEADERFUNCTION, header.write)
            c.setopt(pycurl.URL, url)
            c.setopt(pycurl.FOLLOWLOCATION, 1)
            c.setopt(pycurl.MAXREDIRS, 5)
            c.setopt(pycurl.NOSIGNAL, 1)
            if restclient.debuglevel > 0:
                c.setopt(pycurl.VERBOSE, 1)

            # automatic decompression
            c.setopt(pycurl.ENCODING, 'gzip,deflate')

            if self.cabundle:
                c.setopt(pycurl.CAINFO, celf.cabundle)

            #set proxy
            if self.proxy_infos and self.proxy_infos.get('proxy_host', ''):
                c.setopt(pycurl.PROXYAUTH, pycurl.HTTPAUTH_ANY)
                c.setopt(pycurl.PROXY, self.proxy_infos.get('proxy_host'))

                proxy_port = self.proxy_infos.get('proxy_port', '')
                if proxy_port:
                    c.setopt(pycurl.PROXYPORT, str(proxy_port))

                user = self.proxy_infos.get('proxy_user', '')
                if user:
                    userpass = "******" % (
                        user, self.proxy_infos.get('proxy_password', ''))
                    c.setopt(pycurl.PROXYUSERPWD, userpass)

            # authentification
            auth = self._get_credentials()
            user = auth.get('user', None)
            password = auth.get('password', None)
            if user is not None:
                c.setopt(pycurl.HTTPAUTH, pycurl.HTTPAUTH_ANY)
                userpass = user + ':'
                if password is not None:  # '' is a valid password
                    userpass += password
                c.setopt(pycurl.USERPWD, userpass)

            # set method
            if method == "GET":
                c.setopt(pycurl.HTTPGET, 1)
            elif method == "HEAD":
                c.setopt(pycurl.HTTPGET, 1)
                c.setopt(pycurl.NOBODY, 1)
            elif method == "POST":
                c.setopt(pycurl.POST, 1)
            elif method == "PUT":
                c.setopt(pycurl.UPLOAD, 1)
            else:
                c.setopt(pycurl.CUSTOMREQUEST, method)

            if method in ('POST', 'PUT'):
                if hasattr(body, 'read'):
                    content_length = int(headers.pop('Content-Length', 0))
                    content = body
                else:
                    body = to_bytestring(body)
                    content = StringIO.StringIO(body)
                    if 'Content-Length' in headers:
                        del headers['Content-Length']
                    content_length = len(body)

                if method == 'POST':
                    c.setopt(pycurl.POSTFIELDSIZE, content_length)
                else:
                    c.setopt(pycurl.INFILESIZE, content_length)
                c.setopt(pycurl.READFUNCTION, content.read)

            if headers:
                _normalize_headers(headers)
                c.setopt(
                    pycurl.HTTPHEADER,
                    ["%s: %s" % pair for pair in sorted(headers.iteritems())])

            try:
                c.perform()
            except pycurl.error, e:
                if e[0] != CURLE_SEND_ERROR:
                    if restclient.debuglevel > 0:
                        print >> sys.stderr, str(e)
                    raise TransportError(e)

            response_headers = self._parseHeaders(header)
            code = c.getinfo(pycurl.RESPONSE_CODE)
            return self._make_response(final_url=url,
                                       origin_url=origin_url,
                                       status=code,
                                       headers=response_headers,
                                       body=data.getvalue())
Beispiel #3
0
def form_encode(obj, charser="utf8"):
    tmp = []
    for key, value in list(obj.items()):
        tmp.append("%s=%s" % (url_quote(key), 
                url_quote(value)))
    return to_bytestring("&".join(tmp))
Beispiel #4
0
    def request(self, method, uri, path=None, body=None, headers=None, **params):
        """ Perform HTTP call support GET, HEAD, POST, PUT and DELETE.
        
        Usage example, get friendpaste page :

        .. code-block:: python

            from restclient import RestClient
            client = RestClient()
            page = resource.request('GET', 'http://friendpaste.com')

        Or get a paste in JSON :

        .. code-block:: python

            from restclient import RestClient
            client = RestClient()
            client.request('GET', 'http://friendpaste.com/5rOqE9XTz7lccLgZoQS4IP'),
                headers={'Accept': 'application/json'})

        :param method: str, the HTTP action to be performed: 
            'GET', 'HEAD', 'POST', 'PUT', or 'DELETE'
        :param path: str or list, path to add to the uri
        :param data: tring or File object.
        :param headers: dict, optionnal headers that will
            be added to HTTP request.
        :param params: Optionnal parameterss added to the request.
        
        :return: str.
        """

        # init headers
        _headers = self._headers or {}
        _headers.update(headers or {})
        
        is_unicode = True
        
        if body and body is not None and 'Content-Length' not in headers:
            if isinstance(body, file):
                try:
                    body.flush()
                except IOError:
                    pass
                size = int(os.fstat(body.fileno())[6])
            elif isinstance(body, str):
                size = len(body)
                body = to_bytestring(body)
            elif isinstance(body, dict):
                _headers.setdefault('Content-Type', "application/x-www-form-urlencoded; charset=utf-8")
                body = form_encode(body)
                print(body)
                size = len(body)
            else:
                raise RequestError('Unable to calculate '
                    'the length of the data parameter. Specify a value for '
                    'Content-Length')
            _headers['Content-Length'] = size
            
            if 'Content-Type' not in headers:
                type = None
                if hasattr(body, 'name'):
                    type = mimetypes.guess_type(body.name)[0]
                _headers['Content-Type'] = type and type or 'application/octet-stream'
                
        try:
            resp, data = self.transport.request(self.make_uri(uri, path, **params), 
                method=method, body=body, headers=_headers)
        except TransportError as e:
            raise RequestError(str(e))

        self.status  = status_code = resp.status
        self.response = resp
        
        
        if status_code >= 400:
            if status_code == 404:
                raise ResourceNotFound(data, http_code=404, response=resp)
            elif status_code == 401 or status_code == 403:
                raise Unauthorized(data, http_code=status_code,
                        response=resp)
            else:
                raise RequestFailed(data, http_code=status_code,
                    response=resp)

        # determine character encoding
        true_encoding, http_encoding, xml_encoding, sniffed_xml_encoding, \
        acceptable_content_type = _getCharacterEncoding(resp, data)
        

        tried_encodings = []
        # try: HTTP encoding, declared XML encoding, encoding sniffed from BOM
        for proposed_encoding in (true_encoding, xml_encoding, sniffed_xml_encoding):
            if not proposed_encoding: continue
            if proposed_encoding in tried_encodings: continue
            tried_encodings.append(proposed_encoding)
            try:
               return data.decode(proposed_encoding)
               break
            except:
                pass
                
        # if still no luck and we haven't tried utf-8 yet, try that
        if 'utf-8' not in tried_encodings:
            try:
                proposed_encoding = 'utf-8'
                tried_encodings.append(proposed_encoding)
                return data.decode(proposed_encoding)
              
            except:
                pass
                
        # if still no luck and we haven't tried windows-1252 yet, try that
        if 'windows-1252' not in tried_encodings:
            try:
                proposed_encoding = 'windows-1252'
                tried_encodings.append(proposed_encoding)
                return data.decode(proposed_encoding)
            except:
                pass
                
        # if no luck and we have auto-detection library, try that
        if chardet:
            try:
                proposed_encoding = chardet.detect(data)['encoding']
                if proposed_encoding and (proposed_encoding not in tried_encodings):
                    tried_encodings.append(proposed_encoding)
                    return data.decode(proposed_encoding)
            except:
                pass
              
        # give up, return data as is.   
        return data 
Beispiel #5
0
    def request(self, url, method='GET', body=None, headers=None):
        body = body or ""        
        headers = headers or {}
        headers.setdefault('User-Agent',
                           "%s %s" % (USER_AGENT, pycurl.version,))

        # by default turn off default pragma
        headers.setdefault('Cache-control', 'max-age=0')
        headers.setdefault('Pragma', 'no-cache')

        if method == 'PUT':
            headers.setdefault('Expect', '100-continue')

        # encode url
        origin_url = to_bytestring(url)
        url = iri2uri(origin_url)

        c = pycurl.Curl()
        try:
            # set curl options
            if self.timeout is not None:
                c.setopt(pycurl.TIMEOUT, self.timeout)
            else: # no timeout by default
                c.setopt(pycurl.TIMEOUT, 0)

            data = io.BytesIO()
            header = io.BytesIO()
            c.setopt(pycurl.WRITEFUNCTION, data.write)
            c.setopt(pycurl.HEADERFUNCTION, header.write)
            c.setopt(pycurl.URL, url)
            c.setopt(pycurl.FOLLOWLOCATION, 1)
            c.setopt(pycurl.MAXREDIRS, 5)
            c.setopt(pycurl.NOSIGNAL, 1)
            if restclient.debuglevel > 0:
                 c.setopt(pycurl.VERBOSE, 1)
                 
            # automatic decompression
            c.setopt(pycurl.ENCODING, 'gzip,deflate')

            if self.cabundle:
                c.setopt(pycurl.CAINFO, celf.cabundle)

            #set proxy
            if self.proxy_infos and self.proxy_infos.get('proxy_host', ''):
                c.setopt(pycurl.PROXYAUTH, pycurl.HTTPAUTH_ANY)
                c.setopt(pycurl.PROXY, self.proxy_infos.get('proxy_host'))

                proxy_port = self.proxy_infos.get('proxy_port', '')
                if proxy_port:
                    c.setopt(pycurl.PROXYPORT, str(proxy_port))

                user = self.proxy_infos.get('proxy_user', '')
                if user:
                    userpass = "******" % (user, self.proxy_infos.get('proxy_password', ''))
                    c.setopt(pycurl.PROXYUSERPWD, userpass)

            # authentification
            auth = self._get_credentials()
            user = auth.get('user', None)
            password = auth.get('password', None)
            if user is not None:
                c.setopt(pycurl.HTTPAUTH, pycurl.HTTPAUTH_ANY)
                userpass = user + ':'
                if password is not None: # '' is a valid password
                    userpass += password
                c.setopt(pycurl.USERPWD, userpass)

            # set method
            if method == "GET":
                c.setopt(pycurl.HTTPGET, 1)
            elif method == "HEAD":
                c.setopt(pycurl.HTTPGET, 1)
                c.setopt(pycurl.NOBODY, 1)
            elif method == "POST":
                c.setopt(pycurl.POST, 1)
            elif method == "PUT":
                c.setopt(pycurl.UPLOAD, 1)
            else:
                c.setopt(pycurl.CUSTOMREQUEST, method)

            if method in ('POST','PUT'):
                if hasattr(body, 'read'):
                    content_length = int(headers.pop('Content-Length',
                        0))
                    content = body
                else:
                    body = to_bytestring(body)
                    content = io.BytesIO(body)
                    if 'Content-Length' in headers:
                        del headers['Content-Length']
                    content_length = len(body)

                if method == 'POST':
                    c.setopt(pycurl.POSTFIELDSIZE, content_length)
                else:
                    c.setopt(pycurl.INFILESIZE, content_length)
                c.setopt(pycurl.READFUNCTION, content.read)

            if headers:
                _normalize_headers(headers)
                c.setopt(pycurl.HTTPHEADER,
                        ["%s: %s" % pair for pair in sorted(headers.items())])

            try:
                c.perform()
            except pycurl.error as e:
                if e.args[0] != CURLE_SEND_ERROR:
                    if restclient.debuglevel > 0:
                        print(str(e), file=sys.stderr)
                    raise TransportError(e)

            response_headers = self._parseHeaders(header)
            code = c.getinfo(pycurl.RESPONSE_CODE)
            return self._make_response(final_url=url, origin_url=origin_url,
                    status=code, headers=response_headers, body=data.getvalue())
        finally:
            c.close()
Beispiel #6
0
    def request(self,
                method,
                uri,
                path=None,
                body=None,
                headers=None,
                **params):
        """ Perform HTTP call support GET, HEAD, POST, PUT and DELETE.
        
        Usage example, get friendpaste page :

        .. code-block:: python

            from restclient import RestClient
            client = RestClient()
            page = resource.request('GET', 'http://friendpaste.com')

        Or get a paste in JSON :

        .. code-block:: python

            from restclient import RestClient
            client = RestClient()
            client.request('GET', 'http://friendpaste.com/5rOqE9XTz7lccLgZoQS4IP'),
                headers={'Accept': 'application/json'})

        :param method: str, the HTTP action to be performed: 
            'GET', 'HEAD', 'POST', 'PUT', or 'DELETE'
        :param path: str or list, path to add to the uri
        :param data: tring or File object.
        :param headers: dict, optionnal headers that will
            be added to HTTP request.
        :param params: Optionnal parameterss added to the request.
        
        :return: str.
        """

        # init headers
        _headers = self._headers or {}
        _headers.update(headers or {})

        is_unicode = True

        if body and body is not None and 'Content-Length' not in headers:
            if isinstance(body, file):
                try:
                    body.flush()
                except IOError:
                    pass
                size = int(os.fstat(body.fileno())[6])
            elif isinstance(body, types.StringTypes):
                size = len(body)
                body = to_bytestring(body)
            elif isinstance(body, dict):
                _headers.setdefault(
                    'Content-Type',
                    "application/x-www-form-urlencoded; charset=utf-8")
                body = form_encode(body)
                print body
                size = len(body)
            else:
                raise RequestError(
                    'Unable to calculate '
                    'the length of the data parameter. Specify a value for '
                    'Content-Length')
            _headers['Content-Length'] = size

            if 'Content-Type' not in headers:
                type = None
                if hasattr(body, 'name'):
                    type = mimetypes.guess_type(body.name)[0]
                _headers[
                    'Content-Type'] = type and type or 'application/octet-stream'

        try:
            resp, data = self.transport.request(self.make_uri(
                uri, path, **params),
                                                method=method,
                                                body=body,
                                                headers=_headers)
        except TransportError, e:
            raise RequestError(str(e))
Beispiel #7
0
    def request(self, method, uri, path=None, body=None, headers=None, **params):
        """ Perform HTTP call support GET, HEAD, POST, PUT and DELETE.
        
        Usage example, get friendpaste page :

        .. code-block:: python

            from restclient import RestClient
            client = RestClient()
            page = resource.request('GET', 'http://friendpaste.com')

        Or get a paste in JSON :

        .. code-block:: python

            from restclient import RestClient
            client = RestClient()
            client.request('GET', 'http://friendpaste.com/5rOqE9XTz7lccLgZoQS4IP'),
                headers={'Accept': 'application/json'})

        :param method: str, the HTTP action to be performed: 
            'GET', 'HEAD', 'POST', 'PUT', or 'DELETE'
        :param path: str or list, path to add to the uri
        :param data: tring or File object.
        :param headers: dict, optionnal headers that will
            be added to HTTP request.
        :param params: Optionnal parameterss added to the request.
        
        :return: str.
        """

        # init headers
        _headers = self._headers or {}
        _headers.update(headers or {})
        
        is_unicode = True
        
        if body and body is not None and 'Content-Length' not in headers:
            if isinstance(body, file):
                try:
                    body.flush()
                except IOError:
                    pass
                size = int(os.fstat(body.fileno())[6])
            elif isinstance(body, types.StringTypes):
                size = len(body)
                body = to_bytestring(body)
            elif isinstance(body, dict):
                _headers.setdefault('Content-Type', "application/x-www-form-urlencoded; charset=utf-8")
                body = form_encode(body)
                print body
                size = len(body)
            else:
                raise RequestError('Unable to calculate '
                    'the length of the data parameter. Specify a value for '
                    'Content-Length')
            _headers['Content-Length'] = size
            
            if 'Content-Type' not in headers:
                type = None
                if hasattr(body, 'name'):
                    type = mimetypes.guess_type(body.name)[0]
                _headers['Content-Type'] = type and type or 'application/octet-stream'
                
        try:
            resp, data = self.transport.request(self.make_uri(uri, path, **params), 
                method=method, body=body, headers=_headers)
        except TransportError, e:
            raise RequestError(str(e))