forked from extern/httpie-cli
WIP
This commit is contained in:
parent
c431ed7728
commit
d12af4a569
@ -15,12 +15,10 @@ from httpie.cli.argtypes import (
|
||||
parse_format_options,
|
||||
)
|
||||
from httpie.cli.constants import (
|
||||
DEFAULT_FORMAT_OPTIONS, HTTP_GET, HTTP_POST, OUTPUT_OPTIONS,
|
||||
OUTPUT_OPTIONS_DEFAULT,
|
||||
OUTPUT_OPTIONS_DEFAULT_STDOUT_REDIRECTED, OUT_RESP_BODY, PRETTY_MAP,
|
||||
PRETTY_STDOUT_TTY_ONLY, SEPARATOR_CREDENTIALS, SEPARATOR_GROUP_ALL_ITEMS,
|
||||
SEPARATOR_GROUP_DATA_ITEMS, URL_SCHEME_RE,
|
||||
OUTPUT_OPTIONS_DEFAULT_OFFLINE,
|
||||
HTTP_GET, HTTP_POST, OUTPUT_OPTIONS, OUTPUT_OPTIONS_DEFAULT,
|
||||
OUTPUT_OPTIONS_DEFAULT_OFFLINE, OUTPUT_OPTIONS_DEFAULT_STDOUT_REDIRECTED,
|
||||
OUT_RESP_BODY, PRETTY_MAP, PRETTY_STDOUT_TTY_ONLY, SEPARATOR_CREDENTIALS,
|
||||
SEPARATOR_GROUP_ALL_ITEMS, SEPARATOR_GROUP_DATA_ITEMS, URL_SCHEME_RE,
|
||||
)
|
||||
from httpie.cli.exceptions import ParseError
|
||||
from httpie.cli.requestitems import RequestItems
|
||||
@ -165,7 +163,8 @@ class HTTPieArgumentParser(argparse.ArgumentParser):
|
||||
|
||||
if self.args.quiet:
|
||||
self.env.stderr = self.env.devnull
|
||||
if not (self.args.output_file_specified and not self.args.download):
|
||||
if not (
|
||||
self.args.output_file_specified and not self.args.download):
|
||||
self.env.stdout = self.env.devnull
|
||||
|
||||
def _process_auth(self):
|
||||
@ -193,8 +192,8 @@ class HTTPieArgumentParser(argparse.ArgumentParser):
|
||||
plugin = plugin_manager.get_auth_plugin(self.args.auth_type)()
|
||||
|
||||
if (not self.args.ignore_netrc
|
||||
and self.args.auth is None
|
||||
and plugin.netrc_parse):
|
||||
and self.args.auth is None
|
||||
and plugin.netrc_parse):
|
||||
# Only host needed, so it’s OK URL not finalized.
|
||||
netrc_credentials = get_netrc_auth(self.args.url)
|
||||
if netrc_credentials:
|
||||
@ -222,7 +221,7 @@ class HTTPieArgumentParser(argparse.ArgumentParser):
|
||||
credentials = parse_auth(self.args.auth)
|
||||
|
||||
if (not credentials.has_password()
|
||||
and plugin.prompt_password):
|
||||
and plugin.prompt_password):
|
||||
if self.args.ignore_stdin:
|
||||
# Non-tty stdin read by now
|
||||
self.error(
|
||||
@ -276,7 +275,13 @@ class HTTPieArgumentParser(argparse.ArgumentParser):
|
||||
'data (key=value) cannot be mixed. Pass '
|
||||
'--ignore-stdin to let key/value take priority. '
|
||||
'See https://httpie.org/doc#scripting for details.')
|
||||
self.args.data = getattr(fd, 'buffer', fd).read()
|
||||
buffer = getattr(fd, 'buffer', fd)
|
||||
# if fd is self.env.stdin and not self.args.chunked:
|
||||
# self.args.data = buffer.read()
|
||||
# else:
|
||||
# self.args.data = buffer
|
||||
# print(type(fd))
|
||||
self.args.data = buffer
|
||||
|
||||
def _guess_method(self):
|
||||
"""Set `args.method` if not specified to either POST or GET
|
||||
@ -312,8 +317,8 @@ class HTTPieArgumentParser(argparse.ArgumentParser):
|
||||
has_data = (
|
||||
self.has_stdin_data
|
||||
or any(
|
||||
item.sep in SEPARATOR_GROUP_DATA_ITEMS
|
||||
for item in self.args.request_items)
|
||||
item.sep in SEPARATOR_GROUP_DATA_ITEMS
|
||||
for item in self.args.request_items)
|
||||
)
|
||||
self.args.method = HTTP_POST if has_data else HTTP_GET
|
||||
|
||||
@ -416,11 +421,12 @@ class HTTPieArgumentParser(argparse.ArgumentParser):
|
||||
if self.args.download_resume:
|
||||
self.error('--continue only works with --download')
|
||||
if self.args.download_resume and not (
|
||||
self.args.download and self.args.output_file):
|
||||
self.args.download and self.args.output_file):
|
||||
self.error('--continue requires --output to be specified')
|
||||
|
||||
def _process_format_options(self):
|
||||
parsed_options = PARSED_DEFAULT_FORMAT_OPTIONS
|
||||
for options_group in self.args.format_options or []:
|
||||
parsed_options = parse_format_options(options_group, defaults=parsed_options)
|
||||
parsed_options = parse_format_options(options_group,
|
||||
defaults=parsed_options)
|
||||
self.args.format_options = parsed_options
|
||||
|
@ -657,6 +657,15 @@ network.add_argument(
|
||||
'''
|
||||
)
|
||||
|
||||
network.add_argument(
|
||||
'--chunked',
|
||||
default=False,
|
||||
action='store_true',
|
||||
help="""
|
||||
|
||||
"""
|
||||
)
|
||||
|
||||
#######################################################################
|
||||
# SSL
|
||||
#######################################################################
|
||||
|
@ -5,7 +5,7 @@ import sys
|
||||
import zlib
|
||||
from contextlib import contextmanager
|
||||
from pathlib import Path
|
||||
from typing import Iterable, Union
|
||||
from typing import Callable, Iterable, Union
|
||||
from urllib.parse import urlparse, urlunparse
|
||||
|
||||
import requests
|
||||
@ -16,7 +16,10 @@ from httpie.cli.dicts import RequestHeadersDict
|
||||
from httpie.plugins.registry import plugin_manager
|
||||
from httpie.sessions import get_httpie_session
|
||||
from httpie.ssl import AVAILABLE_SSL_VERSION_ARG_MAPPING, HTTPieHTTPSAdapter
|
||||
from httpie.uploads import get_multipart_data_and_content_type
|
||||
from httpie.uploads import (
|
||||
wrap_request_data,
|
||||
get_multipart_data_and_content_type,
|
||||
)
|
||||
from httpie.utils import get_expired_cookies, repr_dict
|
||||
|
||||
|
||||
@ -31,6 +34,7 @@ DEFAULT_UA = f'HTTPie/{__version__}'
|
||||
def collect_messages(
|
||||
args: argparse.Namespace,
|
||||
config_dir: Path,
|
||||
body_chunk_sent_callback: Callable[[bytes], None]=None,
|
||||
) -> Iterable[Union[requests.PreparedRequest, requests.Response]]:
|
||||
httpie_session = None
|
||||
httpie_session_headers = None
|
||||
@ -46,6 +50,7 @@ def collect_messages(
|
||||
request_kwargs = make_request_kwargs(
|
||||
args=args,
|
||||
base_headers=httpie_session_headers,
|
||||
callback=body_chunk_sent_callback
|
||||
)
|
||||
send_kwargs = make_send_kwargs(args)
|
||||
send_kwargs_mergeable_from_env = make_send_kwargs_mergeable_from_env(args)
|
||||
@ -251,7 +256,8 @@ def make_send_kwargs_mergeable_from_env(args: argparse.Namespace) -> dict:
|
||||
|
||||
def make_request_kwargs(
|
||||
args: argparse.Namespace,
|
||||
base_headers: RequestHeadersDict = None
|
||||
base_headers: RequestHeadersDict = None,
|
||||
callback=lambda chunk: chunk
|
||||
) -> dict:
|
||||
"""
|
||||
Translate our `args` into `requests.Request` keyword arguments.
|
||||
@ -289,7 +295,7 @@ def make_request_kwargs(
|
||||
'method': args.method.lower(),
|
||||
'url': args.url,
|
||||
'headers': headers,
|
||||
'data': data,
|
||||
'data': wrap_request_data(data, callback=callback),
|
||||
'auth': args.auth,
|
||||
'params': args.params,
|
||||
'files': files,
|
||||
|
@ -9,6 +9,10 @@ from pygments import __version__ as pygments_version
|
||||
from requests import __version__ as requests_version
|
||||
|
||||
from httpie import __version__ as httpie_version
|
||||
from httpie.cli.constants import (
|
||||
OUT_REQ_BODY, OUT_REQ_HEAD, OUT_RESP_BODY,
|
||||
OUT_RESP_HEAD,
|
||||
)
|
||||
from httpie.client import collect_messages
|
||||
from httpie.context import Environment
|
||||
from httpie.downloads import Downloader
|
||||
@ -111,6 +115,22 @@ def main(
|
||||
return exit_status
|
||||
|
||||
|
||||
def get_output_options(
|
||||
args: argparse.Namespace,
|
||||
message: Union[requests.PreparedRequest, requests.Response]
|
||||
) -> dict:
|
||||
return {
|
||||
requests.PreparedRequest: {
|
||||
'with_headers': OUT_REQ_HEAD in args.output_options,
|
||||
'with_body': OUT_REQ_BODY in args.output_options,
|
||||
},
|
||||
requests.Response: {
|
||||
'with_headers': OUT_RESP_HEAD in args.output_options,
|
||||
'with_body': OUT_RESP_BODY in args.output_options,
|
||||
},
|
||||
}[type(message)]
|
||||
|
||||
|
||||
def program(
|
||||
args: argparse.Namespace,
|
||||
env: Environment,
|
||||
@ -135,15 +155,36 @@ def program(
|
||||
initial_request = None
|
||||
final_response = None
|
||||
|
||||
for message in collect_messages(args, env.config.directory):
|
||||
write_message(
|
||||
requests_message=message,
|
||||
env=env,
|
||||
args=args,
|
||||
)
|
||||
if isinstance(message, requests.PreparedRequest):
|
||||
def upload_callback(chunk):
|
||||
print('GOT', chunk)
|
||||
|
||||
messages = collect_messages(
|
||||
args=args,
|
||||
config_dir=env.config.directory,
|
||||
body_chunk_sent_callback=upload_callback
|
||||
)
|
||||
for message in messages:
|
||||
is_request = isinstance(message, requests.PreparedRequest)
|
||||
output_options = get_output_options(args=args, message=message)
|
||||
if not is_request or not output_options['with_body']:
|
||||
write_message(
|
||||
requests_message=message,
|
||||
env=env,
|
||||
args=args,
|
||||
**output_options,
|
||||
)
|
||||
if is_request:
|
||||
if not initial_request:
|
||||
initial_request = message
|
||||
if 0and not args.offline:
|
||||
output_options['with_body'] = False
|
||||
write_message(
|
||||
requests_message=message,
|
||||
env=env,
|
||||
args=args,
|
||||
**output_options,
|
||||
)
|
||||
|
||||
else:
|
||||
final_response = message
|
||||
if args.check_status or downloader:
|
||||
|
@ -23,6 +23,13 @@ LARGE_UPLOAD_SUPPRESSED_NOTICE = (
|
||||
)
|
||||
|
||||
|
||||
def might_suppress(chunk):
|
||||
if isinstance(chunk, MultipartEncoder):
|
||||
raise LargeUploadSuppressedError()
|
||||
# if isinstance(io.IOBase):
|
||||
# pass
|
||||
|
||||
|
||||
class DataSuppressedError(Exception):
|
||||
message = None
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
import argparse
|
||||
import errno
|
||||
from typing import Union, IO, TextIO, Tuple, Type
|
||||
from typing import IO, TextIO, Tuple, Type, Union
|
||||
|
||||
import requests
|
||||
|
||||
@ -8,12 +8,7 @@ from httpie.context import Environment
|
||||
from httpie.models import HTTPRequest, HTTPResponse
|
||||
from httpie.output.processing import Conversion, Formatting
|
||||
from httpie.output.streams import (
|
||||
RawStream, PrettyStream,
|
||||
BufferedPrettyStream, EncodedStream,
|
||||
BaseStream,
|
||||
)
|
||||
from httpie.cli.constants import (
|
||||
OUT_REQ_BODY, OUT_REQ_HEAD, OUT_RESP_BODY, OUT_RESP_HEAD,
|
||||
BaseStream, BufferedPrettyStream, EncodedStream, PrettyStream, RawStream,
|
||||
)
|
||||
|
||||
|
||||
@ -21,26 +16,18 @@ def write_message(
|
||||
requests_message: Union[requests.PreparedRequest, requests.Response],
|
||||
env: Environment,
|
||||
args: argparse.Namespace,
|
||||
with_headers=False,
|
||||
with_body=False,
|
||||
):
|
||||
output_options_by_message_type = {
|
||||
requests.PreparedRequest: {
|
||||
'with_headers': OUT_REQ_HEAD in args.output_options,
|
||||
'with_body': OUT_REQ_BODY in args.output_options,
|
||||
},
|
||||
requests.Response: {
|
||||
'with_headers': OUT_RESP_HEAD in args.output_options,
|
||||
'with_body': OUT_RESP_BODY in args.output_options,
|
||||
},
|
||||
}
|
||||
output_options = output_options_by_message_type[type(requests_message)]
|
||||
if not any(output_options.values()):
|
||||
if not (with_body or with_headers):
|
||||
return
|
||||
write_stream_kwargs = {
|
||||
'stream': build_output_stream_for_message(
|
||||
args=args,
|
||||
env=env,
|
||||
requests_message=requests_message,
|
||||
**output_options,
|
||||
with_body=with_body,
|
||||
with_headers=with_headers,
|
||||
),
|
||||
# NOTE: `env.stdout` will in fact be `stderr` with `--download`
|
||||
'outfile': env.stdout,
|
||||
|
@ -1,5 +1,6 @@
|
||||
from typing import Tuple, Union
|
||||
|
||||
from requests.utils import super_len
|
||||
from requests_toolbelt import MultipartEncoder
|
||||
|
||||
from httpie.cli.dicts import RequestDataDict, RequestFilesDict
|
||||
@ -28,5 +29,40 @@ def get_multipart_data_and_content_type(
|
||||
else:
|
||||
content_type = encoder.content_type
|
||||
|
||||
data = encoder.to_string() if encoder.len < UPLOAD_BUFFER else encoder
|
||||
data = encoder.to_string() if 0 and encoder.len < UPLOAD_BUFFER else encoder
|
||||
return data, content_type
|
||||
|
||||
|
||||
class Stdin:
|
||||
|
||||
def __init__(self, stdin, callback):
|
||||
self.callback = callback
|
||||
self.stdin = stdin
|
||||
|
||||
def __iter__(self):
|
||||
for chunk in self.stdin:
|
||||
print("__iter__() =>", chunk)
|
||||
self.callback(chunk)
|
||||
yield chunk
|
||||
|
||||
@classmethod
|
||||
def is_stdin(cls, obj):
|
||||
return super_len(obj) == 0
|
||||
|
||||
|
||||
def wrap_request_data(data, callback=lambda chunk: print('chunk', chunk)):
|
||||
if hasattr(data, 'read'):
|
||||
if Stdin.is_stdin(data):
|
||||
data = Stdin(data, callback=callback)
|
||||
else:
|
||||
orig_read = data.read
|
||||
|
||||
def new_read(*args):
|
||||
val = orig_read(*args)
|
||||
print('read() =>', val)
|
||||
callback(callback)
|
||||
return val
|
||||
|
||||
data.read = new_read
|
||||
|
||||
return data
|
||||
|
@ -1,5 +1,6 @@
|
||||
"""High-level tests."""
|
||||
import io
|
||||
import sys
|
||||
from unittest import mock
|
||||
|
||||
import pytest
|
||||
|
Loading…
Reference in New Issue
Block a user