mirror of
https://github.com/httpie/cli.git
synced 2025-06-25 12:01:41 +02:00
Make sure session and default headers play nice
Before: headers = default + args + session Now: headers = default + session + args Fixes #180
This commit is contained in:
parent
3e1b62fb20
commit
858555abb5
@ -1246,6 +1246,7 @@ Changelog
|
|||||||
* Added ``--cert`` and ``--certkey`` parameters to specify a client side
|
* Added ``--cert`` and ``--certkey`` parameters to specify a client side
|
||||||
certificate and private key for SSL
|
certificate and private key for SSL
|
||||||
* Improved unicode support.
|
* Improved unicode support.
|
||||||
|
* Fixed ``User-Agent`` overwriting when used within a session.
|
||||||
* Switched from ``unittest`` to ``pytest``.
|
* Switched from ``unittest`` to ``pytest``.
|
||||||
* Various test suite improvements.
|
* Various test suite improvements.
|
||||||
* Added `CONTRIBUTING`_.
|
* Added `CONTRIBUTING`_.
|
||||||
|
@ -18,26 +18,27 @@ DEFAULT_UA = 'HTTPie/%s' % __version__
|
|||||||
def get_response(args, config_dir):
|
def get_response(args, config_dir):
|
||||||
"""Send the request and return a `request.Response`."""
|
"""Send the request and return a `request.Response`."""
|
||||||
|
|
||||||
requests_kwargs = get_requests_kwargs(args)
|
|
||||||
|
|
||||||
if args.debug:
|
|
||||||
sys.stderr.write('\n>>> requests.request(%s)\n\n'
|
|
||||||
% pformat(requests_kwargs))
|
|
||||||
|
|
||||||
if not args.session and not args.session_read_only:
|
if not args.session and not args.session_read_only:
|
||||||
|
requests_kwargs = get_requests_kwargs(args)
|
||||||
|
if args.debug:
|
||||||
|
dump_request(requests_kwargs)
|
||||||
response = requests.request(**requests_kwargs)
|
response = requests.request(**requests_kwargs)
|
||||||
else:
|
else:
|
||||||
response = sessions.get_response(
|
response = sessions.get_response(
|
||||||
args=args,
|
args=args,
|
||||||
config_dir=config_dir,
|
config_dir=config_dir,
|
||||||
session_name=args.session or args.session_read_only,
|
session_name=args.session or args.session_read_only,
|
||||||
requests_kwargs=requests_kwargs,
|
|
||||||
read_only=bool(args.session_read_only),
|
read_only=bool(args.session_read_only),
|
||||||
)
|
)
|
||||||
|
|
||||||
return response
|
return response
|
||||||
|
|
||||||
|
|
||||||
|
def dump_request(kwargs):
|
||||||
|
sys.stderr.write('\n>>> requests.request(%s)\n\n'
|
||||||
|
% pformat(kwargs))
|
||||||
|
|
||||||
|
|
||||||
def encode_headers(headers):
|
def encode_headers(headers):
|
||||||
# This allows for unicode headers which is non-standard but practical.
|
# This allows for unicode headers which is non-standard but practical.
|
||||||
# See: https://github.com/jakubroztocil/httpie/issues/212
|
# See: https://github.com/jakubroztocil/httpie/issues/212
|
||||||
@ -47,36 +48,47 @@ def encode_headers(headers):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def get_requests_kwargs(args):
|
def get_default_headers(args):
|
||||||
"""Translate our `args` into `requests.request` keyword arguments."""
|
default_headers = {
|
||||||
|
|
||||||
implicit_headers = {
|
|
||||||
'User-Agent': DEFAULT_UA
|
'User-Agent': DEFAULT_UA
|
||||||
}
|
}
|
||||||
|
|
||||||
auto_json = args.data and not args.form
|
auto_json = args.data and not args.form
|
||||||
# FIXME: Accept is set to JSON with `http url @./file.txt`.
|
# FIXME: Accept is set to JSON with `http url @./file.txt`.
|
||||||
if args.json or auto_json:
|
if args.json or auto_json:
|
||||||
implicit_headers['Accept'] = 'application/json'
|
default_headers['Accept'] = 'application/json'
|
||||||
if args.json or (auto_json and args.data):
|
if args.json or (auto_json and args.data):
|
||||||
implicit_headers['Content-Type'] = JSON
|
default_headers['Content-Type'] = JSON
|
||||||
|
|
||||||
if isinstance(args.data, dict):
|
|
||||||
if args.data:
|
|
||||||
args.data = json.dumps(args.data)
|
|
||||||
else:
|
|
||||||
# We need to set data to an empty string to prevent requests
|
|
||||||
# from assigning an empty list to `response.request.data`.
|
|
||||||
args.data = ''
|
|
||||||
|
|
||||||
elif args.form and not args.files:
|
elif args.form and not args.files:
|
||||||
# If sending files, `requests` will set
|
# If sending files, `requests` will set
|
||||||
# the `Content-Type` for us.
|
# the `Content-Type` for us.
|
||||||
implicit_headers['Content-Type'] = FORM
|
default_headers['Content-Type'] = FORM
|
||||||
|
return default_headers
|
||||||
|
|
||||||
for name, value in implicit_headers.items():
|
|
||||||
if name not in args.headers:
|
def get_requests_kwargs(args, base_headers=None):
|
||||||
args.headers[name] = value
|
"""
|
||||||
|
Translate our `args` into `requests.request` keyword arguments.
|
||||||
|
|
||||||
|
"""
|
||||||
|
# Serialize JSON data, if needed.
|
||||||
|
data = args.data
|
||||||
|
auto_json = data and not args.form
|
||||||
|
if args.json or auto_json and isinstance(data, dict):
|
||||||
|
if data:
|
||||||
|
data = json.dumps(data)
|
||||||
|
else:
|
||||||
|
# We need to set data to an empty string to prevent requests
|
||||||
|
# from assigning an empty list to `response.request.data`.
|
||||||
|
data = ''
|
||||||
|
|
||||||
|
# Finalize headers.
|
||||||
|
headers = get_default_headers(args)
|
||||||
|
if base_headers:
|
||||||
|
headers.update(base_headers)
|
||||||
|
headers.update(args.headers)
|
||||||
|
headers = encode_headers(headers)
|
||||||
|
|
||||||
credentials = None
|
credentials = None
|
||||||
if args.auth:
|
if args.auth:
|
||||||
@ -87,14 +99,14 @@ def get_requests_kwargs(args):
|
|||||||
if args.cert:
|
if args.cert:
|
||||||
cert = args.cert
|
cert = args.cert
|
||||||
if args.certkey:
|
if args.certkey:
|
||||||
cert = (cert, args.certkey)
|
cert = cert, args.certkey
|
||||||
|
|
||||||
kwargs = {
|
kwargs = {
|
||||||
'stream': True,
|
'stream': True,
|
||||||
'method': args.method.lower(),
|
'method': args.method.lower(),
|
||||||
'url': args.url,
|
'url': args.url,
|
||||||
'headers': encode_headers(args.headers),
|
'headers': headers,
|
||||||
'data': args.data,
|
'data': data,
|
||||||
'verify': {
|
'verify': {
|
||||||
'yes': True,
|
'yes': True,
|
||||||
'no': False
|
'no': False
|
||||||
|
@ -21,21 +21,17 @@ VALID_SESSION_NAME_PATTERN = re.compile('^[a-zA-Z0-9_.-]+$')
|
|||||||
SESSION_IGNORED_HEADER_PREFIXES = ['Content-', 'If-']
|
SESSION_IGNORED_HEADER_PREFIXES = ['Content-', 'If-']
|
||||||
|
|
||||||
|
|
||||||
def get_response(session_name, requests_kwargs, config_dir, args,
|
def get_response(session_name, config_dir, args, read_only=False):
|
||||||
read_only=False):
|
|
||||||
"""Like `client.get_response`, but applies permanent
|
"""Like `client.get_response`, but applies permanent
|
||||||
aspects of the session to the request.
|
aspects of the session to the request.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
from .client import encode_headers
|
from .client import get_requests_kwargs, dump_request
|
||||||
if os.path.sep in session_name:
|
if os.path.sep in session_name:
|
||||||
path = os.path.expanduser(session_name)
|
path = os.path.expanduser(session_name)
|
||||||
else:
|
else:
|
||||||
hostname = (
|
hostname = (args.headers.get('Host', None)
|
||||||
requests_kwargs['headers'].get('Host', None)
|
or urlsplit(args.url).netloc.split('@')[-1])
|
||||||
or urlsplit(requests_kwargs['url']).netloc.split('@')[-1]
|
|
||||||
)
|
|
||||||
|
|
||||||
assert re.match('^[a-zA-Z0-9_.:-]+$', hostname)
|
assert re.match('^[a-zA-Z0-9_.:-]+$', hostname)
|
||||||
|
|
||||||
# host:port => host_port
|
# host:port => host_port
|
||||||
@ -48,13 +44,10 @@ def get_response(session_name, requests_kwargs, config_dir, args,
|
|||||||
session = Session(path)
|
session = Session(path)
|
||||||
session.load()
|
session.load()
|
||||||
|
|
||||||
request_headers = requests_kwargs.get('headers', {})
|
requests_kwargs = get_requests_kwargs(args, base_headers=session.headers)
|
||||||
|
if args.debug:
|
||||||
merged_headers = dict(session.headers)
|
dump_request(requests_kwargs)
|
||||||
merged_headers.update(request_headers)
|
session.update_headers(requests_kwargs['headers'])
|
||||||
requests_kwargs['headers'] = encode_headers(merged_headers)
|
|
||||||
|
|
||||||
session.update_headers(request_headers)
|
|
||||||
|
|
||||||
if args.auth:
|
if args.auth:
|
||||||
session.auth = {
|
session.auth = {
|
||||||
|
@ -137,3 +137,14 @@ class TestSession(SessionTestBase):
|
|||||||
assert (r2.json['headers']['Authorization']
|
assert (r2.json['headers']['Authorization']
|
||||||
== HTTPBasicAuth.make_header(u'test', UNICODE))
|
== HTTPBasicAuth.make_header(u'test', UNICODE))
|
||||||
assert r2.json['headers']['Test'] == UNICODE
|
assert r2.json['headers']['Test'] == UNICODE
|
||||||
|
|
||||||
|
def test_session_default_header_value_overwritten(self):
|
||||||
|
# https://github.com/jakubroztocil/httpie/issues/180
|
||||||
|
r1 = http('--session=test', httpbin('/headers'), 'User-Agent:custom',
|
||||||
|
env=self.env())
|
||||||
|
assert HTTP_OK in r1
|
||||||
|
assert r1.json['headers']['User-Agent'] == 'custom'
|
||||||
|
|
||||||
|
r2 = http('--session=test', httpbin('/headers'), env=self.env())
|
||||||
|
assert HTTP_OK in r2
|
||||||
|
assert r2.json['headers']['User-Agent'] == 'custom'
|
||||||
|
Loading…
x
Reference in New Issue
Block a user