fix(upload): preserve fields in multipart fallback
Build and Push Docker Container / build-and-push (push) Successful in 1m40s
Build and Push Docker Container / build-and-push (push) Successful in 1m40s
- Recover regular multipart fields when the file part is not exposed through request.files. - Preserve expires and note values for browser uploads that need body-based file recovery. - Add parser coverage for file parts without filenames and recovered expiry fields. - Extend upload route tests to assert recovered uploads keep expiry metadata. - Bump NanoShare to 1.27.3.
This commit is contained in:
@@ -40,9 +40,15 @@ class AwaitableValue:
|
||||
return get_value().__await__()
|
||||
|
||||
class FakeRequest:
|
||||
def __init__(self, form, files):
|
||||
def __init__(self, form, files, body=b'', boundary=None):
|
||||
self.form = AwaitableValue(form)
|
||||
self.files = AwaitableValue(files)
|
||||
self.mimetype = 'multipart/form-data' if boundary else ''
|
||||
self.mimetype_params = {'boundary': boundary} if boundary else {}
|
||||
self._body = body
|
||||
|
||||
async def get_data(self, cache=True):
|
||||
return self._body
|
||||
|
||||
class FakeConvex:
|
||||
def __init__(self):
|
||||
@@ -91,5 +97,50 @@ def test_upload_accepts_file_field_without_filename(monkeypatch):
|
||||
assert await response.get_json() == {'ok': True}
|
||||
assert app.convex.sent == [(b'hello', 'application/octet-stream')]
|
||||
assert app.convex.files[0]['file_name'].endswith('.bin')
|
||||
assert app.convex.files[0]['expires_at'] is not None
|
||||
|
||||
asyncio.run(run_test())
|
||||
|
||||
def test_upload_recovers_file_field_from_multipart_body(monkeypatch):
|
||||
async def run_test():
|
||||
upload = load_upload_module(monkeypatch)
|
||||
|
||||
app = Quart(__name__)
|
||||
app.secret_key = 'test-secret'
|
||||
app.convex = FakeConvex()
|
||||
app.orphan_storage_registry = None
|
||||
|
||||
boundary = '----nanoshare-test-boundary'
|
||||
body = (
|
||||
f'--{boundary}\r\n'
|
||||
'Content-Disposition: form-data; name="file"\r\n'
|
||||
'Content-Type: application/octet-stream\r\n'
|
||||
'\r\n'
|
||||
).encode() + b'hello recovered' + (
|
||||
'\r\n'
|
||||
f'--{boundary}\r\n'
|
||||
'Content-Disposition: form-data; name="expires"\r\n'
|
||||
'\r\n'
|
||||
'7d\r\n'
|
||||
f'--{boundary}--\r\n'
|
||||
).encode()
|
||||
|
||||
async with app.test_request_context('/api/upload', method='POST'):
|
||||
session['user'] = {'sub': 'user_1'}
|
||||
fake_request = FakeRequest(
|
||||
form={'expires': '7d', 'note': 'test', 'text': ''},
|
||||
files={},
|
||||
body=body,
|
||||
boundary=boundary,
|
||||
)
|
||||
monkeypatch.setattr(upload, 'request', fake_request)
|
||||
|
||||
response = await upload.api_upload()
|
||||
|
||||
assert await response.get_json() == {'ok': True}
|
||||
assert app.convex.sent == [(b'hello recovered', 'application/octet-stream')]
|
||||
assert app.convex.files[0]['file_name'].endswith('.bin')
|
||||
assert app.convex.files[0]['expires_at'] is not None
|
||||
assert app.convex.files[0]['note'] == 'test'
|
||||
|
||||
asyncio.run(run_test())
|
||||
|
||||
Reference in New Issue
Block a user