mirror of
https://github.com/httpie/cli.git
synced 2025-06-26 12:31:47 +02:00
parent
5754e33a75
commit
684a4708d7
@ -8,6 +8,7 @@ This project adheres to `Semantic Versioning <https://semver.org/>`_.
|
|||||||
|
|
||||||
`2.1.0-dev`_ (unreleased)
|
`2.1.0-dev`_ (unreleased)
|
||||||
-------------------------
|
-------------------------
|
||||||
|
* Add ``--path-as-is`` to bypass dot segment (``/../`` or ``/./``) URL squashing.
|
||||||
* Fixed ``--form`` file upload mixed with redirected ``stdin`` error handling.
|
* Fixed ``--form`` file upload mixed with redirected ``stdin`` error handling.
|
||||||
|
|
||||||
|
|
||||||
|
@ -552,6 +552,15 @@ network.add_argument(
|
|||||||
|
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
|
network.add_argument(
|
||||||
|
'--path-as-is',
|
||||||
|
default=False,
|
||||||
|
action='store_true',
|
||||||
|
help="""
|
||||||
|
Bypass dot segment (/../ or /./) URL squashing.
|
||||||
|
|
||||||
|
"""
|
||||||
|
)
|
||||||
|
|
||||||
#######################################################################
|
#######################################################################
|
||||||
# SSL
|
# SSL
|
||||||
|
@ -6,6 +6,7 @@ import zlib
|
|||||||
from contextlib import contextmanager
|
from contextlib import contextmanager
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Iterable, Union
|
from typing import Iterable, Union
|
||||||
|
from urllib.parse import urlparse, urlunparse
|
||||||
|
|
||||||
import requests
|
import requests
|
||||||
from requests.adapters import HTTPAdapter
|
from requests.adapters import HTTPAdapter
|
||||||
@ -77,6 +78,11 @@ def collect_messages(
|
|||||||
|
|
||||||
request = requests.Request(**request_kwargs)
|
request = requests.Request(**request_kwargs)
|
||||||
prepared_request = requests_session.prepare_request(request)
|
prepared_request = requests_session.prepare_request(request)
|
||||||
|
if args.path_as_is:
|
||||||
|
prepared_request.url = ensure_path_as_is(
|
||||||
|
orig_url=args.url,
|
||||||
|
prepped_url=prepared_request.url,
|
||||||
|
)
|
||||||
if args.compress and prepared_request.body:
|
if args.compress and prepared_request.body:
|
||||||
compress_body(prepared_request, always=args.compress > 1)
|
compress_body(prepared_request, always=args.compress > 1)
|
||||||
response_count = 0
|
response_count = 0
|
||||||
@ -278,3 +284,30 @@ def make_request_kwargs(
|
|||||||
}
|
}
|
||||||
|
|
||||||
return kwargs
|
return kwargs
|
||||||
|
|
||||||
|
|
||||||
|
def ensure_path_as_is(orig_url: str, prepped_url: str) -> str:
|
||||||
|
"""
|
||||||
|
Handle `--path-as-is` by replacing the path component of the prepared
|
||||||
|
URL with the path component from the original URL. Other parts stay
|
||||||
|
untouched because other (welcome) processing on the URL might have
|
||||||
|
taken place.
|
||||||
|
|
||||||
|
<https://github.com/jakubroztocil/httpie/issues/895>
|
||||||
|
|
||||||
|
|
||||||
|
<https://ec.haxx.se/http/http-basics#path-as-is>
|
||||||
|
<https://curl.haxx.se/libcurl/c/CURLOPT_PATH_AS_IS.html>
|
||||||
|
|
||||||
|
>>> ensure_path_as_is('http://foo/../', 'http://foo/?foo=bar')
|
||||||
|
'http://foo/../?foo=bar'
|
||||||
|
|
||||||
|
"""
|
||||||
|
parsed_orig, parsed_prepped = urlparse(orig_url), urlparse(prepped_url)
|
||||||
|
final_dict = {
|
||||||
|
# noinspection PyProtectedMember
|
||||||
|
**parsed_prepped._asdict(),
|
||||||
|
'path': parsed_orig.path,
|
||||||
|
}
|
||||||
|
final_url = urlunparse(tuple(final_dict.values()))
|
||||||
|
return final_url
|
||||||
|
@ -55,6 +55,25 @@ def test_GET(httpbin_both):
|
|||||||
assert HTTP_OK in r
|
assert HTTP_OK in r
|
||||||
|
|
||||||
|
|
||||||
|
def test_path_dot_normalization():
|
||||||
|
r = http(
|
||||||
|
'--offline',
|
||||||
|
'example.org/../../etc/password',
|
||||||
|
'param==value'
|
||||||
|
)
|
||||||
|
assert 'GET /etc/password?param=value' in r
|
||||||
|
|
||||||
|
|
||||||
|
def test_path_as_is():
|
||||||
|
r = http(
|
||||||
|
'--offline',
|
||||||
|
'--path-as-is',
|
||||||
|
'example.org/../../etc/password',
|
||||||
|
'param==value'
|
||||||
|
)
|
||||||
|
assert 'GET /../../etc/password?param=value' in r
|
||||||
|
|
||||||
|
|
||||||
def test_DELETE(httpbin_both):
|
def test_DELETE(httpbin_both):
|
||||||
r = http('DELETE', httpbin_both + '/delete')
|
r = http('DELETE', httpbin_both + '/delete')
|
||||||
assert HTTP_OK in r
|
assert HTTP_OK in r
|
||||||
|
Loading…
x
Reference in New Issue
Block a user