Skip to content

Multipart

Parses and persists HTTP multipart/form-data request bodies.

Multipart turns incoming byte streams into typed form parts. Text parts become decoded fields, while upload parts stay as streamed files until they are collected or written to scoped temporary files. The persisted representation can then be decoded with schemas for handlers that receive fields and uploaded files together. This module also includes multipart error types, schema helpers for persisted files, and parser limit settings.

29 exports Added in v4.0.0 Source

Configuration

makeConfig

Added in v4.0.0 Source

Builds the low-level multipart parser configuration from request headers and the current fiber context.

Details

Parser limits are read from the multipart references, including maximum parts, field size, file size, total body size, and field MIME type overrides.

Signature

declare function makeConfig(headers: Record<string, string>): Effect<BaseConfig>;

Converting

Runs a channel of byte chunks and collects all output into a single Uint8Array.

Gotchas

This materializes the full content in memory.

Signature

declare function collectUint8Array<OE, OD, R>(
  self: Channel<
    readonly [Uint8Array<ArrayBufferLike>, Uint8Array<ArrayBufferLike>],
    OE,
    OD,
    unknown,
    unknown,
    unknown,
    R
  >,
): Effect<Uint8Array<ArrayBuffer>, OE, R>;

toPersisted

Added in v4.0.0 Source

Persists a stream of multipart parts into a record.

Details

Text fields are collected as strings, and file parts are written to files in a scoped temporary directory.

Gotchas

Persisted file paths remain valid for the lifetime of the scope.

Signature

declare function toPersisted(
  stream: Stream<Part, MultipartError>,
  writeFile: (path: string, file: File) => Effect<void, MultipartError, FileSystem>,
): Effect<Persisted, MultipartError, Scope | FileSystem | Path>;

Errors

Error raised while parsing, streaming, or persisting multipart form data.

Details

The reason field contains the concrete MultipartErrorReason. When used as a server response, parse errors render as 400, limit errors as 413, and internal errors as 500. Multipart errors are ignored by the error reporter.

Signature

declare class MultipartError extends YieldableError<this> & {
  readonly _tag: "MultipartError";
} & Readonly<{
  readonly reason: MultipartErrorReason;
}> implements Respondable {
  constructor(args: {
    readonly reason: MultipartErrorReason;
  });
  readonly "~effect/ErrorReporter/ignore": true;
  readonly "~effect/http/Multipart/MultipartError": "~effect/http/Multipart/MultipartError";
  message: string;
  "~effect/http/HttpServerRespondable"(): Effect<HttpServerResponse, never, never>;
  static fromReason(reason: "InternalError" | "FileTooLarge" | "FieldTooLarge" | "BodyTooLarge" | "TooManyParts" | "Parse", cause?: unknown): MultipartError;
}

Error reason carried by a MultipartError.

Details

It identifies parser and limit failures such as oversized files or fields, too many parts, total body size limits, parse errors, and internal errors.

Signature

declare class MultipartErrorReason extends Error<{
  readonly _tag:
    | "FileTooLarge"
    | "FieldTooLarge"
    | "BodyTooLarge"
    | "TooManyParts"
    | "InternalError"
    | "Parse";
  readonly cause?: unknown;
}> {
  constructor(args: {
    readonly _tag:
      | "InternalError"
      | "FileTooLarge"
      | "FieldTooLarge"
      | "BodyTooLarge"
      | "TooManyParts"
      | "Parse";
    readonly cause?: unknown;
  });
}

Guards

isField

Added in v4.0.0 Source

Returns true when a value is a multipart text Field.

Signature

declare function isField(u: unknown): u is Field;

isFile

Added in v4.0.0 Source

Returns true when a value is a multipart File.

Signature

declare function isFile(u: unknown): u is File;

isPart

Added in v4.0.0 Source

Returns true when a value is a multipart Part.

Signature

declare function isPart(u: unknown): u is Part;

Returns true when a value is a persisted multipart file.

Signature

declare function isPersistedFile(u: unknown): u is PersistedFile;

Models

Field interface

Added in v4.0.0 Source

Multipart form field containing a decoded text value.

Details

The key is the field name, contentType is the part media type, and value is the decoded field content.

Signature

interface Field extends Proto {
  readonly _tag: "Field";
  readonly contentType: string;
  readonly key: string;
  readonly value: string;
}

File interface

Added in v4.0.0 Source

Multipart file part.

Gotchas

The file content is exposed as a byte stream. contentEffect collects the full file into memory and should be used only when the file size is acceptable.

Signature

interface File extends Proto {
  readonly _tag: "File";
  readonly content: Stream<Uint8Array<ArrayBufferLike>, MultipartError>;
  readonly contentEffect: Effect<Uint8Array<ArrayBufferLike>, MultipartError>;
  readonly contentType: string;
  readonly key: string;
  readonly name: string;
}

