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 media handlers
to recursively
parse embedded forms of the multipart/mixed
content type:
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:
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
.