My agentic slop goes here. Not intended for anyone else!
1let src = Logs.Src.create "requests.mime" ~doc:"MIME Type Handling"
2module Log = (val Logs.src_log src : Logs.LOG)
3
4type t = {
5 type_ : string;
6 subtype : string;
7 parameters : (string * string) list;
8}
9
10let make type_ subtype = {
11 type_;
12 subtype;
13 parameters = [];
14}
15
16let of_string s =
17 let parts = String.split_on_char ';' s in
18 match parts with
19 | [] -> make "text" "plain"
20 | mime :: params ->
21 let mime_parts = String.split_on_char '/' (String.trim mime) in
22 let type_, subtype = match mime_parts with
23 | [t; s] -> String.trim t, String.trim s
24 | [t] -> String.trim t, "*"
25 | _ -> "text", "plain"
26 in
27 let parse_param p =
28 match String.split_on_char '=' (String.trim p) with
29 | [k; v] ->
30 let k = String.trim k in
31 let v = String.trim v in
32 let v =
33 if String.length v >= 2 && v.[0] = '"' && v.[String.length v - 1] = '"'
34 then String.sub v 1 (String.length v - 2)
35 else v
36 in
37 Some (String.lowercase_ascii k, v)
38 | _ -> None
39 in
40 let parameters = List.filter_map parse_param params in
41 { type_; subtype; parameters }
42
43let to_string t =
44 let base = Printf.sprintf "%s/%s" t.type_ t.subtype in
45 match t.parameters with
46 | [] -> base
47 | params ->
48 let param_str =
49 List.map (fun (k, v) ->
50 if String.contains v ' ' || String.contains v ';'
51 then Printf.sprintf "%s=\"%s\"" k v
52 else Printf.sprintf "%s=%s" k v
53 ) params
54 |> String.concat "; "
55 in
56 Printf.sprintf "%s; %s" base param_str
57
58let pp ppf t = Format.fprintf ppf "%s" (to_string t)
59
60let charset t =
61 List.assoc_opt "charset" t.parameters
62
63let with_charset charset t =
64 let parameters =
65 ("charset", charset) ::
66 List.filter (fun (k, _) -> k <> "charset") t.parameters
67 in
68 { t with parameters }
69
70(* Common MIME types *)
71let json = make "application" "json"
72let text = make "text" "plain"
73let html = make "text" "html"
74let xml = make "application" "xml"
75let form = make "application" "x-www-form-urlencoded"
76let octet_stream = make "application" "octet-stream"
77let multipart_form = make "multipart" "form-data"