diff --git a/httpie/cli/argparser.py b/httpie/cli/argparser.py index c8ab9ed5..4053b580 100644 --- a/httpie/cli/argparser.py +++ b/httpie/cli/argparser.py @@ -169,6 +169,7 @@ class HTTPieArgumentParser(BaseHTTPieArgumentParser): ) # Arguments processing and environment setup. self._apply_no_options(no_options) + self._process_http_versions() self._process_request_type() self._process_download_options() self._setup_standard_streams() @@ -213,6 +214,38 @@ class HTTPieArgumentParser(BaseHTTPieArgumentParser): return self.args + def _process_http_versions(self): + available, forced, disabled = ( + {1, 2, 3}, + { + self.args.force_http1 and 1, + self.args.force_http2 and 2, + self.args.force_http3 and 3, + } - {False}, + { + self.args.disable_http1 and 1, + self.args.disable_http2 and 2, + self.args.disable_http3 and 3, + } - {False}, + ) + if forced and disabled: + self.error( + 'You cannot both force a http protocol version and disable some other. e.g. ' + '--http2 already force HTTP/2, do not use --disable-http1 at the same time.' + ) + if len(forced) > 1: + self.error( + 'You may only force one of --http1, --http2 or --http3. Use --disable-http1, ' + '--disable-http2 or --disable-http3 instead if you prefer the excluding logic.' + ) + if disabled == available: + self.error('At least one HTTP protocol version must be enabled.') + + if forced: + self.args.disable_http1 = forced != {1} + self.args.disable_http2 = forced != {2} + self.args.disable_http3 = forced != {3} + def _process_request_type(self): request_type = self.args.request_type self.args.json = request_type is RequestType.JSON diff --git a/httpie/client.py b/httpie/client.py index de42a743..05949f4c 100644 --- a/httpie/client.py +++ b/httpie/client.py @@ -73,41 +73,11 @@ def collect_messages( # We want to make sure every ".localhost" host resolve to loopback if parsed_url.host and parsed_url.host.endswith(".localhost"): ensure_resolver = f"in-memory://default/?hosts={parsed_url.host}:127.0.0.1&hosts={parsed_url.host}:[::1]" - if resolver and isinstance(resolver, list): resolver.append(ensure_resolver) else: resolver = [ensure_resolver, "system://"] - force_opt_count = [args.force_http1, args.force_http2, args.force_http3].count(True) - disable_opt_count = [args.disable_http1, args.disable_http2, args.disable_http3].count(True) - - if force_opt_count > 1: - raise ValueError( - 'You may only force one of --http1, --http2 or --http3. Use --disable-http1, ' - '--disable-http2 or --disable-http3 instead if you prefer the excluding logic.' - ) - elif force_opt_count == 1 and disable_opt_count: - raise ValueError( - 'You cannot both force a http protocol version and disable some other. e.g. ' - '--http2 already force HTTP/2, do not use --disable-http1 at the same time.' - ) - - if args.force_http1: - args.disable_http1 = False - args.disable_http2 = True - args.disable_http3 = True - - if args.force_http2: - args.disable_http1 = True - args.disable_http2 = False - args.disable_http3 = True - - if args.force_http3: - args.disable_http1 = True - args.disable_http2 = True - args.disable_http3 = False - requests_session = build_requests_session( ssl_version=args.ssl_version, ciphers=args.ciphers, diff --git a/tests/test_h2n3.py b/tests/test_h2n3.py index 216ef0ad..6a680ecc 100644 --- a/tests/test_h2n3.py +++ b/tests/test_h2n3.py @@ -68,7 +68,7 @@ def test_disable_all_error_https(remote_httpbin_secure): tolerate_error_exit_status=True, ) - assert 'You disabled every supported protocols.' in r.stderr + assert 'At least one HTTP protocol version must be enabled.' in r.stderr def test_disable_all_error_http(remote_httpbin): @@ -94,8 +94,10 @@ def test_disable_all_error_http(remote_httpbin): def with_quic_cache_persistent(tmp_path): env = PersistentMockEnvironment() env.config['quic_file'] = tmp_path / 'quic.json' - yield env - env.cleanup(force=True) + try: + yield env + finally: + env.cleanup(force=True) @pytest.mark.skipif(qh3 is None, reason="test require HTTP/3 support")