package multipart_form
Multipart-form: RFC2183, RFC2388 & RFC7578
Install
Dune Dependency
Authors
Maintainers
Sources
multipart_form-v0.2.0.tbz
sha256=cff5758d3ea1bd759d65b628611527deec9719dc10e89779a0306cfcf36bf6a0
sha512=e59a6cd6893825452672e8ee1fa3ae8d8d72449948ca1b8500a81670b416cd1715e2a8f7bb72794565c422064e0fe7950038b5cba600aa04647eaedeee6b1ac0
doc/src/multipart_form.lwt/multipart_form_lwt.ml.html
Source file multipart_form_lwt.ml
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80
open Multipart_form open Lwt.Infix let stream ?(bounds = 10) ~identify stream content_type = let output, push = Lwt_stream.create () in let q = Queue.create () in let fresh_id = let r = ref 0 in fun () -> incr r ; !r in let tbl = Hashtbl.create 0x10 in let emitters header = let id = fresh_id () in Queue.push (`Id (header, id)) q ; ((fun data -> Queue.push (`Data (id, data)) q), id) in let parse = Multipart_form.parse ~emitters content_type in let rec go () = match Queue.pop q with | `Id (header, id) -> let client_id = identify header in let stream, bounded_emitter = Lwt_stream.create_bounded bounds in Hashtbl.add tbl id (client_id, stream, bounded_emitter) ; push (Some (client_id, header, stream)) ; go () | `Data (id, Some data) -> let _, _, emitter = Hashtbl.find tbl id in emitter#push data >>= fun () -> go () | `Data (id, None) -> let _, _, emitter = Hashtbl.find tbl id in emitter#close ; go () | exception Queue.Empty -> ( (* otherwise, continue parsing (thus adding elements to the queue) *) Lwt_stream.get stream >>= fun data -> let data = match data with Some s -> `String s | None -> `Eof in match parse data with | `Continue -> go () | `Done t -> let client_id_of_id id = let client_id, _, _ = Hashtbl.find tbl id in client_id in push None ; Lwt.return_ok (map client_id_of_id t) | `Fail _ -> push None ; Lwt.return_error (`Msg "Invalid multipart/form")) in (`Parse (go ()), output) (* only used internally to implement of_stream_to_{tree,list} *) let of_stream_to_tbl s content_type = let identify = let id = ref (-1) in fun _header -> incr id ; !id in let `Parse t, parts = stream ~identify s content_type in let parts_tbl = Hashtbl.create 0x10 in let consume_part (id, _, part_stream) = let buf = Buffer.create 4096 in Lwt_stream.iter (Buffer.add_string buf) part_stream >>= fun () -> Hashtbl.add parts_tbl id (Buffer.contents buf) ; Lwt.return () in Lwt.both t (Lwt_stream.iter_s consume_part parts) >>= fun (res, ()) -> Lwt.return @@ Result.map (fun tree -> (tree, parts_tbl)) res let of_stream_to_tree s content_type = of_stream_to_tbl s content_type >>= fun res -> Lwt.return @@ Result.map (fun (tree, parts_tbl) -> map (Hashtbl.find parts_tbl) tree) res let of_stream_to_list s content_type = of_stream_to_tbl s content_type >>= fun res -> Lwt.return @@ Result.map (fun (tree, parts_tbl) -> let assoc = Hashtbl.fold (fun k b a -> (k, b) :: a) parts_tbl [] in (tree, assoc)) res
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>