irox_networking/http/
request.rs

1// SPDX-License-Identifier: MIT
2// Copyright 2023 IROX Contributors
3//
4
5use crate::http::headers::HttpHeaders;
6use crate::http::{HttpBody, HttpMethod, HttpVersion};
7use crate::url::URL;
8use log::debug;
9use std::io::Write;
10
11pub struct HttpRequest {
12    pub(crate) url: URL,
13    pub(crate) method: HttpMethod,
14    pub(crate) version: HttpVersion,
15    pub(crate) headers: HttpHeaders,
16    pub(crate) body: HttpBody,
17}
18
19impl HttpRequest {
20    pub fn new(url: URL) -> Self {
21        Self {
22            method: HttpMethod::Get,
23            url,
24            version: HttpVersion::Http1_1,
25            headers: HttpHeaders::new_request(),
26            body: HttpBody::Empty,
27        }
28    }
29
30    pub fn set_method(&mut self, method: HttpMethod) {
31        self.method = method
32    }
33    pub fn method(&self) -> &HttpMethod {
34        &self.method
35    }
36
37    pub fn set_url(&mut self, url: URL) {
38        self.url = url;
39    }
40    pub fn url(&self) -> &URL {
41        &self.url
42    }
43
44    pub fn write_to<T: Write>(mut self, mut out: &mut T) -> Result<(), std::io::Error> {
45        if !self.headers.contains_header("Host") {
46            let port = if let Some(port) = self.url.port {
47                format!(":{port}")
48            } else {
49                String::new()
50            };
51            let host = format!("{}{port}", self.url.host);
52            self.headers.maybe_add("Host", &host);
53        }
54        self.headers
55            .maybe_add("User-Agent", crate::http::DEFAULT_USER_AGENT);
56        match &self.body {
57            HttpBody::Empty => {
58                self.headers.maybe_add("Content-Length", "0");
59            }
60            HttpBody::String(s) => {
61                self.headers
62                    .maybe_add("Content-Length", format!("{}", s.len()));
63            }
64            HttpBody::Bytes(b) => {
65                self.headers
66                    .maybe_add("Content-Length", format!("{}", b.len()));
67            }
68            _ => {}
69        }
70
71        let hdr = format!(
72            "{} {} {}",
73            self.method,
74            self.url.get_path_query_fragment(),
75            self.version
76        );
77        debug!("{hdr}");
78        write!(out, "{hdr}\r\n")?;
79        self.headers.write_to(&mut out)?;
80
81        self.body.write_to(&mut out)?;
82
83        out.flush()?;
84
85        Ok(())
86    }
87}