Multipart Form Parser
Hard · Parsing
HTML forms with file uploads send multipart/form-data, which packages like multer and busboy parse in Node. The body is made of parts separated by a boundary string chosen by the browser (it is in the Content-Type header, for example multipart/form-data; boundary=XyZ).
Write parseMultipart(body, boundary) for a simplified, text-only version. All line breaks are \r\n.
- The first delimiter is --<boundary>, either at the very start of the body or at the start of a line. Text before it (the preamble) is ignored.
- Every later delimiter is \r\n--<boundary>: the \r\n in front belongs to the delimiter, not to the content. The closing delimiter is --<boundary>--, and everything after it (the epilogue) is ignored.
- After a normal delimiter comes \r\n, then the part: header lines, an empty line, then the content up to the next delimiter.
- Header names are case-insensitive and values are trimmed. Content-Disposition looks like form-data; name="field"; filename="a.txt". Parameter names are case-insensitive. A parameter value is either quoted (it may contain ; and spaces, and \" stands for a quote) or a plain token without spaces or ;.
- A part with a filename parameter (even an empty one) is a file: add { field, filename, contentType, content } to files. contentType comes from the part's Content-Type header and defaults to "text/plain" (the default in RFC 7578).
- Other parts are fields: fields[name] = content. If the same name appears again, the value becomes an array of all its values in order. Parts without a name are skipped.
- If the closing delimiter is missing, or a delimiter is followed by something other than \r\n or --, return { error: "Unexpected end of form" }.
Otherwise return { fields, files }.