KEEL 1.0.0
Minimal C11 HTTP client/server library built on epoll/kqueue/io_uring/poll
Loading...
Searching...
No Matches
Data Structures | Macros | Typedefs | Enumerations | Functions
body_reader_multipart.h File Reference
#include <keel/body_reader.h>
#include <keel/request.h>
#include <stddef.h>
Include dependency graph for body_reader_multipart.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  KlMultipartPartMeta
 
struct  KlMultipartConfig
 

Macros

#define KL_MP_MAX_BOUNDARY   70
 Streaming multipart/form-data parser.
 

Typedefs

typedef struct KlMultipartReader KlMultipartReader
 

Enumerations

enum  KlMultipartEvent {
  KL_MP_EVT_PART_BEGIN = 1 , KL_MP_EVT_PART_DATA , KL_MP_EVT_PART_END , KL_MP_EVT_DONE ,
  KL_MP_EVT_NEED_DATA , KL_MP_EVT_ERROR
}
 
enum  KlMultipartErrorCode {
  KL_MP_ERR_NONE = 0 , KL_MP_ERR_MALFORMED , KL_MP_ERR_PART_TOO_LARGE , KL_MP_ERR_TOTAL_TOO_LARGE ,
  KL_MP_ERR_TOO_MANY_PARTS , KL_MP_ERR_HEADERS_TOO_LARGE , KL_MP_ERR_INPUT_OVERFLOW , KL_MP_ERR_PREMATURE_EOF ,
  KL_MP_ERR_NOMEM
}
 

Functions

KlBodyReaderkl_body_reader_multipart (KlAllocator *alloc, const KlRequest *req, void *user_data)
 Factory: produce a streaming multipart reader for a request.
 
KlMultipartEvent kl_multipart_next (KlBodyReader *br, KlMultipartPartMeta *meta, const char **data, size_t *data_len)
 Advance the parser by one event.
 
KlMultipartErrorCode kl_multipart_last_error (const KlBodyReader *br)
 Return the error code for the latest ERROR event.
 

Macro Definition Documentation

◆ KL_MP_MAX_BOUNDARY

#define KL_MP_MAX_BOUNDARY   70

Streaming multipart/form-data parser.

The reader is a pull iterator on top of the framework's push-shaped body callback. Each call to kl_multipart_next() advances the parser by one event:

PART_BEGIN — headers parsed; meta is populated. The pointers in meta are owned by the reader and remain valid until the NEXT call to kl_multipart_next(). PART_DATA — a chunk of the current part body is available. *data / *data_len are populated with a borrowed slice of the internal input buffer. Valid until the next call. PART_END — the current part finished (boundary hit). No data. DONE — the closing boundary was seen. The reader is finished. NEED_DATA — input buffer drained; the caller should yield and wait for more bytes to arrive via on_data. ERROR — malformed input or a cap was exceeded. Call kl_multipart_last_error() for the specific code.

Caps: max_part_size — bytes of body per part. Exceeded → ERROR. max_total_size — total bytes received from the socket. max_parts — distinct parts; counted when PART_BEGIN is emitted. max_input_buffer — bytes the reader may hold internally. Exceeded means the framework delivered data faster than the handler consumed it. 0 = unlimited.

413 mapping: The factory returns NULL for non-multipart content types (→ 415). Any cap overflow during parsing causes kl_multipart_next() to return ERROR; the handler should respond 413. RFC 2046 maximum boundary length.

Typedef Documentation

◆ KlMultipartReader

Opaque reader. Obtain via the factory; consume via kl_multipart_next.

Enumeration Type Documentation

◆ KlMultipartEvent

Events returned by kl_multipart_next().

Enumerator
KL_MP_EVT_PART_BEGIN 
KL_MP_EVT_PART_DATA 
KL_MP_EVT_PART_END 
KL_MP_EVT_DONE 
KL_MP_EVT_NEED_DATA 
KL_MP_EVT_ERROR 

◆ KlMultipartErrorCode

Error codes reported by kl_multipart_last_error().

Enumerator
KL_MP_ERR_NONE 
KL_MP_ERR_MALFORMED 

bad preamble / boundary / header line

KL_MP_ERR_PART_TOO_LARGE 

per-part body cap exceeded

KL_MP_ERR_TOTAL_TOO_LARGE 

total body cap exceeded

KL_MP_ERR_TOO_MANY_PARTS 

max-parts cap exceeded

KL_MP_ERR_HEADERS_TOO_LARGE 

single part's headers exceeded buffer

KL_MP_ERR_INPUT_OVERFLOW 

unconsumed input buffer over cap

KL_MP_ERR_PREMATURE_EOF 

on_complete called mid-part

KL_MP_ERR_NOMEM 

allocator failure

Function Documentation

◆ kl_body_reader_multipart()

KlBodyReader * kl_body_reader_multipart ( KlAllocator alloc,
const KlRequest req,
void *  user_data 
)

Factory: produce a streaming multipart reader for a request.

Extracts boundary from Content-Type. Returns NULL if the content type is not multipart/form-data, the boundary is missing or too long, or allocation fails. NULL triggers a 415 response from the framework.

Parameters
allocAllocator used for all internal allocations.
reqParsed request; Content-Type header must be set.
user_dataOptional KlMultipartConfig*; NULL → defaults.
Returns
Body reader, or NULL.

◆ kl_multipart_next()

KlMultipartEvent kl_multipart_next ( KlBodyReader br,
KlMultipartPartMeta meta,
const char **  data,
size_t *  data_len 
)

Advance the parser by one event.

Parameters
brThe body reader returned by the factory.
metaOn PART_BEGIN: populated with part metadata. Otherwise untouched.
dataOn PART_DATA: set to a borrowed slice of the input buffer. Borrowed pointer is valid only until the NEXT mutation of the reader — that is, the next kl_multipart_next() call OR the next on_data callback. If your caller can yield to the framework's read loop while holding the slice (so on_data may fire), copy the bytes before yielding.
data_lenOn PART_DATA: bytes in *data.
Returns
One of the KL_MP_EVT_* event codes.

meta and data may be NULL if the caller doesn't care about that variant.

◆ kl_multipart_last_error()

KlMultipartErrorCode kl_multipart_last_error ( const KlBodyReader br)

Return the error code for the latest ERROR event.

Parameters
brThe body reader.
Returns
KL_MP_ERR_NONE if no error, else the specific cause.