123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195 |
- # -*- 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
|