add support for early responses 1xx (informational)

This commit is contained in:
Ahmed TAHRI 2024-10-13 20:09:35 +02:00
parent 2e3617ecdb
commit 1379a2e281
5 changed files with 34 additions and 14 deletions

View File

@ -3,10 +3,11 @@
This document records all notable changes to [HTTPie](https://httpie.io).
This project adheres to [Semantic Versioning](https://semver.org/).
## [4.0.0.b1](https://github.com/httpie/cli/compare/3.2.2...master) (unreleased)
## [4.0.0](https://github.com/httpie/cli/compare/3.2.3...master) (unreleased)
- Switched from the [`requests`](https://github.com/psf/requests) library to the compatible [`niquests`](https://github.com/jawah/niquests). ([#1531](https://github.com/httpie/cli/pull/1531))
- Added support for HTTP/2, and HTTP/3 protocols. ([#523](https://github.com/httpie/cli/issues/523), [#692](https://github.com/httpie/cli/issues/692), [#1531](https://github.com/httpie/cli/pull/1531))
- Added support for early (informational) responses. ([#752](https://github.com/httpie/cli/issues/752)) ([#1531](https://github.com/httpie/cli/pull/1531))
- Added support for IPv4/IPv6 enforcement with `-6` and `-4`. ([#94](https://github.com/httpie/cli/issues/94), [#1531](https://github.com/httpie/cli/pull/1531))
- Added support for alternative DNS resolvers via `--resolver`. DNS over HTTPS, DNS over TLS, DNS over QUIC, and DNS over UDP are accepted. ([#99](https://github.com/httpie/cli/issues/99), [#1531](https://github.com/httpie/cli/pull/1531))
- Added support for binding to a specific network adapter with `--interface`. ([#1422](https://github.com/httpie/cli/issues/1422), [#1531](https://github.com/httpie/cli/pull/1531))

View File

@ -1,3 +1,5 @@
from __future__ import annotations
import argparse
import json
import sys
@ -43,7 +45,7 @@ def collect_messages(
env: Environment,
args: argparse.Namespace,
request_body_read_callback: Callable[[bytes], None] = None,
prepared_request_readiness: Callable[[niquests.PreparedRequest], None] = None,
request_or_response_callback: Callable[[niquests.PreparedRequest | niquests.Response], None] = None,
) -> Iterable[RequestsMessage]:
httpie_session = None
httpie_session_headers = None
@ -155,8 +157,8 @@ def collect_messages(
# It will help us yield the request before it is
# actually sent. This will permit us to know about
# the connection information for example.
if prepared_request_readiness:
hooks = {"pre_send": [prepared_request_readiness]}
if request_or_response_callback:
hooks = {"pre_send": [request_or_response_callback], "early_response": [request_or_response_callback]}
request = niquests.Request(**request_kwargs, hooks=hooks)
prepared_request = requests_session.prepare_request(request)

View File

@ -3,6 +3,7 @@ import os
import platform
import sys
import socket
from time import monotonic
from typing import List, Optional, Union, Callable
import niquests
@ -211,21 +212,26 @@ def program(args: argparse.Namespace, env: Environment) -> ExitStatus:
downloader = Downloader(env, output_file=args.output_file, resume=args.download_resume)
downloader.pre_request(args.headers)
def prepared_request_readiness(pr):
"""This callback is meant to output the request part. It is triggered by
the underlying Niquests library just after establishing the connection."""
def request_or_response_callback(delayed_message):
"""This callback is called in two scenario:
(i) just after initializing a connection to remote host
(ii) an early response has been received (1xx responses)"""
oo = OutputOptions.from_message(
pr,
delayed_message,
args.output_options
)
oo = oo._replace(
body=isinstance(pr.body, (str, bytes)) and (args.verbose or oo.body)
)
if hasattr(delayed_message, "body"):
oo = oo._replace(
body=isinstance(delayed_message.body, (str, bytes)) and (args.verbose or oo.body)
)
else:
delayed_message._httpie_headers_parsed_at = monotonic()
write_message(
requests_message=pr,
requests_message=delayed_message,
env=env,
output_options=oo,
processing_options=processing_options
@ -238,7 +244,7 @@ def program(args: argparse.Namespace, env: Environment) -> ExitStatus:
env,
args=args,
request_body_read_callback=request_body_read_callback,
prepared_request_readiness=prepared_request_readiness
request_or_response_callback=request_or_response_callback
)
force_separator = False

View File

@ -71,7 +71,7 @@ install_requires =
pip
charset_normalizer>=2.0.0
defusedxml>=0.6.0
niquests[socks]>=3.7
niquests[socks]>=3.9
Pygments>=2.5.2
setuptools
importlib-metadata>=1.4.0; python_version<"3.8"

View File

@ -0,0 +1,11 @@
from .utils import http
def test_early_response_show(remote_httpbin_secure):
r = http(
"--verify=no",
'https://early-hints.fastlylabs.com/'
)
assert "103 Early Hints" in r
assert "200 OK" in r