DeterministicESPAsyncWebServer v6.27.1
Zero-allocation, bounded-execution async HTTP server for ESP32
Loading...
Searching...
No Matches
multipart.h
Go to the documentation of this file.
1// Copyright (C) 2026 Douglas Quigg (dstroy0) <dquigg123@gmail.com>
2// SPDX-License-Identifier: AGPL-3.0-or-later
3
4/**
5 * @file multipart.h
6 * @brief In-place multipart/form-data parser (RFC 7578).
7 *
8 * Parses the body already stored in `HttpReq::body[]`. The parser modifies
9 * the body buffer in-place by inserting null terminators, so `part->data`
10 * pointers are valid only while the `HttpReq` lives (before `http_reset()`).
11 *
12 * The scan is length-bounded over `HttpReq::body_len` and matches the full
13 * `\r\n--boundary` delimiter (RFC 2046), so a **binary** part is safe: embedded
14 * NUL bytes and even the raw boundary string inside the payload do not truncate it
15 * (only the true `CRLF--boundary` delimiter ends a part). Read a binary part via
16 * `part->data` + `part->data_len` (the in-place NUL terminator is a convenience for
17 * text parts, not a length).
18 *
19 * **Limitations**
20 * - Maximum parts: `MAX_MULTIPART_PARTS` (default 4).
21 * - Maximum total body size: `BODY_BUF_SIZE` bytes.
22 * - Only `name` and `filename` are extracted from Content-Disposition;
23 * other parameters are ignored.
24 * - Boundary value must be ≤ `MAX_BOUNDARY_LEN` bytes (RFC 2046 cap: 70).
25 *
26 * @author Douglas Quigg (dstroy0)
27 * @date 2026
28 */
29
30#ifndef DETERMINISTICESPASYNCWEBSERVER_MULTIPART_H
31#define DETERMINISTICESPASYNCWEBSERVER_MULTIPART_H
32
33#include "ServerConfig.h"
34#include "network_drivers/presentation/presentation.h" // for HttpReq, http_get_header
35
36// ---------------------------------------------------------------------------
37// Data types
38// ---------------------------------------------------------------------------
39
40/**
41 * @brief One parsed part from a multipart body.
42 *
43 * All char* fields point into the (modified) `HttpReq::body[]` buffer.
44 * They are null-terminated and valid until `http_reset()` is called.
45 */
47{
48 const char *name; ///< Form field name from Content-Disposition, or nullptr.
49 const char *filename; ///< Upload filename from Content-Disposition, or nullptr.
50 const char *type; ///< Content-Type of this part, or nullptr.
51 const char *data; ///< Part body (null-terminated in-place).
52 size_t data_len; ///< Part body length in bytes (not counting the null).
53};
54
55/**
56 * @brief Container for all parsed parts of a multipart body.
57 */
59{
61 int part_count; ///< Number of valid entries in parts[].
62};
63
64// ---------------------------------------------------------------------------
65// Public API
66// ---------------------------------------------------------------------------
67
68/**
69 * @brief Parse the body of @p req as multipart/form-data.
70 *
71 * Reads the boundary from the `Content-Type` header, then scans
72 * `req->body` in-place, null-terminating each part's headers and data.
73 *
74 * @param req Fully-parsed HTTP request (must be in ParseState::PARSE_COMPLETE state).
75 * @param mp Output structure; filled on success.
76 * @return true if at least one part was found, false on parse error.
77 */
78bool multipart_parse(HttpReq *req, Multipart *mp);
79
80/**
81 * @brief Look up a field value across all parsed parts by name.
82 *
83 * Returns the data pointer of the first part whose `name` matches @p field.
84 * Useful for simple form submissions where each field has a unique name.
85 *
86 * @param mp Parsed multipart result.
87 * @param field Form field name to search for.
88 * @return Part data (null-terminated), or nullptr if not found.
89 */
90const char *multipart_get_field(const Multipart *mp, const char *field);
91
92#endif
User-facing configuration for DeterministicESPAsyncWebServer.
#define MAX_MULTIPART_PARTS
Maximum simultaneously parsed multipart parts per request.
const char * multipart_get_field(const Multipart *mp, const char *field)
Look up a field value across all parsed parts by name.
bool multipart_parse(HttpReq *req, Multipart *mp)
Parse the body of req as multipart/form-data.
Definition multipart.cpp:44
Layer 6 (Presentation) - wires the transport ring buffer to the HTTP parser.
Fully-parsed HTTP/1.1 request.
One parsed part from a multipart body.
Definition multipart.h:47
const char * data
Part body (null-terminated in-place).
Definition multipart.h:51
const char * type
Content-Type of this part, or nullptr.
Definition multipart.h:50
size_t data_len
Part body length in bytes (not counting the null).
Definition multipart.h:52
const char * name
Form field name from Content-Disposition, or nullptr.
Definition multipart.h:48
const char * filename
Upload filename from Content-Disposition, or nullptr.
Definition multipart.h:49
Container for all parsed parts of a multipart body.
Definition multipart.h:59
MultipartPart parts[MAX_MULTIPART_PARTS]
Parsed parts.
Definition multipart.h:60
int part_count
Number of valid entries in parts[].
Definition multipart.h:61