Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes14kdownloads
dump.py199 linesDownload Raw Back to utils
1"""This module provides functions for dumping information about responses."""2import collections3 4from requests import compat5 6 7__all__ = ('dump_response', 'dump_all')8 9HTTP_VERSIONS = {10    9: b'0.9',11    10: b'1.0',12    11: b'1.1',13}14 15_PrefixSettings = collections.namedtuple('PrefixSettings',16                                         ['request', 'response'])17 18 19class PrefixSettings(_PrefixSettings):20    def __new__(cls, request, response):21        request = _coerce_to_bytes(request)22        response = _coerce_to_bytes(response)23        return super(PrefixSettings, cls).__new__(cls, request, response)24 25 26def _get_proxy_information(response):27    if getattr(response.connection, 'proxy_manager', False):28        proxy_info = {}29        request_url = response.request.url30        if request_url.startswith('https://'):31            proxy_info['method'] = 'CONNECT'32 33        proxy_info['request_path'] = request_url34        return proxy_info35    return None36 37 38def _format_header(name, value):39    return (_coerce_to_bytes(name) + b': ' + _coerce_to_bytes(value) +40            b'\r\n')41 42 43def _build_request_path(url, proxy_info):44    uri = compat.urlparse(url)45    proxy_url = proxy_info.get('request_path')46    if proxy_url is not None:47        request_path = _coerce_to_bytes(proxy_url)48        return request_path, uri49 50    request_path = _coerce_to_bytes(uri.path)51    if uri.query:52        request_path += b'?' + _coerce_to_bytes(uri.query)53 54    return request_path, uri55 56 57def _dump_request_data(request, prefixes, bytearr, proxy_info=None):58    if proxy_info is None:59        proxy_info = {}60 61    prefix = prefixes.request62    method = _coerce_to_bytes(proxy_info.pop('method', request.method))63    request_path, uri = _build_request_path(request.url, proxy_info)64 65    # <prefix><METHOD> <request-path> HTTP/1.166    bytearr.extend(prefix + method + b' ' + request_path + b' HTTP/1.1\r\n')67 68    # <prefix>Host: <request-host> OR host header specified by user69    headers = request.headers.copy()70    host_header = _coerce_to_bytes(headers.pop('Host', uri.netloc))71    bytearr.extend(prefix + b'Host: ' + host_header + b'\r\n')72 73    for name, value in headers.items():74        bytearr.extend(prefix + _format_header(name, value))75 76    bytearr.extend(prefix + b'\r\n')77    if request.body:78        if isinstance(request.body, compat.basestring):79            bytearr.extend(prefix + _coerce_to_bytes(request.body))80        else:81            # In the event that the body is a file-like object, let's not try82            # to read everything into memory.83            bytearr.extend(b'<< Request body is not a string-like type >>')84        bytearr.extend(b'\r\n')85    bytearr.extend(b'\r\n')86 87 88def _dump_response_data(response, prefixes, bytearr):89    prefix = prefixes.response90    # Let's interact almost entirely with urllib3's response91    raw = response.raw92 93    # Let's convert the version int from httplib to bytes94    version_str = HTTP_VERSIONS.get(raw.version, b'?')95 96    # <prefix>HTTP/<version_str> <status_code> <reason>97    bytearr.extend(prefix + b'HTTP/' + version_str + b' ' +98                   str(raw.status).encode('ascii') + b' ' +99                   _coerce_to_bytes(response.reason) + b'\r\n')100 101    headers = raw.headers102    for name in headers.keys():103        for value in headers.getlist(name):104            bytearr.extend(prefix + _format_header(name, value))105 106    bytearr.extend(prefix + b'\r\n')107 108    bytearr.extend(response.content)109 110 111def _coerce_to_bytes(data):112    if not isinstance(data, bytes) and hasattr(data, 'encode'):113        data = data.encode('utf-8')114    # Don't bail out with an exception if data is None115    return data if data is not None else b''116 117 118def dump_response(response, request_prefix=b'< ', response_prefix=b'> ',119                  data_array=None):120    """Dump a single request-response cycle's information.121 122    This will take a response object and dump only the data that requests can123    see for that single request-response cycle.124 125    Example::126 127        import requests128        from requests_toolbelt.utils import dump129 130        resp = requests.get('https://api.github.com/users/sigmavirus24')131        data = dump.dump_response(resp)132        print(data.decode('utf-8'))133 134    :param response:135        The response to format136    :type response: :class:`requests.Response`137    :param request_prefix: (*optional*)138        Bytes to prefix each line of the request data139    :type request_prefix: :class:`bytes`140    :param response_prefix: (*optional*)141        Bytes to prefix each line of the response data142    :type response_prefix: :class:`bytes`143    :param data_array: (*optional*)144        Bytearray to which we append the request-response cycle data145    :type data_array: :class:`bytearray`146    :returns: Formatted bytes of request and response information.147    :rtype: :class:`bytearray`148    """149    data = data_array if data_array is not None else bytearray()150    prefixes = PrefixSettings(request_prefix, response_prefix)151 152    if not hasattr(response, 'request'):153        raise ValueError('Response has no associated request')154 155    proxy_info = _get_proxy_information(response)156    _dump_request_data(response.request, prefixes, data,157                       proxy_info=proxy_info)158    _dump_response_data(response, prefixes, data)159    return data160 161 162def dump_all(response, request_prefix=b'< ', response_prefix=b'> '):163    """Dump all requests and responses including redirects.164 165    This takes the response returned by requests and will dump all166    request-response pairs in the redirect history in order followed by the167    final request-response.168 169    Example::170 171        import requests172        from requests_toolbelt.utils import dump173 174        resp = requests.get('https://httpbin.org/redirect/5')175        data = dump.dump_all(resp)176        print(data.decode('utf-8'))177 178    :param response:179        The response to format180    :type response: :class:`requests.Response`181    :param request_prefix: (*optional*)182        Bytes to prefix each line of the request data183    :type request_prefix: :class:`bytes`184    :param response_prefix: (*optional*)185        Bytes to prefix each line of the response data186    :type response_prefix: :class:`bytes`187    :returns: Formatted bytes of request and response information.188    :rtype: :class:`bytearray`189    """190    data = bytearray()191 192    history = list(response.history[:])193    history.append(response)194 195    for response in history:196        dump_response(response, request_prefix, response_prefix, data)197 198    return data199 
codekingpro/portable-devtools · Team Ai