Add request.form() for multipart form data and file uploads#2626
Add request.form() for multipart form data and file uploads#2626
Conversation
New Request.form() method that handles both application/x-www-form-urlencoded and multipart/form-data content types with streaming parsing. Features: - Streaming multipart parser that doesn't buffer entire body in memory - Files spill to disk above 1MB threshold via SpooledTemporaryFile - files=False (default) discards file content, files=True stores them - Security limits: max_request_size, max_file_size, max_fields, max_files - FormData container with dict-like access and getlist() for multiple values - UploadedFile class with async read(), seek(), filename, content_type, size - Support for RFC 5987 filename* encoding for international filenames Uses multipart-form-data-conformance test suite for validation.
- Migrate PermissionsDebugView, MessagesDebugView, and CreateTokenView from post_vars() to form() - Add documentation for request.form(), FormData, and UploadedFile classes
|
I just tried this out in a branch of |
|
I had GPT-5.2 Thinking do a code review and got some very useful feedback: https://chatgpt.com/share/6976e7c9-2914-8006-8e82-2d4816b3ced1 The summary:
|
…eption (#2627) * Fix test isolation bug in test_startup_error_from_plugin_is_click_exception The test creates a plugin that raises StartupError("boom") and registers it in the global plugin manager (pm). Without cleanup, this plugin leaks to subsequent tests, causing test_setting_boolean_validation_false_values to fail with "Error: boom" instead of "Forbidden". Add try/finally block to ensure the plugin is unregistered after the test completes, following the established cleanup pattern used elsewhere in the test suite. * Fix blacken-docs formatting in plugin_hooks.rst Apply blacken-docs formatting to code example that exceeded the 60 character line limit. --------- Co-authored-by: Claude <noreply@anthropic.com>
Centralize multipart defaults and expose stricter limits via Request.form(). Enforce header, part, file, and disk space limits even when files are discarded; detect truncated bodies and client disconnects; and move blocking work off the event loop. Add FormData close/aclose context managers, update internals docs, and expand multipart tests (including len semantics and stricter conformance expectations).
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #2626 +/- ##
=======================================
Coverage ? 90.37%
=======================================
Files ? 52
Lines ? 7983
Branches ? 0
=======================================
Hits ? 7215
Misses ? 768
Partials ? 0 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
|
The failing test only affects SQLite 3.25.3 and only for Python 3.10 and 3.12. |
|
Retrying in CI caused it to pass, so this is a flaky test. |
| async def flush_batch() -> None: | ||
| if batch: | ||
| data = bytes(batch) | ||
| batch.clear() | ||
| await asyncio.to_thread(parser.feed, data) |
There was a problem hiding this comment.
This is the bit that runs the parsing code in a thread (the MultipartParser class uses blocking methods throughout, but gets run in a thread here.)
|
Fingers crossed that fixed the flaky tests! Gonna land this now and ship it in an alpha. |
New Request.form() method that handles both application/x-www-form-urlencoded
and multipart/form-data content types with streaming parsing.
Features:
Uses multipart-form-data-conformance test suite for validation.
📚 Documentation preview 📚: https://datasette--2626.org.readthedocs.build/en/2626/