irox_networking/http/
request.rs1use 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}