Eio HTTP server with static file serving and route handlers
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

respond: configurable ?max_body_size (default 16 MiB)

The body limit was hard-coded at 1 MiB in two places (the read buffer
and the Content-Length gate), which prevents file uploads of any real
size. Expose it as a single parameter on Respond.run; bump the default
to 16 MiB so multipart/form-data uploads work out of the box without
every caller threading a custom value.

+15 -10
+9 -7
lib/respond.ml
··· 318 318 in 319 319 loop routes 320 320 321 - let read_body reader headers = 321 + let read_body ~max_body_size reader headers = 322 322 match Headers.find `Content_length headers with 323 323 | Some len_str -> ( 324 324 match int_of_string_opt len_str with 325 - | Some len when len > 0 && len <= 1024 * 1024 -> 325 + | Some len when len > 0 && len <= max_body_size -> 326 326 Eio.Buf_read.take len reader 327 327 | _ -> "") 328 328 | None -> "" 329 329 330 - let handle ~root ~routes flow reader = 330 + let handle ~max_body_size ~root ~routes flow reader = 331 331 let request_line = read_line reader in 332 332 let headers = parse_headers reader in 333 333 match String.split_on_char ' ' request_line with ··· 341 341 send_cors flow 342 342 | "POST", url :: _ -> ( 343 343 let path, params = parse_url url in 344 - let body = read_body reader headers in 344 + let body = read_body ~max_body_size reader headers in 345 345 match match_route routes path with 346 346 | Some ({ handler = Post handler; _ }, path_params) -> ( 347 347 let req = { path; path_params; params; body; headers } in ··· 382 382 383 383 (* ── Server ───────────────────────────────────────────────────────── *) 384 384 385 - let run ~net ~port ~root routes = 385 + let default_max_body_size = 16 * 1024 * 1024 386 + 387 + let run ?(max_body_size = default_max_body_size) ~net ~port ~root routes = 386 388 Log.info (fun m -> m "listening on http://0.0.0.0:%d" port); 387 389 Eio.Switch.run @@ fun sw -> 388 390 let addr = `Tcp (Eio.Net.Ipaddr.V4.any, port) in ··· 392 394 ~on_error:(fun exn -> 393 395 Log.debug (fun m -> m "connection error: %s" (Printexc.to_string exn))) 394 396 (fun flow _addr -> 395 - let reader = Eio.Buf_read.of_flow ~max_size:(1024 * 1024) flow in 396 - handle ~root ~routes flow reader) 397 + let reader = Eio.Buf_read.of_flow ~max_size:max_body_size flow in 398 + handle ~max_body_size ~root ~routes flow reader) 397 399 done
+6 -3
lib/respond.mli
··· 135 135 (** {1 Running} *) 136 136 137 137 val run : 138 + ?max_body_size:int -> 138 139 net:_ Eio.Net.t -> 139 140 port:int -> 140 141 root:Eio.Fs.dir_ty Eio.Path.t -> 141 142 route list -> 142 143 unit 143 - (** [run ~net ~port ~root routes] starts the server. Routes are matched by 144 - method and path; unmatched GET requests fall through to static file serving 145 - from [root]. *) 144 + (** [run ?max_body_size ~net ~port ~root routes] starts the server. Routes are 145 + matched by method and path; unmatched GET requests fall through to static 146 + file serving from [root]. [max_body_size] caps both the per-connection read 147 + buffer and the [Content-Length] the POST handler will accept (default 16 148 + MiB). *)