FastCGI implementation in OCaml
at main 2.5 kB view raw
1open Cmdliner 2 3(* Handler function that processes FastCGI requests *) 4let handler ~stdout ~stderr request = 5 Eio.traceln "Processing request: %a" Fastcgi.Request.pp request; 6 7 (* Get request parameters *) 8 let params = request.Fastcgi.Request.params in 9 let method_ = Fastcgi.Record.KV.find_opt "REQUEST_METHOD" params |> Option.value ~default:"GET" in 10 let uri = Fastcgi.Record.KV.find_opt "REQUEST_URI" params |> Option.value ~default:"/" in 11 let script_name = Fastcgi.Record.KV.find_opt "SCRIPT_NAME" params |> Option.value ~default:"" in 12 13 (* Log request info *) 14 Eio.traceln " Method: %s" method_; 15 Eio.traceln " URI: %s" uri; 16 Eio.traceln " Script: %s" script_name; 17 18 (* Generate simple HTTP response *) 19 let response_body = 20 Printf.sprintf 21 "<!DOCTYPE html>\n\ 22 <html>\n\ 23 <head><title>FastCGI OCaml Server</title></head>\n\ 24 <body>\n\ 25 <h1>FastCGI OCaml Server</h1>\n\ 26 <p>Request processed successfully!</p>\n\ 27 <ul>\n\ 28 <li>Method: %s</li>\n\ 29 <li>URI: %s</li>\n\ 30 <li>Script: %s</li>\n\ 31 </ul>\n\ 32 <h2>All Parameters:</h2>\n\ 33 <pre>%s</pre>\n\ 34 </body>\n\ 35 </html>\n" 36 method_ uri script_name 37 (let params_seq = Fastcgi.Record.KV.to_seq params in 38 let params_list = List.of_seq params_seq in 39 String.concat "\n" (List.map (fun (k, v) -> Printf.sprintf "%s = %s" k v) params_list)) 40 in 41 42 (* Write HTTP response using FastCGI STDOUT records *) 43 let response_headers = 44 Printf.sprintf 45 "Status: 200 OK\r\n\ 46 Content-Type: text/html; charset=utf-8\r\n\ 47 Content-Length: %d\r\n\ 48 \r\n" 49 (String.length response_body) 50 in 51 stdout response_headers; 52 stderr "stderr stuff"; 53 stdout response_body 54 55let run port = 56 Eio_main.run @@ fun env -> 57 Eio.Switch.run @@ fun sw -> 58 let net = Eio.Stdenv.net env in 59 let addr = `Tcp (Eio.Net.Ipaddr.V4.loopback, port) in 60 let server_socket = Eio.Net.listen net ~backlog:10 ~reuse_addr:true ~sw addr in 61 Eio.traceln "FastCGI server listening on port %d" port; 62 63 (* Run the FastCGI server *) 64 Fastcgi.run server_socket 65 ~on_error:(fun ex -> 66 Eio.traceln "Error: %s" (Printexc.to_string ex); 67 Eio.traceln "bt: %s" (Printexc.get_backtrace ())) 68 handler 69 70let port = 71 let doc = "Port to listen on" in 72 Arg.(value & opt int 9000 & info ["p"; "port"] ~docv:"PORT" ~doc) 73 74let cmd = 75 let doc = "FastCGI server" in 76 let info = Cmd.info "fcgi-server" ~doc in 77 Cmd.v info Term.(const run $ port) 78 79let () = exit (Cmd.eval cmd)