forked from extern/httpie-cli
147a066dbe
* Support `requests.response.raw` being a file-like object Previously HTTPie relied on `requests.models.Response.raw` being `urllib3.HTTPResponse`. The `requests` documentation specifies that (requests.models.Response.raw)[https://docs.python-requests.org/en/master/api/#requests.Response.raw] is a file-like object but allows for other types for internal use. This change introduces graceful handling for scenarios when `requests.models.Response.raw` is not `urllib3.HTTPResponse`. In such a scenario HTTPie now falls back to extracting metadata from `requests.models.Response` directly instead of direct access from protected protected members such as `response.raw._original_response`. A side effect in this fallback procedure is that we can no longer determine HTTP protocol version and report it as `1.1`. This change is necessary to make it possible to implement `TransportPlugins` without having to also needing to emulate internal behavior of `urlib3` and `http.client`. * Load cookies from `response.headers` instead of `response.raw._original_response.msg._headers` `response.cookies` was not utilized as it not possible to construct original payload from `http.cookiejar.Cookie`. Data is stored in lossy format. For example `Cookie.secure` defaults to `False` so we cannot distinguish if `Cookie.secure` was set to `False` or was not set at all. Same problem applies to other fields also. * Simpler HTTP envelope data extraction * Test cookie extraction and make cookie presentment backwards compatible Co-authored-by: Mickaël Schoentgen <contact@tiger-222.fr> Co-authored-by: Jakub Roztocil <jakub@roztocil.co>
46 lines
1.2 KiB
Python
46 lines
1.2 KiB
Python
from io import BytesIO
|
|
|
|
from requests.adapters import BaseAdapter
|
|
from requests.models import Response
|
|
from requests.utils import get_encoding_from_headers
|
|
|
|
from httpie.plugins import TransportPlugin
|
|
from httpie.plugins.registry import plugin_manager
|
|
|
|
from .utils import HTTP_OK, http
|
|
|
|
SCHEME = 'http+fake'
|
|
|
|
|
|
class FakeAdapter(BaseAdapter):
|
|
def send(self, request, **kwargs):
|
|
response = Response()
|
|
response.status_code = 200
|
|
response.reason = 'OK'
|
|
response.headers = {
|
|
'Content-Type': 'text/html; charset=UTF-8',
|
|
}
|
|
response.encoding = get_encoding_from_headers(response.headers)
|
|
response.raw = BytesIO(b'<!doctype html><html>Hello</html>')
|
|
return response
|
|
|
|
|
|
class FakeTransportPlugin(TransportPlugin):
|
|
name = 'Fake Transport'
|
|
|
|
prefix = SCHEME
|
|
|
|
def get_adapter(self):
|
|
return FakeAdapter()
|
|
|
|
|
|
def test_transport_from_requests_response(httpbin):
|
|
plugin_manager.register(FakeTransportPlugin)
|
|
try:
|
|
r = http(f'{SCHEME}://example.com')
|
|
assert HTTP_OK in r
|
|
assert 'Hello' in r
|
|
assert 'Content-Type: text/html; charset=UTF-8' in r
|
|
finally:
|
|
plugin_manager.unregister(FakeTransportPlugin)
|