Skip to content

Commit

Permalink
cohttp-eio.Server: Don't blow up in callback on client disconnections.
Browse files Browse the repository at this point in the history
  • Loading branch information
mefyl committed Jan 22, 2024
1 parent 5da40ec commit f4b5e09
Showing 1 changed file with 31 additions and 17 deletions.
48 changes: 31 additions & 17 deletions cohttp-eio/src/server.ml
Original file line number Diff line number Diff line change
Expand Up @@ -92,22 +92,40 @@ let write output (response : Cohttp.Response.t) body =
in
Eio.Buf_write.flush output
let callback { conn_closed; handler } conn input output =
let callback { conn_closed; handler } ((_, peer_address) as conn) input output =
let id = (Cohttp.Connection.create () [@ocaml.warning "-3"]) in
let rec handle () =
match read input with
| `Eof -> conn_closed (conn, id)
| `Eof ->
let () =
Logs.info (fun m ->
m "%a: disconnected" Eio.Net.Sockaddr.pp peer_address)
in
conn_closed (conn, id)
| exception Eio.Io (Eio.Net.E (Connection_reset _), _) ->
let () =
Logs.info (fun m ->
m "%a: connection reset" Eio.Net.Sockaddr.pp peer_address)
in
()
| `Invalid e ->
write output
(Http.Response.make ~status:`Bad_request ())
(Body.of_string e)
| `Ok (request, body) ->
let () =
match handler (conn, id) request body with
| `Response (response, body) -> write output response body
| `Expert (response, handler) ->
let () = Io.Response.write_header response output in
handler input output
try
match handler (conn, id) request body with
| `Response (response, body) -> write output response body
| `Expert (response, handler) ->
let () = Io.Response.write_header response output in
handler input output
with Eio.Io (Eio.Net.E (Connection_reset _), _) ->
let () =
Logs.info (fun m ->
m "%a: connection reset" Eio.Net.Sockaddr.pp peer_address)
in
()
in
if Cohttp.Request.is_keep_alive request then handle ()
in
Expand All @@ -116,14 +134,10 @@ let callback { conn_closed; handler } conn input output =
let run ?max_connections ?additional_domains ?stop ~on_error socket server =
Eio.Net.run_server socket ?max_connections ?additional_domains ?stop ~on_error
(fun socket peer_address ->
try
Eio.Switch.run @@ fun sw ->
let () =
Logs.info (fun m ->
m "%a: accept connection" Eio.Net.Sockaddr.pp peer_address)
and input = Eio.Buf_read.of_flow ~max_size:max_int socket in
Eio.Buf_write.with_flow socket @@ fun output ->
callback server (sw, peer_address) input output
with Eio.Io (Eio.Net.E (Connection_reset _), _) ->
Eio.Switch.run @@ fun sw ->
let () =
Logs.info (fun m ->
m "%a: disconnected" Eio.Net.Sockaddr.pp peer_address))
m "%a: accept connection" Eio.Net.Sockaddr.pp peer_address)
and input = Eio.Buf_read.of_flow ~max_size:max_int socket in
Eio.Buf_write.with_flow socket @@ fun output ->
callback server (sw, peer_address) input output)

0 comments on commit f4b5e09

Please sign in to comment.