2020-08-15 17:50:00 +02:00
|
|
|
from typing import Tuple, Union
|
|
|
|
|
2020-09-25 13:44:28 +02:00
|
|
|
from requests.utils import super_len
|
2020-08-15 17:50:00 +02:00
|
|
|
from requests_toolbelt import MultipartEncoder
|
|
|
|
|
2020-08-19 10:22:42 +02:00
|
|
|
from httpie.cli.dicts import RequestDataDict, RequestFilesDict
|
|
|
|
|
2020-08-15 17:50:00 +02:00
|
|
|
|
|
|
|
# Multipart uploads smaller than this size gets buffered (otherwise streamed).
|
|
|
|
# NOTE: Unbuffered upload requests cannot be displayed on the terminal.
|
2020-09-25 14:44:22 +02:00
|
|
|
MULTIPART_UPLOAD_BUFFER = 1024 * 1000
|
2020-08-15 17:50:00 +02:00
|
|
|
|
|
|
|
|
2020-08-19 10:22:42 +02:00
|
|
|
def get_multipart_data_and_content_type(
|
2020-08-15 17:50:00 +02:00
|
|
|
data: RequestDataDict,
|
2020-08-19 10:22:42 +02:00
|
|
|
files: RequestFilesDict,
|
|
|
|
boundary: str = None,
|
|
|
|
content_type: str = None,
|
2020-08-15 17:50:00 +02:00
|
|
|
) -> Tuple[Union[MultipartEncoder, bytes], str]:
|
|
|
|
fields = list(data.items()) + list(files.items())
|
2020-08-19 10:22:42 +02:00
|
|
|
encoder = MultipartEncoder(
|
|
|
|
fields=fields,
|
|
|
|
boundary=boundary,
|
|
|
|
)
|
|
|
|
if content_type:
|
|
|
|
content_type = content_type.strip() # maybe auto-strip all headers somewhere
|
|
|
|
if 'boundary=' not in content_type:
|
|
|
|
content_type = f'{content_type}; boundary={encoder.boundary_value}'
|
|
|
|
else:
|
|
|
|
content_type = encoder.content_type
|
|
|
|
|
2020-09-25 14:46:19 +02:00
|
|
|
data = encoder.to_string() if 0 and encoder.len < MULTIPART_UPLOAD_BUFFER else encoder
|
2020-08-15 17:50:00 +02:00
|
|
|
return data, content_type
|
2020-09-25 13:44:28 +02:00
|
|
|
|
|
|
|
|
|
|
|
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
|