Part type

Added in v4.0.0 Source

A parsed multipart part.

Details

A part is either a text Field or a streamed File.

Signature

type Part = Field | File;

Persisted interface

Added in v4.0.0 Source

Record representation of persisted multipart data.

Details

Field names map to text values, arrays of text values, or arrays of PersistedFile values.

Signature

interface Persisted {
  [key: string]: string | readonly Array<string> | readonly Array<PersistedFile>;
}

PersistedFile interface

Added in v4.0.0 Source

Multipart file part that has been written to the filesystem.

Details

The path points to the persisted file while the scope used to persist the multipart data remains open.

Signature

interface PersistedFile extends Proto {
  readonly _tag: "PersistedFile";
  readonly contentType: string;
  readonly key: string;
  readonly name: string;
  readonly path: string;
}

Other

Part

Added in v4.0.0 Source

Namespace containing shared multipart part model types.

withLimits

Added in v4.0.0 Source

Namespace containing multipart parser limit option types.

Parsing

makeChannel

Added in v4.0.0 Source

Creates a channel that parses multipart byte chunks into multipart parts.

Details

The channel consumes non-empty batches of Uint8Array chunks and emits non-empty batches of parsed Part values, failing with MultipartError for parser and limit failures.

Signature

declare function makeChannel<IE>(
  headers: Record<string, string>,
): Channel<
  readonly [Part, Part],
  MultipartError | IE,
  void,
  readonly [Uint8Array<ArrayBufferLike>, Uint8Array<ArrayBufferLike>],
  IE,
  unknown
>;

References

Creates a context containing multipart parser limit settings.

Details

The context can provide maximum part count, field size, file size, total body size, and MIME types that should be parsed as fields.

Signature

declare function limitsServices(options: {
  readonly fieldMimeTypes?: readonly Array<string>;
  readonly maxFieldSize?: SizeInput;
  readonly maxFileSize?: SizeInput;
  readonly maxParts?: number;
  readonly maxTotalSize?: SizeInput;
}): Context<never>

Schemas

FilesSchema

Added in v4.0.0 Source

Schema for an array of persisted multipart files.

Signature

declare const FilesSchema: Schema.$Array<PersistedFileSchema>;

Schema for persisted multipart files.

Details

The encoded form contains the field key, original file name, content type, and filesystem path.

Signature

declare const PersistedFileSchema: PersistedFileSchema;

PersistedFileSchema interface

Added in v4.0.0 Source

Schema type for persisted multipart files.

Signature

interface PersistedFileSchema extends declare<PersistedFile> {
  constructor(_: never);
}

schemaJson

Added in v4.0.0 Source

Creates a decoder for a JSON-encoded field in persisted multipart data.

Details

The selected field is parsed from a JSON string and decoded with the supplied schema.

Signature

declare function schemaJson<A, RD>(
  schema: ConstraintDecoder<A, RD>,
  options?: ParseOptions,
): {
  (field: string): (persisted: Persisted) => Effect<A, SchemaError, RD>;
  (persisted: Persisted, field: string): Effect<A, SchemaError, RD>;
};

Creates a decoder for persisted multipart data using the supplied schema.

Details

The returned function decodes an unknown input into the schema output and fails with SchemaError when validation fails.

Signature

declare function schemaPersisted<A, I extends Partial<Persisted>, RD>(
  schema: ConstraintCodec<A, I, RD, unknown>,
): (input: unknown, options?: ParseOptions) => Effect<A, SchemaError, RD>;

Schema for exactly one persisted multipart file.

Details

The encoded form is a one-element file array, while the decoded value is the single PersistedFile.

Signature

declare const SingleFileSchema: Schema.decodeTo<
  PersistedFileSchema,
  Schema.$Array<PersistedFileSchema>
>;

Services

Context reference for MIME type fragments that should be parsed as multipart fields instead of files.

Details

The default treats application/json parts as fields.

Signature

declare const FieldMimeTypes: Reference<readonly Array<string>>

MaxFieldSize

Added in v4.0.0 Source

Context reference for the maximum size of a multipart field value.

Details

The default limit is 10 MiB.

Signature

declare const MaxFieldSize: Reference<SizeInput>;

MaxFileSize

Added in v4.0.0 Source

Context reference for the maximum size of a multipart file part.

Details

The default is undefined, meaning no explicit per-file limit.

Signature

declare const MaxFileSize: Reference<SizeInput | undefined>;

MaxParts

Added in v4.0.0 Source

Context reference for the maximum number of multipart parts allowed.

Details

The default is undefined, meaning no explicit part-count limit.

Signature

declare const MaxParts: Reference<number | undefined>;

Type IDs

TypeId

Added in v4.0.0 Source

Type identifier used to brand multipart part values.

Signature

declare const TypeId: "~effect/http/Multipart";