package tiny_httpd
Minimal HTTP server using threads
Install
Dune Dependency
Authors
Maintainers
Sources
tiny_httpd-0.19.tbz
sha256=55b6eed7d2e41b9b2a282b344e01ca010abdba66cbbbbe5adab18303b9ff8360
sha512=98c599627b9cd98f641d389e022f9ddc025bfba838793267904b94a01b0b40b3b4cfd8f5a8d8214aaa947958e45cecbe1df751692a461f929802714d7af50e06
doc/src/tiny_httpd.core/headers.ml.html
Source file headers.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 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103
open Common_ type t = (string * string) list let empty = [] (* [Char.lowercase_ascii] but easier to inline *) let[@inline] lower_char_ = function | 'A' .. 'Z' as c -> Char.unsafe_chr (Char.code c + 32) | c -> c (** Are these two header names equal? This is case insensitive *) let equal_name_ (s1 : string) (s2 : string) : bool = String.length s1 = String.length s2 && try for i = 0 to String.length s1 - 1 do let c1 = String.unsafe_get s1 i |> lower_char_ in let c2 = String.unsafe_get s2 i |> lower_char_ in if c1 <> c2 then raise_notrace Exit done; true with Exit -> false let contains name headers = List.exists (fun (n, _) -> equal_name_ name n) headers let rec get_exn ?(f = fun x -> x) x h = match h with | [] -> raise Not_found | (k, v) :: _ when equal_name_ x k -> f v | _ :: tl -> get_exn ~f x tl let get ?(f = fun x -> x) x h = try Some (get_exn ~f x h) with Not_found -> None let remove x h = List.filter (fun (k, _) -> not (equal_name_ k x)) h let set x y h = let h = if contains x h then remove x h else h in (x, y) :: h let pp out l = let pp_pair out (k, v) = Format.fprintf out "@[<h>%s: %s@]" k v in Format.fprintf out "@[<v>%a@]" (Format.pp_print_list pp_pair) l (* token = 1*tchar tchar = "!" / "#" / "$" / "%" / "&" / "'" / "*" / "+" / "-" / "." / "^" / "_" / "`" / "|" / "~" / DIGIT / ALPHA ; any VCHAR, except delimiters Reference: https://datatracker.ietf.org/doc/html/rfc7230#section-3.2 *) let is_tchar = function | '0' .. '9' | 'a' .. 'z' | 'A' .. 'Z' | '!' | '#' | '$' | '%' | '&' | '\'' | '*' | '+' | '-' | '.' | '^' | '_' | '`' | '|' | '~' -> true | _ -> false let for_all pred s = try String.iter (fun c -> if not (pred c) then raise Exit) s; true with Exit -> false let parse_line_ (line : string) : _ result = try let i = try String.index line ':' with Not_found -> failwith "invalid header, missing ':'" in let k = String.sub line 0 i in if not (for_all is_tchar k) then failwith (Printf.sprintf "Invalid header key: %S" k); let v = String.sub line (i + 1) (String.length line - i - 1) |> String.trim in Ok (k, v) with Failure msg -> Error msg let parse_ ~(buf : Buf.t) (bs : IO.Input.t) : t = let rec loop acc = match IO.Input.read_line_using_opt ~buf bs with | None -> raise End_of_file | Some "" -> assert false | Some "\r" -> acc | Some line when line.[String.length line - 1] <> '\r' -> bad_reqf 400 "bad header line, not ended in CRLF" | Some line -> let k, v = match parse_line_ line with | Ok r -> r | Error msg -> bad_reqf 400 "invalid header line: %s\nline is: %S" msg line in loop ((k, v) :: acc) in loop []
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>