diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 26b785f..8b68b33 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -12,7 +12,19 @@ and may break applications that rely on *incorrect* or *undefined* behavior. Release 1.2 =========== -Not released yet. +This release improves error handling and adds new functionality. API changes are +backwards compatible. + +* feat: New `is_form_request(environ)` helper. +* feat: Split up `MultipartError`` into more specific exceptions and added HTTP + status code info to each one. All exceptions are subclasses of `MultipartError`. +* feat: Added `parse_form_data(ignore_errors)` parameter to throw exceptions in + non-strict mode, or suppress exceptions in strict mode. Default behavior does + not change. +* fix: `parse_form_data` no longer checks the request method and `is_form_request` + also ignores it. All methods can carry parse-able form data, including unknown + methods. The only reliable way is to check the `Content-Type` header, which + both functions do. Release 1.1 =========== diff --git a/README.rst b/README.rst index 2649989..909aef2 100644 --- a/README.rst +++ b/README.rst @@ -20,11 +20,12 @@ low-level for framework authors and high-level for WSGI application developers: * ``PushMultipartParser``: A low-level incremental `SansIO `_ (non-blocking) parser suitable for asyncio and other time or memory constrained environments. -* ``MultipartParser``: A streaming parser emitting memory- and disk-buffered +* ``MultipartParser``: A streaming parser emitting memory- or disk-buffered ``MultipartPart`` instances. -* ``parse_form_data``: A helper function to parse both ``multipart/form-data`` - and ``application/x-www-form-urlencoded`` form submissions from a - `WSGI `_ environment. +* ``parse_form_data`` and ``is_form_request``: Helper functions for + `WSGI `_ applications with support for + ``multipart/form-data`` as well as ``application/x-www-form-urlencoded`` form + submission requests. Installation @@ -70,14 +71,14 @@ instances in return, one for text fields and the other for file uploads: .. code-block:: python - from multipart import parse_form_data + from multipart import parse_form_data, is_form_request def wsgi(environ, start_response): - if environ["REQUEST_METHOD"] == "POST": + if is_form_request(environ): forms, files = parse_form_data(environ) - title = forms["title"] # string - upload = files["upload"] # MultipartPart + title = forms["title"] # type: string + upload = files["upload"] # type: MultipartPart upload.save_as(...) Note that form fields that are too large to fit into memory will end up as @@ -129,25 +130,22 @@ allows you to process ``MultipartPart`` instances as soon as they arrive: from multipart import parse_options_header, MultipartParser def wsgi(environ, start_response): - assert environ["REQUEST_METHOD"] == "POST" - - content_type = environ["CONTENT_TYPE"] - content_type, content_params = parse_options_header(content_type) - assert content_type == "multipart/form-data" - - stream = environ["wsgi.input"] - boundary = content_params.get("boundary") - charset = content_params.get("charset", "utf8") - - parser = MultipartParser(stream, boundary, charset) - for part in parser: - if part.filename: - print(f"{part.name}: File upload ({part.size} bytes)") - part.save_as(...) - elif part.size < 1024: - print(f"{part.name}: Text field ({part.value!r})") - else: - print(f"{part.name}: Test field, but too big to print :/") + content_type, params = parse_options_header(environ["CONTENT_TYPE"]) + + if content_type == "multipart/form-data": + stream = environ["wsgi.input"] + boundary = params["boundary"] + charset = params.get("charset", "utf8") + + parser = MultipartParser(stream, boundary, charset) + for part in parser: + if part.filename: + print(f"{part.name}: File upload ({part.size} bytes)") + part.save_as(...) + elif part.size < 1024: + print(f"{part.name}: Text field ({part.value!r})") + else: + print(f"{part.name}: Test field, but too big to print :/") Non-blocking parser: ``PushMultipartParser``