package piaf

  1. Overview
  2. Docs

Multipart-form.

The MIME type multipart/form-data is used to express values submitted through a <form>. This module helps the user to extract these values from an input.

module Field_name : sig ... end
module Content_type : sig ... end
module Content_encoding : sig ... end
module Content_disposition : sig ... end
module Field : sig ... end
module Header : sig ... end
type 'id emitters = Header.t -> (Bigstringaf.t Faraday.iovec option -> unit) * 'id

Type of emitters.

An emitters is able to produce from the given header a pusher which is able to save contents and a unique ID to be able to get the content furthermore.

type 'a elt = {
  1. header : Header.t;
  2. body : 'a;
}

Type of a simple element.

An element is a part in sense of the multipart/form-data format. A part can contains multiple parts. It has systematically a Header.t.

type 'a t =
  1. | Leaf of 'a elt
  2. | Multipart of 'a t option list elt

Type of multipart/form-data contents.

  • a Leaf is a content with a simple header.
  • a Multipart is a list of possibly empty (option) sub-elements - indeed, we can have a multipart inside a multipart.
val parser : emitters:'id emitters -> Content_type.t -> max_chunk_size:int -> 'id t Angstrom.t

parser ~emitters content_type creates an angstrom's parser which can process a multipart/form-data input. For each Leaf, the parser calls emitters to be able to save contents and get a reference of it.

A simple use of it is to generate an unique ID and associate it to a Buffer.t such as:

let gen = let v = ref (-1) in fun () -> incr v ; !v in
let tbl = Hashtbl.create 0x10 in
let emitters () =
  let idx = gen () in
  let buf = Buffer.create 0x100 in
  (function None -> ()
          | Some str -> Buffer.add_string buf str), idx in
parser ~emitters content_type 

With such style, a mapping exists between the returned value t and tbl. At the end, the user is able to extract contents with these values.

In some contexts, something else such as an Lwt_stream.t/asynchronous stream can be used instead a Buffer.t.

type 'a stream = unit -> 'a option
val of_stream : string stream -> Content_type.t -> (int t * (int * string) list, [> `Msg of string ]) result

of_stream stream content_type returns, if it succeeds, a value t with an associative list of unique ID and contents.

val of_string : string -> Content_type.t -> (int t * (int * string) list, [> `Msg of string ]) result

of_string str content_type returns, if it succeeds, a value t with an associative list of unique ID and contents.

type part
val part : ?header:Header.t -> ?disposition:Content_disposition.t -> ?encoding:Content_encoding.t -> (string * int * int) stream -> part
type multipart
val multipart : rng:(?g:'g -> int -> string) -> ?g:'g -> ?header:Header.t -> ?boundary:string -> part list -> multipart
val to_stream : multipart -> Header.t * (string * int * int) stream