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()
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())
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))
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
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()
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))
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))