mirror of
https://github.com/httpie/cli.git
synced 2024-11-28 10:43:24 +01:00
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>
48 lines
1.8 KiB
Python
48 lines
1.8 KiB
Python
from http.cookies import SimpleCookie
|
|
from http.server import BaseHTTPRequestHandler, HTTPServer
|
|
from threading import Thread
|
|
|
|
from .utils import http
|
|
|
|
|
|
class TestIntegration:
|
|
|
|
def setup_mock_server(self, handler):
|
|
"""Configure mock server."""
|
|
# Passing 0 as the port will cause a random free port to be chosen.
|
|
self.mock_server = HTTPServer(('localhost', 0), handler)
|
|
_, self.mock_server_port = self.mock_server.server_address
|
|
|
|
# Start running mock server in a separate thread.
|
|
# Daemon threads automatically shut down when the main process exits.
|
|
self.mock_server_thread = Thread(target=self.mock_server.serve_forever)
|
|
self.mock_server_thread.setDaemon(True)
|
|
self.mock_server_thread.start()
|
|
|
|
def test_cookie_parser(self):
|
|
"""Not directly testing HTTPie but `requests` to ensure their cookies handling
|
|
is still as expected by `get_expired_cookies()`.
|
|
"""
|
|
|
|
class MockServerRequestHandler(BaseHTTPRequestHandler):
|
|
""""HTTP request handler."""
|
|
|
|
def do_GET(self):
|
|
"""Handle GET requests."""
|
|
# Craft multiple cookies
|
|
cookie = SimpleCookie()
|
|
cookie['hello'] = 'world'
|
|
cookie['hello']['path'] = self.path
|
|
cookie['oatmeal_raisin'] = 'is the best'
|
|
cookie['oatmeal_raisin']['path'] = self.path
|
|
|
|
# Send HTTP headers
|
|
self.send_response(200)
|
|
self.send_header('Set-Cookie', cookie.output())
|
|
self.end_headers()
|
|
|
|
self.setup_mock_server(MockServerRequestHandler)
|
|
response = http(f'http://localhost:{self.mock_server_port}/')
|
|
assert 'Set-Cookie: hello=world; Path=/' in response
|
|
assert 'Set-Cookie: oatmeal_raisin="is the best"; Path=/' in response
|