.. _nested-multipart-forms: Parsing Nested Multipart Forms ============================== Out of the box, Falcon does not offer official support for parsing nested multipart forms (i.e., where multiple files for a single field are transmitted using a nested ``multipart/mixed`` part). .. note:: Nested multipart forms are considered deprecated according to the `living HTML5 standard `_ and `RFC 7578, Section 4.3 `_. If your app needs to handle nested forms, this can be done in the same fashion as any other part embedded in the form -- by installing an appropriate media handler. Let us extend the multipart form parser :attr:`media handlers ` to recursively parse embedded forms of the ``multipart/mixed`` content type: .. code:: python import falcon import falcon.media parser = falcon.media.MultipartFormHandler() parser.parse_options.media_handlers['multipart/mixed'] = ( falcon.media.MultipartFormHandler()) .. note:: Here we create a new parser (with default options) for nested parts, effectively disallowing further recursion. If traversing into even deeper multipart form hierarchy is desired, we can just reuse the same parser. Let us now use the nesting-aware parser in an app: .. code:: python import falcon import falcon.media class Forms: def on_post(self, req, resp): example = {} for part in req.media: if part.content_type.startswith('multipart/mixed'): for nested in part.media: example[nested.filename] = nested.text resp.media = example parser = falcon.media.MultipartFormHandler() parser.parse_options.media_handlers['multipart/mixed'] = ( falcon.media.MultipartFormHandler()) app = falcon.App() app.req_options.media_handlers[falcon.MEDIA_MULTIPART] = parser app.add_route('/forms', Forms()) We should now be able to consume a form containing a nested ``multipart/mixed`` part (the example is adapted from the now-obsolete `RFC 1867 `_):: --AaB03x Content-Disposition: form-data; name="field1" Joe Blow --AaB03x Content-Disposition: form-data; name="docs" Content-Type: multipart/mixed; boundary=BbC04y --BbC04y Content-Disposition: attachment; filename="file1.txt" This is file1. --BbC04y Content-Disposition: attachment; filename="file2.txt" Hello, World! --BbC04y-- --AaB03x-- Note that all line endings in the form above are assumed to be CRLF. The form should be ``POST``\ed with the ``Content-Type`` header set to ``multipart/form-data; boundary=AaB03x``.