summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBatuhan Taskaya <isidentical@gmail.com>2022-04-03 16:02:41 +0300
committerGitHub <noreply@github.com>2022-04-03 06:02:41 -0700
commit33ea977b6443a023315084f2fb78e712a073ad65 (patch)
tree593b4661e05bd3ab7b8a3081d6f9f26d5a16f829
parentd1596dde126b1a491389329a424eba5602c9b67e (diff)
Don't send `Content-Length` for `OPTIONS` requests when there is no data. (#1319)
-rw-r--r--CHANGELOG.md4
-rw-r--r--httpie/__init__.py2
-rw-r--r--httpie/cli/constants.py1
-rw-r--r--httpie/client.py31
-rw-r--r--tests/test_httpie.py38
5 files changed, 71 insertions, 5 deletions
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 764c1738..509e7ee2 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -3,6 +3,10 @@
This document records all notable changes to [HTTPie](https://httpie.io).
This project adheres to [Semantic Versioning](https://semver.org/).
+## [3.1.1.dev0](https://github.com/httpie/httpie/compare/3.1.0...HEAD) (Unreleased)
+
+- Fixed redundant creation of `Content-Length` header on `OPTIONS` requests. ([#1310](https://github.com/httpie/httpie/issues/1310))
+
## [3.1.0](https://github.com/httpie/httpie/compare/3.0.2...3.1.0) (2022-03-08)
- **SECURITY** Fixed the [vulnerability](https://github.com/httpie/httpie/security/advisories/GHSA-9w4w-cpc8-h2fq) that caused exposure of cookies on redirects to third party hosts. ([#1312](https://github.com/httpie/httpie/pull/1312))
diff --git a/httpie/__init__.py b/httpie/__init__.py
index 90aa2789..c8b2eb5e 100644
--- a/httpie/__init__.py
+++ b/httpie/__init__.py
@@ -3,6 +3,6 @@ HTTPie: modern, user-friendly command-line HTTP client for the API era.
"""
-__version__ = '3.1.0'
+__version__ = '3.1.1.dev0'
__author__ = 'Jakub Roztocil'
__licence__ = 'BSD'
diff --git a/httpie/cli/constants.py b/httpie/cli/constants.py
index e8188938..61e61f40 100644
--- a/httpie/cli/constants.py
+++ b/httpie/cli/constants.py
@@ -9,6 +9,7 @@ URL_SCHEME_RE = re.compile(r'^[a-z][a-z0-9.+-]*://', re.IGNORECASE)
HTTP_POST = 'POST'
HTTP_GET = 'GET'
+HTTP_OPTIONS = 'OPTIONS'
# Various separators used in args
SEPARATOR_HEADER = ':'
diff --git a/httpie/client.py b/httpie/client.py
index 530d589c..047b7856 100644
--- a/httpie/client.py
+++ b/httpie/client.py
@@ -13,7 +13,7 @@ import urllib3
from . import __version__
from .adapters import HTTPieHTTPAdapter
from .context import Environment
-from .cli.constants import EMPTY_STRING
+from .cli.constants import EMPTY_STRING, HTTP_OPTIONS
from .cli.dicts import HTTPHeadersDict, NestedJSONArray
from .encoding import UTF8
from .models import RequestsMessage
@@ -34,6 +34,8 @@ JSON_CONTENT_TYPE = 'application/json'
JSON_ACCEPT = f'{JSON_CONTENT_TYPE}, */*;q=0.5'
DEFAULT_UA = f'HTTPie/{__version__}'
+IGNORE_CONTENT_LENGTH_METHODS = frozenset([HTTP_OPTIONS])
+
def collect_messages(
env: Environment,
@@ -85,7 +87,7 @@ def collect_messages(
request = requests.Request(**request_kwargs)
prepared_request = requests_session.prepare_request(request)
- apply_missing_repeated_headers(prepared_request, request.headers)
+ transform_headers(request, prepared_request)
if args.path_as_is:
prepared_request.url = ensure_path_as_is(
orig_url=args.url,
@@ -200,9 +202,30 @@ def finalize_headers(headers: HTTPHeadersDict) -> HTTPHeadersDict:
return final_headers
+def transform_headers(
+ request: requests.Request,
+ prepared_request: requests.PreparedRequest
+) -> None:
+ """Apply various transformations on top of the `prepared_requests`'s
+ headers to change the request prepreation behavior."""
+
+ # Remove 'Content-Length' when it is misplaced by requests.
+ if (
+ prepared_request.method in IGNORE_CONTENT_LENGTH_METHODS
+ and prepared_request.headers.get('Content-Length') == '0'
+ and request.headers.get('Content-Length') != '0'
+ ):
+ prepared_request.headers.pop('Content-Length')
+
+ apply_missing_repeated_headers(
+ request.headers,
+ prepared_request
+ )
+
+
def apply_missing_repeated_headers(
- prepared_request: requests.PreparedRequest,
- original_headers: HTTPHeadersDict
+ original_headers: HTTPHeadersDict,
+ prepared_request: requests.PreparedRequest
) -> None:
"""Update the given `prepared_request`'s headers with the original
ones. This allows the requests to be prepared as usual, and then later
diff --git a/tests/test_httpie.py b/tests/test_httpie.py
index f646d4e0..f07f34b9 100644
--- a/tests/test_httpie.py
+++ b/tests/test_httpie.py
@@ -324,3 +324,41 @@ def test_json_input_preserve_order(httpbin_both):
assert HTTP_OK in r
assert r.json['data'] == \
'{"order": {"map": {"1": "first", "2": "second"}}}'
+
+
+@pytest.mark.parametrize('extra_args, expected_content_length', [
+ (
+ ['Content-Length:0'],
+ '0'
+ ),
+ (
+ ['Content-Length:xxx'],
+ 'xxx',
+ ),
+ (
+ ['--raw=data'],
+ '4'
+ ),
+ (
+ ['query[param]=something'],
+ '33'
+ )
+])
+def test_options_content_length_preservation(httpbin, extra_args, expected_content_length):
+ r = http(
+ '--offline',
+ 'OPTIONS',
+ httpbin + '/anything',
+ *extra_args
+ )
+ assert f'Content-Length: {expected_content_length}' in r
+
+
+@pytest.mark.parametrize('method', ['options', 'Options', 'OPTIONS'])
+def test_options_dropping_redundant_content_length(httpbin, method):
+ r = http(
+ '--offline',
+ method,
+ httpbin + '/anything'
+ )
+ assert 'Content-Length' not in r