def encode_hdr(self, boundary): """Returns the header of the encoding of this parameter""" boundary = encode_and_quote(boundary) headers = ["--%s" % boundary] if self.filename: disposition = 'form-data; name="%s"; filename="%s"' % (self.name, to_string(self.filename)) else: disposition = 'form-data; name="%s"' % self.name headers.append("Content-Disposition: %s" % disposition) if self.filetype: filetype = to_string(self.filetype) else: filetype = "text/plain; charset=utf-8" headers.append("Content-Type: %s" % filetype) headers.append("") headers.append("") return "\r\n".join(headers)
def encode_hdr(self, boundary): """Returns the header of the encoding of this parameter""" boundary = encode_and_quote(boundary) headers = ["--%s" % boundary] if self.filename: disposition = 'form-data; name="%s"; filename="%s"' % ( self.name, to_string(self.filename)) else: disposition = 'form-data; name="%s"' % self.name headers.append("Content-Disposition: %s" % disposition) if self.filetype: filetype = to_string(self.filetype) else: filetype = "text/plain; charset=utf-8" headers.append("Content-Type: %s" % filetype) headers.append("") headers.append("") return "\r\n".join(headers)
def call_api(method, uri, params, **options): prefix = options.pop( "upload_prefix", cloudinary.config().upload_prefix) or "https://api.cloudinary.com" cloud_name = options.pop("cloud_name", cloudinary.config().cloud_name) if not cloud_name: raise Exception("Must supply cloud_name") api_key = options.pop("api_key", cloudinary.config().api_key) if not api_key: raise Exception("Must supply api_key") api_secret = options.pop("api_secret", cloudinary.config().api_secret) if not cloud_name: raise Exception("Must supply api_secret") data = to_bytes(urlencode(params)) api_url = "/".join([prefix, "v1_1", cloud_name] + uri) request = urllib2.Request(api_url, data) # Add authentication byte_value = to_bytes('%s:%s' % (api_key, api_secret)) encoded_value = base64.encodebytes( byte_value) if PY3 else base64.encodestring(byte_value) base64string = to_string(encoded_value).replace('\n', '') request.add_header("Authorization", "Basic %s" % base64string) request.add_header("User-Agent", cloudinary.USER_AGENT) request.get_method = lambda: method.upper() kw = {} if 'timeout' in options: kw['timeout'] = options['timeout'] try: response = urllib2.urlopen(request, **kw) body = response.read() except HTTPError: e = sys.exc_info()[1] exception_class = EXCEPTION_CODES.get(e.code) if exception_class: response = e body = response.read() else: raise GeneralError( "Server returned unexpected status code - %d - %s" % (e.code, e.read())) except socket.error: e = sys.exc_info()[1] raise GeneralError("Socket Error: %s" % (str(e))) try: body = to_string(body) result = json.loads(body) except Exception: # Error is parsing json e = sys.exc_info()[1] raise GeneralError( "Error parsing server response (%d) - %s. Got - %s" % (response.code, body, e)) if "error" in result: exception_class = exception_class or Exception raise exception_class(result["error"]["message"]) return Response(result, response)
def call_api(method, uri, params, **options): prefix = options.pop("upload_prefix", cloudinary.config().upload_prefix) or "https://api.cloudinary.com" cloud_name = options.pop("cloud_name", cloudinary.config().cloud_name) if not cloud_name: raise Exception("Must supply cloud_name") api_key = options.pop("api_key", cloudinary.config().api_key) if not api_key: raise Exception("Must supply api_key") api_secret = options.pop("api_secret", cloudinary.config().api_secret) if not cloud_name: raise Exception("Must supply api_secret") data = to_bytes(urlencode(params)) api_url = "/".join([prefix, "v1_1", cloud_name] + uri) request = urllib2.Request(api_url, data) # Add authentication byte_value = to_bytes('%s:%s' % (api_key, api_secret)) encoded_value = base64.encodebytes(byte_value) if PY3 else base64.encodestring(byte_value) base64string = to_string(encoded_value).replace('\n', '') request.add_header("Authorization", "Basic %s" % base64string) request.add_header("User-Agent", cloudinary.USER_AGENT) request.get_method = lambda: method.upper() kw = {} if 'timeout' in options: kw['timeout'] = options['timeout'] try: response = urllib2.urlopen(request, **kw) body = response.read() except socket.error: e = sys.exc_info()[1] raise GeneralError("Socket Error: %s" % (str(e))) except urllib2.HTTPError: e = sys.exc_info()[1] exception_class = EXCEPTION_CODES.get(e.code) if exception_class: response = e body = response.read() else: raise GeneralError("Server returned unexpected status code - %d - %s" % (e.code, e.read())) try: body = to_string(body) result = json.loads(body) except Exception: # Error is parsing json e = sys.exc_info()[1] raise GeneralError("Error parsing server response (%d) - %s. Got - %s" % (response.code, body, e)) if "error" in result: exception_class = exception_class or Exception raise exception_class(result["error"]["message"]) return Response(result, response)
def cloudinary_url(source, **options): original_source = source type = options.pop("type", "upload") if type == 'fetch': options["fetch_format"] = options.get("fetch_format", options.pop("format", None)) transformation, options = generate_transformation_string(**options) resource_type = options.pop("resource_type", "image") version = options.pop("version", None) format = options.pop("format", None) cdn_subdomain = options.pop("cdn_subdomain", cloudinary.config().cdn_subdomain) secure_cdn_subdomain = options.pop("secure_cdn_subdomain", cloudinary.config().secure_cdn_subdomain) cname = options.pop("cname", cloudinary.config().cname) shorten = options.pop("shorten", cloudinary.config().shorten) cloud_name = options.pop("cloud_name", cloudinary.config().cloud_name or None) if cloud_name is None: raise ValueError("Must supply cloud_name in tag or in configuration") secure = options.pop("secure", cloudinary.config().secure) private_cdn = options.pop("private_cdn", cloudinary.config().private_cdn) secure_distribution = options.pop("secure_distribution", cloudinary.config().secure_distribution) sign_url = options.pop("sign_url", cloudinary.config().sign_url) api_secret = options.pop("api_secret", cloudinary.config().api_secret) url_suffix = options.pop("url_suffix", None) use_root_path = options.pop("use_root_path", cloudinary.config().use_root_path) auth_token = options.pop("auth_token", None) if auth_token is not False: auth_token = merge(cloudinary.config().auth_token, auth_token) if (not source) or type == "upload" and re.match(r'^https?:', source): return original_source, options resource_type, type = finalize_resource_type(resource_type, type, url_suffix, use_root_path, shorten) source, source_to_sign = finalize_source(source, format, url_suffix) if source_to_sign.find("/") >= 0 \ and not re.match(r'^https?:/', source_to_sign) \ and not re.match(r'^v[0-9]+', source_to_sign) \ and not version: version = "1" if version: version = "v" + str(version) transformation = re.sub(r'([^:])/+', r'\1/', transformation) signature = None if sign_url and not auth_token: to_sign = "/".join(__compact([transformation, source_to_sign])) signature = "s--" + to_string( base64.urlsafe_b64encode(hashlib.sha1(to_bytes(to_sign + api_secret)).digest())[0:8]) + "--" prefix = unsigned_download_url_prefix(source, cloud_name, private_cdn, cdn_subdomain, secure_cdn_subdomain, cname, secure, secure_distribution) source = "/".join(__compact([prefix, resource_type, type, signature, transformation, version, source])) if sign_url and auth_token: path = urlparse(source).path token = cloudinary.auth_token.generate( **merge(auth_token, {"url": path})) source = "%s?%s" % (source, token) return source, options
def smart_escape(source, unsafe=r"([^a-zA-Z0-9_.\-\/:]+)"): def pack(m): return to_bytes('%' + "%".join([ "%02X" % x for x in struct.unpack('B' * len(m.group(1)), m.group(1)) ]).upper()) return to_string(re.sub(to_bytes(unsafe), pack, to_bytes(source)))
def base64url_encode(data): """ Url safe version of urlsafe_b64encode with stripped `=` sign at the end. :param data: input data :return: Base64 URL safe encoded string """ return to_string(base64.urlsafe_b64encode(to_bytes(data)))
def smart_escape(source, unsafe=r"([^a-zA-Z0-9_.\-\/:]+)"): """ Based on ruby's CGI::unescape. In addition does not escape / : :param source: Source string to escape :param unsafe: Unsafe characters :return: Escaped string """ def pack(m): return to_bytes('%' + "%".join( ["%02X" % x for x in struct.unpack('B' * len(m.group(1)), m.group(1))] ).upper()) return to_string(re.sub(to_bytes(unsafe), pack, to_bytes(source)))
def __init__(self, name, value=None, filename=None, filetype=None, filesize=None, fileobj=None, cb=None): self.name = Header(name).encode() self.value = _strify(value) if filename is None: self.filename = None else: if PY3: byte_filename = filename.encode("ascii", "xmlcharrefreplace") self.filename = to_string(byte_filename) encoding = 'unicode_escape' else: if isinstance(filename, unicode): # Encode with XML entities self.filename = filename.encode("ascii", "xmlcharrefreplace") else: self.filename = str(filename) encoding = 'string_escape' self.filename = self.filename.encode(encoding).replace( to_bytes('"'), to_bytes('\\"')) self.filetype = _strify(filetype) self.filesize = filesize self.fileobj = fileobj self.cb = cb if self.value is not None and self.fileobj is not None: raise ValueError("Only one of value or fileobj may be specified") if fileobj is not None and filesize is None: # Try and determine the file size try: self.filesize = os.fstat(fileobj.fileno()).st_size except (OSError, AttributeError, UnsupportedOperation): try: fileobj.seek(0, 2) self.filesize = fileobj.tell() fileobj.seek(0) except Exception: raise ValueError("Could not determine filesize")
def __init__(self, name, value=None, filename=None, filetype=None, filesize=None, fileobj=None, cb=None): self.name = Header(name).encode() self.value = _strify(value) if filename is None: self.filename = None else: if PY3: byte_filename = filename.encode("ascii", "xmlcharrefreplace") self.filename = to_string(byte_filename) encoding = 'unicode_escape' else: if isinstance(filename, unicode): # Encode with XML entities self.filename = filename.encode("ascii", "xmlcharrefreplace") else: self.filename = str(filename) encoding = 'string_escape' self.filename = self.filename.encode(encoding).replace(to_bytes('"'), to_bytes('\\"')) self.filetype = _strify(filetype) self.filesize = filesize self.fileobj = fileobj self.cb = cb if self.value is not None and self.fileobj is not None: raise ValueError("Only one of value or fileobj may be specified") if fileobj is not None and filesize is None: # Try and determine the file size try: self.filesize = os.fstat(fileobj.fileno()).st_size except (OSError, AttributeError, UnsupportedOperation): try: fileobj.seek(0, 2) self.filesize = fileobj.tell() fileobj.seek(0) except: raise ValueError("Could not determine filesize")
def call_api(action, params, **options): try: file_io = None return_error = options.get("return_error") if options.get("unsigned"): params = utils.cleanup_params(params) else: params = utils.sign_request(params, options) param_list = [] for k, v in params.items(): if isinstance(v, list): for vv in v: param_list.append((k + "[]", vv)) elif v: param_list.append((k, v)) api_url = utils.cloudinary_api_url(action, **options) global _initialized if not _initialized: _initialized = True # Register the streaming http handlers with urllib2 register_openers() datagen = to_bytes("") headers = {} if "file" in options: file = options["file"] if not isinstance(file, string_types): datagen, headers = multipart_encode({'file': file}) elif not re.match( r'^https?:|^s3:|^data:[^;]*;base64,([a-zA-Z0-9\/+\n=]+)$', file): file_io = open(file, "rb") datagen, headers = multipart_encode({'file': file_io}) else: param_list.append(("file", file)) request = urllib2.Request(api_url + "?" + urlencode(param_list), datagen, headers) request.add_header("User-Agent", cloudinary.USER_AGENT) code = 200 try: response = urllib2.urlopen(request).read() except urllib2.HTTPError: e = sys.exc_info()[1] if not e.code in [200, 400, 500]: raise Error( "Server returned unexpected status code - %d - %s" % (e.code, e.read())) code = e.code response = e.read() try: result = json.loads(to_string(response)) except Exception: e = sys.exc_info()[1] # Error is parsing json raise Error("Error parsing server response (%d) - %s. Got - %s", code, response, e) if "error" in result: if return_error: result["error"]["http_code"] = response.code else: raise Error(result["error"]["message"]) return result finally: if file_io: file_io.close()
def smart_escape(string): pack = lambda m: to_bytes('%' + "%".join(["%02X" % x for x in struct.unpack('B'*len(m.group(1)), m.group(1))]).upper()) return to_string(re.sub(to_bytes(r"([^a-zA-Z0-9_.\-\/:]+)"), pack, to_bytes(string)))
def cloudinary_url(source, **options): original_source = source type = options.pop("type", "upload") if type == 'fetch': options["fetch_format"] = options.get("fetch_format", options.pop("format", None)) transformation, options = generate_transformation_string(**options) resource_type = options.pop("resource_type", "image") version = options.pop("version", None) format = options.pop("format", None) cdn_subdomain = options.pop("cdn_subdomain", cloudinary.config().cdn_subdomain) cname = options.pop("cname", cloudinary.config().cname) shorten = options.pop("shorten", cloudinary.config().shorten) cloud_name = options.pop("cloud_name", cloudinary.config().cloud_name or None) if cloud_name == None: raise ValueError("Must supply cloud_name in tag or in configuration") secure = options.pop("secure", cloudinary.config().secure) private_cdn = options.pop("private_cdn", cloudinary.config().private_cdn) secure_distribution = options.pop("secure_distribution", cloudinary.config().secure_distribution) sign_url = options.pop("sign_url", cloudinary.config().sign_url) api_secret = options.pop("api_secret", cloudinary.config().api_secret) if (not source) or ((type == "upload" or type=="asset") and re.match(r'^https?:', source)): return (original_source, options) if re.match(r'^https?:', source): source = smart_escape(source) else: source = unquote(source) if not PY3: source = source.decode('utf8') source = smart_escape(source) if format: source = source + "." + format if cloud_name.startswith("/"): prefix = "/res" + cloud_name else: shared_domain = not private_cdn if secure: if not secure_distribution or secure_distribution == cloudinary.OLD_AKAMAI_SHARED_CDN: secure_distribution = cloud_name + "-res.cloudinary.com" if private_cdn else cloudinary.SHARED_CDN shared_domain = shared_domain or secure_distribution == cloudinary.SHARED_CDN prefix = "https://" + secure_distribution else: subdomain = "a" + str((zlib.crc32(to_bytearray(source)) & 0xffffffff)%5 + 1) + "." if cdn_subdomain else "" if cname: host = cname elif private_cdn: host = cloud_name + "-res.cloudinary.com" else: host = "res.cloudinary.com" prefix = "http://" + subdomain + host if shared_domain: prefix += "/" + cloud_name if shorten and resource_type == "image" and type == "upload": resource_type = "iu" type = "" if source.find("/") >= 0 and not re.match(r'^https?:/', source) and not re.match(r'^v[0-9]+', source) and not version: version = "1" rest = "/".join(filter(lambda x: x, [transformation, "v" + str(version) if version else "", source])) if sign_url: signature = to_string(base64.urlsafe_b64encode( hashlib.sha1(to_bytes(rest + api_secret)).digest() )[0:8]) rest = "s--%(signature)s--/%(rest)s" % {"signature": signature, "rest": rest} components = [prefix, resource_type, type, rest] source = re.sub(r'([^:])/+', r'\1/', "/".join(components)) return (source, options)
def call_api(action, params, http_headers={}, return_error=False, unsigned=False, file=None, timeout=None, **options): try: file_io = None if unsigned: params = utils.cleanup_params(params) else: params = utils.sign_request(params, options) param_list = [] for k, v in params.items(): if isinstance(v, list): for vv in v: param_list.append((k+"[]", vv)) elif v: param_list.append((k, v)) api_url = utils.cloudinary_api_url(action, **options) global _initialized if not _initialized: _initialized = True # Register the streaming http handlers with urllib2 register_openers() datagen, headers = multipart_encode({}) if file: if not isinstance(file, string_types): datagen, headers = multipart_encode({'file': file}) elif not re.match(r'ftp:|https?:|s3:|data:[^;]*;base64,([a-zA-Z0-9\/+\n=]+)$', file): file_io = open(file, "rb") datagen, headers = multipart_encode({'file': file_io}) else: param_list.append(("file", file)) if _is_gae(): # Might not be needed in the future but for now this is needed in GAE datagen = "".join(datagen) request = urllib2.Request(api_url + "?" + urlencode(param_list), datagen, headers) request.add_header("User-Agent", cloudinary.get_user_agent()) for k, v in http_headers.items(): request.add_header(k, v) kw = {} if timeout is not None: kw['timeout'] = timeout code = 200 try: response = urllib2.urlopen(request, **kw).read() except HTTPError: e = sys.exc_info()[1] if not e.code in [200, 400, 500]: raise Error("Server returned unexpected status code - %d - %s" % (e.code, e.read())) code = e.code response = e.read() except urllib2.URLError: e = sys.exc_info()[1] raise Error("Error - %s" % str(e)) except socket.error: e = sys.exc_info()[1] raise Error("Socket error: %s" % str(e)) try: result = json.loads(to_string(response)) except Exception: e = sys.exc_info()[1] # Error is parsing json raise Error("Error parsing server response (%d) - %s. Got - %s", code, response, e) if "error" in result: if return_error: result["error"]["http_code"] = code else: raise Error(result["error"]["message"]) return result finally: if file_io: file_io.close()
def smart_escape(string): pack = lambda m: to_bytes('%' + "%".join( ["%02X" % x for x in struct.unpack('B' * len(m.group(1)), m.group(1))]).upper()) return to_string( re.sub(to_bytes(r"([^a-zA-Z0-9_.\-\/:]+)"), pack, to_bytes(string)))
def call_api(action, params, http_headers={}, return_error=False, unsigned=False, file=None, timeout=None, **options): try: file_io = None if unsigned: params = utils.cleanup_params(params) else: params = utils.sign_request(params, options) param_list = [] for k, v in params.items(): if isinstance(v, list): for vv in v: param_list.append((k + "[]", vv)) elif v: param_list.append((k, v)) api_url = utils.cloudinary_api_url(action, **options) global _initialized if not _initialized: _initialized = True # Register the streaming http handlers with urllib2 register_openers() if file: if not isinstance(file, string_types): param_list.append(("file", file)) elif not re.match( r'ftp:|https?:|s3:|data:[^;]*;base64,([a-zA-Z0-9\/+\n=]+)$', file): file_io = open(file, "rb") param_list.append(('file', file_io)) else: param_list.append(("file", file)) datagen, headers = multipart_encode(param_list) if _is_gae(): # Might not be needed in the future but for now this is needed in GAE datagen = "".join(datagen) request = urllib2.Request(api_url, datagen, headers) request.add_header("User-Agent", cloudinary.get_user_agent()) for k, v in http_headers.items(): request.add_header(k, v) kw = {} if timeout is not None: kw['timeout'] = timeout code = 200 try: response = urllib2.urlopen(request, **kw).read() except HTTPError: e = sys.exc_info()[1] if not e.code in [200, 400, 500]: raise Error( "Server returned unexpected status code - %d - %s" % (e.code, e.read())) code = e.code response = e.read() except urllib2.URLError: e = sys.exc_info()[1] raise Error("Error - %s" % str(e)) except socket.error: e = sys.exc_info()[1] raise Error("Socket error: %s" % str(e)) try: result = json.loads(to_string(response)) except Exception: e = sys.exc_info()[1] # Error is parsing json raise Error("Error parsing server response (%d) - %s. Got - %s", code, response, e) if "error" in result: if return_error: result["error"]["http_code"] = code else: raise Error(result["error"]["message"]) return result finally: if file_io: file_io.close()
def smart_escape(source,unsafe = r"([^a-zA-Z0-9_.\-\/:]+)"): def pack(m): return to_bytes('%' + "%".join(["%02X" % x for x in struct.unpack('B' * len(m.group(1)), m.group(1))]).upper()) return to_string(re.sub(to_bytes(unsafe), pack, to_bytes(source)))
def cloudinary_url(source, **options): original_source = source patch_fetch_format(options) type = options.pop("type", "upload") transformation, options = generate_transformation_string(**options) resource_type = options.pop("resource_type", "image") force_version = options.pop("force_version", cloudinary.config().force_version) if force_version is None: force_version = True version = options.pop("version", None) format = options.pop("format", None) cdn_subdomain = options.pop("cdn_subdomain", cloudinary.config().cdn_subdomain) secure_cdn_subdomain = options.pop("secure_cdn_subdomain", cloudinary.config().secure_cdn_subdomain) cname = options.pop("cname", cloudinary.config().cname) shorten = options.pop("shorten", cloudinary.config().shorten) cloud_name = options.pop("cloud_name", cloudinary.config().cloud_name or None) if cloud_name is None: raise ValueError("Must supply cloud_name in tag or in configuration") secure = options.pop("secure", cloudinary.config().secure) private_cdn = options.pop("private_cdn", cloudinary.config().private_cdn) secure_distribution = options.pop("secure_distribution", cloudinary.config().secure_distribution) sign_url = options.pop("sign_url", cloudinary.config().sign_url) api_secret = options.pop("api_secret", cloudinary.config().api_secret) url_suffix = options.pop("url_suffix", None) use_root_path = options.pop("use_root_path", cloudinary.config().use_root_path) auth_token = options.pop("auth_token", None) long_url_signature = options.pop("long_url_signature", cloudinary.config().long_url_signature) signature_algorithm = options.pop("signature_algorithm", cloudinary.config().signature_algorithm) if auth_token is not False: auth_token = merge(cloudinary.config().auth_token, auth_token) if (not source) or type == "upload" and re.match(r'^https?:', source): return original_source, options resource_type, type = finalize_resource_type( resource_type, type, url_suffix, use_root_path, shorten) source, source_to_sign = finalize_source(source, format, url_suffix) if not version and force_version \ and source_to_sign.find("/") >= 0 \ and not re.match(r'^https?:/', source_to_sign) \ and not re.match(r'^v[0-9]+', source_to_sign): version = "1" if version: version = "v" + str(version) else: version = None transformation = re.sub(r'([^:])/+', r'\1/', transformation) signature = None if sign_url and not auth_token: to_sign = "/".join(__compact([transformation, source_to_sign])) if long_url_signature: # Long signature forces SHA256 signature_algorithm = SIGNATURE_SHA256 chars_length = LONG_URL_SIGNATURE_LENGTH else: chars_length = SHORT_URL_SIGNATURE_LENGTH if signature_algorithm not in signature_algorithms: raise ValueError("Unsupported signature algorithm '{}'".format(signature_algorithm)) hash_fn = signature_algorithms[signature_algorithm] signature = "s--" + to_string( base64.urlsafe_b64encode( hash_fn(to_bytes(to_sign + api_secret)).digest())[0:chars_length]) + "--" prefix = unsigned_download_url_prefix( source, cloud_name, private_cdn, cdn_subdomain, secure_cdn_subdomain, cname, secure, secure_distribution) source = "/".join(__compact( [prefix, resource_type, type, signature, transformation, version, source])) if sign_url and auth_token: path = urlparse(source).path token = cloudinary.auth_token.generate(**merge(auth_token, {"url": path})) source = "%s?%s" % (source, token) return source, options
def call_api(action, params, **options): try: file_io = None return_error = options.get("return_error") if options.get("unsigned"): params = utils.cleanup_params(params) else: params = utils.sign_request(params, options) param_list = [] for k, v in params.items(): if isinstance(v, list): for vv in v: param_list.append((k+"[]", vv)) elif v: param_list.append((k, v)) api_url = utils.cloudinary_api_url(action, **options) global _initialized if not _initialized: _initialized = True # Register the streaming http handlers with urllib2 register_openers() datagen = to_bytes("") headers = {} if "file" in options: file = options["file"] if not isinstance(file, string_types): datagen, headers = multipart_encode({'file': file}) elif not re.match(r'^https?:|^s3:|^data:[^;]*;base64,([a-zA-Z0-9\/+\n=]+)$', file): file_io = open(file, "rb") datagen, headers = multipart_encode({'file': file_io}) else: param_list.append(("file", file)) request = urllib2.Request(api_url + "?" + urlencode(param_list), datagen, headers) request.add_header("User-Agent", cloudinary.USER_AGENT) kw = {} if 'timeout' in options: kw['timeout'] = options['timeout'] code = 200 try: response = urllib2.urlopen(request, **kw).read() except socket.error: e = sys.exc_info()[1] raise Error("Socket error: %s" % str(e)) except urllib2.HTTPError: e = sys.exc_info()[1] if not e.code in [200, 400, 500]: raise Error("Server returned unexpected status code - %d - %s" % (e.code, e.read())) code = e.code response = e.read() try: result = json.loads(to_string(response)) except Exception: e = sys.exc_info()[1] # Error is parsing json raise Error("Error parsing server response (%d) - %s. Got - %s", code, response, e) if "error" in result: if return_error: result["error"]["http_code"] = code else: raise Error(result["error"]["message"]) return result finally: if file_io: file_io.close()