cegla_cgi/
server.rs

1//! CGI implementation for web applications.
2
3use std::future::Future;
4
5use cegla::{
6  server::{convert_cgi_request, convert_from_http_response},
7  CgiEnvironment, CgiIncoming,
8};
9use tokio::io::{AsyncRead, AsyncWrite};
10use tokio_util::io::StreamReader;
11
12/// Handles a CGI request by converting it to an HTTP request, invoking the provided request function,
13/// and then converting the HTTP response back to a CGI response.
14pub async fn handle_request<I, O, E, F, Fut, B, Err>(
15  stdin: I,
16  mut stdout: O,
17  stderr: E,
18  request_fn: F,
19) -> Result<(), std::io::Error>
20where
21  I: AsyncRead + Unpin + 'static,
22  O: AsyncWrite + Unpin,
23  E: AsyncWrite + Unpin,
24  F: FnOnce(http::Request<CgiIncoming<I>>, E) -> Fut,
25  Fut: Future<Output = Result<http::Response<B>, Err>>,
26  B: http_body::Body,
27  B::Data: AsRef<[u8]> + Send + 'static,
28  B::Error: Into<std::io::Error>,
29  Err: Into<std::io::Error>,
30{
31  let request = convert_cgi_request(stdin, CgiEnvironment::from_iter(std::env::vars()))?;
32
33  let response = request_fn(request, stderr).await.map_err(|err| err.into())?;
34
35  let response_data = convert_from_http_response(response)?;
36  let mut response_reader = StreamReader::new(response_data);
37  tokio::io::copy(&mut response_reader, &mut stdout).await?;
38
39  Ok(())
40}