Why Gemfury? Push, build, and install  RubyGems npm packages Python packages Maven artifacts PHP packages Go Modules Debian packages RPM packages NuGet packages

Repository URL to install this package:

Details    
alipay-sdk-python / alipay / aop / api / util / WebUtils.py
Size: Mime:
# -*- coding: utf-8 -*-
'''
Created on 2017-12-20

@author: liuqun
'''
import json
import os

import itertools

from alipay.aop.api.FileItem import FileItem
from alipay.aop.api.constant.CommonConstants import *

try:
    import httplib
except ImportError:
    import http.client as httplib
try:
    import urlparse
except ImportError:
    import urllib.parse as urlparse
try:
    from urllib.parse import quote_plus
except ImportError:
    from urllib import quote_plus
import mimetypes

from alipay.aop.api.exception.Exception import *


class MultiPartForm(object):
    """Accumulate the data to be used when posting a form."""

    def __init__(self, charset='utf-8'):
        self.charset = charset
        self.form_fields = []
        self.files = []
        self.boundary = "ALIPAY_SDK_PYTHON_BOUNDARY"
        return

    def get_content_type(self):
        return 'multipart/form-data; boundary=%s' % self.boundary

    def add_field(self, name, value):
        """Add a simple field to the form data."""
        if not isinstance(value, str):
            value = json.dumps(value, ensure_ascii=False)
        self.form_fields.append((name, value))
        return

    def add_file(self, field_name, file_name, file_content, mimetype=None):
        """Add a file to be uploaded."""
        if mimetype is None:
            mimetype = mimetypes.guess_type(file_name)[0] or 'application/octet-stream'
        self.files.append((field_name, file_name, mimetype, file_content))
        return

    def build_body(self):
        """Return a string representing the form data, including attached files."""
        # Build a list of lists, each containing "lines" of the
        # request.  Each part is separated by a boundary string.
        # Once the list is built, return a string where each
        # line is separated by '\r\n'.
        parts = []
        part_boundary = '--' + self.boundary

        # Add the form fields
        parts.extend(
            [bytes(part_boundary.encode(self.charset)),
             bytes(('Content-Disposition: form-data; name="%s"' % name).encode(self.charset))
                if PYTHON_VERSION_3 else ('Content-Disposition: form-data; name="%s"' % name),
             bytes(('Content-Type: text/plain; charset=%s' % self.charset).encode(self.charset)),
             bytes(''.encode(self.charset)),
             bytes(value.encode(self.charset)) if PYTHON_VERSION_3 else value
            ]
            for name, value in self.form_fields
        )

        # Add the files to upload
        parts.extend(
            [bytes(part_boundary.encode(self.charset)),
             bytes(('Content-Disposition: form-data; name="%s"; filename="%s"' %
                    (field_name, filename)).encode(self.charset)) if PYTHON_VERSION_3 else
                    ('Content-Disposition: form-data; name="%s"; filename="%s"' % (field_name, filename)),
             bytes(('Content-Type: %s' % content_type).encode(self.charset)),
             bytes('Content-Transfer-Encoding: binary'.encode(self.charset)),
             bytes(''.encode(self.charset)),
             body,
            ]
            for field_name, filename, content_type, body in self.files
        )

        # Flatten the list and add closing boundary marker,
        # then return CR+LF separated data
        flattened = list(itertools.chain(*parts))
        flattened.append(bytes(('--' + self.boundary + '--').encode(self.charset)))
        flattened.append(bytes(''.encode(self.charset)))
        return bytes('\r\n'.encode(self.charset)).join(flattened)


def url_encode(params, charset):
    query_string = ""
    for (k, v) in params.items():
        value = v
        if not isinstance(value, str):
            value = json.dumps(value, ensure_ascii=False)
        if PYTHON_VERSION_3:
            value = quote_plus(value, encoding=charset)
        else:
            value = quote_plus(value)
        query_string += ("&" + k + "=" + value)
    query_string = query_string[1:]
    return query_string


def get_http_connection(url, query_string, timeout):
    url_parse_result = urlparse.urlparse(url)
    host = url_parse_result.hostname
    port = 80
    connection = httplib.HTTPConnection(host=host, port=port, timeout=timeout)
    if url.find("https") == 0:
        port = 443
        connection = httplib.HTTPSConnection(host=host, port=port, timeout=timeout)
    url = url_parse_result.scheme + "://" + url_parse_result.hostname
    if url_parse_result.port:
        url += url_parse_result.port
    url += url_parse_result.path
    url += ('?' + query_string)
    return url, connection


def do_post(url, query_string=None, headers=None, params=None, charset='utf-8', timeout=15):
    url, connection = get_http_connection(url, query_string, timeout)

    try:
        connection.connect()
    except Exception as e:
        raise RequestException('[' + THREAD_LOCAL.uuid + ']post connect failed. ' + str(e))
    body = None
    if params:
        body = url_encode(params, charset)
    try:
        connection.request("POST", url, body=body, headers=headers)
    except Exception as e:
        raise RequestException('[' + THREAD_LOCAL.uuid + ']post request failed. ' + str(e))
    response = connection.getresponse()
    if response.status is not 200:
        raise ResponseException('[' + THREAD_LOCAL.uuid + ']invalid http status ' + str(response.status) + \
                               ',detail body:' + response.read())
    result = response.read()
    try:
        response.close()
        connection.close()
    except Exception:
        pass
    return result


def do_multipart_post(url, query_string=None, headers=None, params=None, multipart_params=None, charset='utf-8', timeout=30):
    url, connection = get_http_connection(url, query_string, timeout)

    try:
        connection.connect()
    except Exception as e:
        raise RequestException('[' + THREAD_LOCAL.uuid + ']post connect failed. ' + str(e))

    form = MultiPartForm(charset)
    for key, value in params.items():
        form.add_field(key, value)
    for key, value in multipart_params.items():
        file_item = value
        if file_item and isinstance(file_item, FileItem):
            form.add_file(field_name=key, file_name=file_item.get_file_name(),
                          file_content=file_item.get_file_content(), mimetype=file_item.get_mime_type())
    body = form.build_body()
    if not headers:
        headers = {}
    headers['Content-type'] = form.get_content_type()

    try:
        connection.request("POST", url, body=body, headers=headers)
    except Exception as e:
        raise RequestException('[' + THREAD_LOCAL.uuid + ']post request failed. ' + str(e))
    response = connection.getresponse()
    if response.status is not 200:
        raise ResponseException('[' + THREAD_LOCAL.uuid + ']invalid http status ' + str(response.status) + \
                                ',detail body:' + response.read())
    result = response.read()
    try:
        response.close()
        connection.close()
    except Exception:
        pass
    return result