proto_tower_http_1/data/
request.rs

1use async_trait::async_trait;
2use http::Uri;
3use tokio::io::AsyncWriteExt;
4
5/// An HTTP/1.1 request
6#[derive(Debug, Clone)]
7pub struct HTTP1Request {
8    pub path: Uri,
9    pub method: http::Method,
10    pub headers: http::HeaderMap,
11    pub body: Vec<u8>,
12}
13
14#[async_trait]
15impl<Writer> proto_tower_util::WriteTo<Writer, ()> for HTTP1Request
16where
17    Writer: AsyncWriteExt + Send + Unpin + 'static,
18{
19    async fn write_to(&self, writer: &mut Writer) -> Result<(), ()> {
20        // Request line
21        writer.write_all(self.method.as_str().as_bytes()).await.map_err(|_| ())?;
22        writer.write_all(" ".as_bytes()).await.map_err(|_| ())?;
23        writer.write_all(self.path.path().as_bytes()).await.map_err(|_| ())?;
24        writer.write_all(" HTTP/1.1\r\n".as_bytes()).await.map_err(|_| ())?;
25        // Headers
26        for (header_name, header_value) in &self.headers {
27            writer.write_all(header_name.as_str().as_bytes()).await.map_err(|_| ())?;
28            writer.write_all(": ".as_bytes()).await.map_err(|_| ())?;
29            writer.write_all(header_value.as_bytes()).await.map_err(|_| ())?;
30            writer.write_all("\r\n".as_bytes()).await.map_err(|_| ())?;
31        }
32        writer
33            .write_all(format!("Content-Length: {}\r\n", self.body.len()).as_bytes())
34            .await
35            .map_err(|_| ())?;
36        writer.write_all("\r\n".as_bytes()).await.map_err(|_| ())?;
37        // Body
38        if !self.body.is_empty() {
39            writer.write_all(&self.body).await.map_err(|_| ())?;
40        }
41        Ok(())
42    }
43}