Mercurial > repos > shellac > guppy_basecaller
comparison env/lib/python3.7/site-packages/requests_toolbelt/utils/dump.py @ 0:26e78fe6e8c4 draft
"planemo upload commit c699937486c35866861690329de38ec1a5d9f783"
| author | shellac |
|---|---|
| date | Sat, 02 May 2020 07:14:21 -0400 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| -1:000000000000 | 0:26e78fe6e8c4 |
|---|---|
| 1 """This module provides functions for dumping information about responses.""" | |
| 2 import collections | |
| 3 | |
| 4 from requests import compat | |
| 5 | |
| 6 | |
| 7 __all__ = ('dump_response', 'dump_all') | |
| 8 | |
| 9 HTTP_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 | |
| 19 class 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 | |
| 26 def _get_proxy_information(response): | |
| 27 if getattr(response.connection, 'proxy_manager', False): | |
| 28 proxy_info = {} | |
| 29 request_url = response.request.url | |
| 30 if request_url.startswith('https://'): | |
| 31 proxy_info['method'] = 'CONNECT' | |
| 32 | |
| 33 proxy_info['request_path'] = request_url | |
| 34 return proxy_info | |
| 35 return None | |
| 36 | |
| 37 | |
| 38 def _format_header(name, value): | |
| 39 return (_coerce_to_bytes(name) + b': ' + _coerce_to_bytes(value) + | |
| 40 b'\r\n') | |
| 41 | |
| 42 | |
| 43 def _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, uri | |
| 49 | |
| 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, uri | |
| 55 | |
| 56 | |
| 57 def _dump_request_data(request, prefixes, bytearr, proxy_info=None): | |
| 58 if proxy_info is None: | |
| 59 proxy_info = {} | |
| 60 | |
| 61 prefix = prefixes.request | |
| 62 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.1 | |
| 66 bytearr.extend(prefix + method + b' ' + request_path + b' HTTP/1.1\r\n') | |
| 67 | |
| 68 # <prefix>Host: <request-host> OR host header specified by user | |
| 69 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 try | |
| 82 # to read everything into memory. | |
| 83 bytearr.extend(b'<< Request body is not a string-like type >>') | |
| 84 bytearr.extend(b'\r\n') | |
| 85 | |
| 86 | |
| 87 def _dump_response_data(response, prefixes, bytearr): | |
| 88 prefix = prefixes.response | |
| 89 # Let's interact almost entirely with urllib3's response | |
| 90 raw = response.raw | |
| 91 | |
| 92 # Let's convert the version int from httplib to bytes | |
| 93 version_str = HTTP_VERSIONS.get(raw.version, b'?') | |
| 94 | |
| 95 # <prefix>HTTP/<version_str> <status_code> <reason> | |
| 96 bytearr.extend(prefix + b'HTTP/' + version_str + b' ' + | |
| 97 str(raw.status).encode('ascii') + b' ' + | |
| 98 _coerce_to_bytes(response.reason) + b'\r\n') | |
| 99 | |
| 100 headers = raw.headers | |
| 101 for name in headers.keys(): | |
| 102 for value in headers.getlist(name): | |
| 103 bytearr.extend(prefix + _format_header(name, value)) | |
| 104 | |
| 105 bytearr.extend(prefix + b'\r\n') | |
| 106 | |
| 107 bytearr.extend(response.content) | |
| 108 | |
| 109 | |
| 110 def _coerce_to_bytes(data): | |
| 111 if not isinstance(data, bytes) and hasattr(data, 'encode'): | |
| 112 data = data.encode('utf-8') | |
| 113 # Don't bail out with an exception if data is None | |
| 114 return data if data is not None else b'' | |
| 115 | |
| 116 | |
| 117 def dump_response(response, request_prefix=b'< ', response_prefix=b'> ', | |
| 118 data_array=None): | |
| 119 """Dump a single request-response cycle's information. | |
| 120 | |
| 121 This will take a response object and dump only the data that requests can | |
| 122 see for that single request-response cycle. | |
| 123 | |
| 124 Example:: | |
| 125 | |
| 126 import requests | |
| 127 from requests_toolbelt.utils import dump | |
| 128 | |
| 129 resp = requests.get('https://api.github.com/users/sigmavirus24') | |
| 130 data = dump.dump_response(resp) | |
| 131 print(data.decode('utf-8')) | |
| 132 | |
| 133 :param response: | |
| 134 The response to format | |
| 135 :type response: :class:`requests.Response` | |
| 136 :param request_prefix: (*optional*) | |
| 137 Bytes to prefix each line of the request data | |
| 138 :type request_prefix: :class:`bytes` | |
| 139 :param response_prefix: (*optional*) | |
| 140 Bytes to prefix each line of the response data | |
| 141 :type response_prefix: :class:`bytes` | |
| 142 :param data_array: (*optional*) | |
| 143 Bytearray to which we append the request-response cycle data | |
| 144 :type data_array: :class:`bytearray` | |
| 145 :returns: Formatted bytes of request and response information. | |
| 146 :rtype: :class:`bytearray` | |
| 147 """ | |
| 148 data = data_array if data_array is not None else bytearray() | |
| 149 prefixes = PrefixSettings(request_prefix, response_prefix) | |
| 150 | |
| 151 if not hasattr(response, 'request'): | |
| 152 raise ValueError('Response has no associated request') | |
| 153 | |
| 154 proxy_info = _get_proxy_information(response) | |
| 155 _dump_request_data(response.request, prefixes, data, | |
| 156 proxy_info=proxy_info) | |
| 157 _dump_response_data(response, prefixes, data) | |
| 158 return data | |
| 159 | |
| 160 | |
| 161 def dump_all(response, request_prefix=b'< ', response_prefix=b'> '): | |
| 162 """Dump all requests and responses including redirects. | |
| 163 | |
| 164 This takes the response returned by requests and will dump all | |
| 165 request-response pairs in the redirect history in order followed by the | |
| 166 final request-response. | |
| 167 | |
| 168 Example:: | |
| 169 | |
| 170 import requests | |
| 171 from requests_toolbelt.utils import dump | |
| 172 | |
| 173 resp = requests.get('https://httpbin.org/redirect/5') | |
| 174 data = dump.dump_all(resp) | |
| 175 print(data.decode('utf-8')) | |
| 176 | |
| 177 :param response: | |
| 178 The response to format | |
| 179 :type response: :class:`requests.Response` | |
| 180 :param request_prefix: (*optional*) | |
| 181 Bytes to prefix each line of the request data | |
| 182 :type request_prefix: :class:`bytes` | |
| 183 :param response_prefix: (*optional*) | |
| 184 Bytes to prefix each line of the response data | |
| 185 :type response_prefix: :class:`bytes` | |
| 186 :returns: Formatted bytes of request and response information. | |
| 187 :rtype: :class:`bytearray` | |
| 188 """ | |
| 189 data = bytearray() | |
| 190 | |
| 191 history = list(response.history[:]) | |
| 192 history.append(response) | |
| 193 | |
| 194 for response in history: | |
| 195 dump_response(response, request_prefix, response_prefix, data) | |
| 196 | |
| 197 return data |
