package tiny_libs
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>
From-scratch libraries for teaching: graphics, audio, compression, crypto, networking and more
Install
dune-project
Dependency
Authors
Maintainers
Sources
0.3.6.tar.gz
md5=7c636383d146d30ac6f2fa234a6253c8
sha512=c79f3823c5f8f57e5038eb640d487c61168b84aa07c61999d6622ef9fd0c890e2b03b4c6a7cdbbe9352a49e25dda00ac7bb14693cee8e3d7beeed251351a2af0
doc/src/tiny_libs.networking_unix/Http_server.ml.html
Source file Http_server.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 104 105 106(* Claude Code * * Copyright (C) 2026 Yoann Padioleau * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public License * (LGPL) as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. *) (* See Http_server.mli *) type connection = { fd : Unix.file_descr; peer : string; mutable inbox : string; (* bytes read, not yet a whole request *) mutable outbox : string; (* bytes to write, when the socket takes them *) mutable answered : bool; (* closed once its outbox is written *) } type t = { listener : Unix.file_descr; mutable connections : connection list } type handler = peer:string -> Http.request -> string -> Http.response let listen (caps : < Cap.network ; .. >) ~(bind : string) ~(port : int) : t * int = let (_ : Cap.Network.t) = caps#network bind in let fd = Unix.socket Unix.PF_INET Unix.SOCK_STREAM 0 in Unix.setsockopt fd Unix.SO_REUSEADDR true; Unix.bind fd (Unix.ADDR_INET (Unix.inet_addr_of_string bind, port)); Unix.listen fd 16; Unix.set_nonblock fd; let port = match Unix.getsockname fd with Unix.ADDR_INET (_, p) -> p | _ -> port in ({ listener = fd; connections = [] }, port) let connections (t : t) : int = List.length t.connections (*****************************************************************************) (* One step of each connection *) (*****************************************************************************) let accept_all (t : t) : unit = let rec go () = match Unix.accept t.listener with | fd, addr -> Unix.set_nonblock fd; let peer = match addr with Unix.ADDR_INET (a, _) -> Unix.string_of_inet_addr a | _ -> "?" in t.connections <- t.connections @ [ { fd; peer; inbox = ""; outbox = ""; answered = false } ]; go () | exception Unix.Unix_error ((Unix.EAGAIN | Unix.EWOULDBLOCK), _, _) -> () in go () (* what arrived; a client gone before its answer is answered nothing *) let read (c : connection) : unit = let buf = Bytes.create 65536 in let rec go () = match Unix.read c.fd buf 0 (Bytes.length buf) with | 0 -> c.answered <- true | n -> c.inbox <- c.inbox ^ Bytes.sub_string buf 0 n; go () | exception Unix.Unix_error ((Unix.EAGAIN | Unix.EWOULDBLOCK), _, _) -> () | exception Unix.Unix_error _ -> c.answered <- true in if not c.answered then go () (* a whole request answered by the handler; garbage answered 400 *) let answer (handler : handler) (c : connection) : unit = if not c.answered then match Http.parse_request c.inbox with | Incomplete -> () | Bad why -> c.outbox <- Http.response_to_string (Http.response 400 ~content_type:"text/plain" (why ^ "\n")); c.answered <- true | Request (request, body, _) -> let response = try handler ~peer:c.peer request body with e -> Http.response 500 ~content_type:"text/plain" (Printexc.to_string e ^ "\n") in c.outbox <- Http.response_to_string response; c.answered <- true (* as much of the outbox as the socket takes now *) let write (c : connection) : unit = if c.outbox <> "" then match Unix.write_substring c.fd c.outbox 0 (String.length c.outbox) with | n -> c.outbox <- String.sub c.outbox n (String.length c.outbox - n) | exception Unix.Unix_error ((Unix.EAGAIN | Unix.EWOULDBLOCK), _, _) -> () | exception Unix.Unix_error _ -> c.outbox <- "" let step (t : t) (handler : handler) : unit = accept_all t; List.iter (fun c -> read c; answer handler c; write c) t.connections; (* the connections answered, once their answer is written *) let done_, kept = List.partition (fun c -> c.answered && c.outbox = "") t.connections in List.iter (fun c -> try Unix.close c.fd with Unix.Unix_error _ -> ()) done_; t.connections <- kept let wait (t : t) (timeout : float) : unit = let reads = t.listener :: List.filter_map (fun c -> if c.answered then None else Some c.fd) t.connections in let writes = List.filter_map (fun c -> if c.outbox <> "" then Some c.fd else None) t.connections in try ignore (Unix.select reads writes [] timeout) with Unix.Unix_error (Unix.EINTR, _, _) -> ()
sectionYPositions = computeSectionYPositions($el), 10)"
x-init="setTimeout(() => sectionYPositions = computeSectionYPositions($el), 10)"
>