1use std::fmt::Write;
4
5use crate::body::{EncodedRequest, RequestBody};
6
7pub(crate) fn encode_request(req: &http::Request<RequestBody>) -> EncodedRequest {
9 let mut s = format!("{} {} HTTP/1.0\r\n", req.method(), req.uri());
10
11 for (key, val) in req.headers().iter() {
12 write!(
13 s,
14 "{}: {}\r\n",
15 key,
16 val.to_str()
17 .expect("Added an HTTP header that wasn't UTF-8!")
18 )
19 .expect("Write to string failed");
20 }
21
22 if req.method() == http::Method::POST || !req.body().is_empty() {
23 write!(s, "Content-Length: {}\r\n", req.body().len())
24 .expect("Added an HTTP header that wasn't UTF-8!");
25 }
26
27 s.push_str("\r\n");
28
29 let mut body = EncodedRequest::from_header(s);
30 body.set_body(req.body().clone());
31
32 body
33}
34
35#[cfg(test)]
41pub(crate) fn request_to_string(req: &http::Request<RequestBody>) -> String {
42 let body = encode_request(req);
43 let bytes: Vec<u8> = body.to_owned();
44 String::from_utf8(bytes).expect("Body was not UTF-8")
45}
46
47#[cfg(test)]
48mod test {
49 #![allow(clippy::bool_assert_comparison)]
51 #![allow(clippy::clone_on_copy)]
52 #![allow(clippy::dbg_macro)]
53 #![allow(clippy::mixed_attributes_style)]
54 #![allow(clippy::print_stderr)]
55 #![allow(clippy::print_stdout)]
56 #![allow(clippy::single_char_pattern)]
57 #![allow(clippy::unwrap_used)]
58 #![allow(clippy::unchecked_time_subtraction)]
59 #![allow(clippy::useless_vec)]
60 #![allow(clippy::needless_pass_by_value)]
61 #![allow(clippy::string_slice)] use std::sync::Arc;
64
65 use super::*;
66
67 fn build_request(body: String, headers: &[(&str, &str)]) -> http::Request<RequestBody> {
68 let mut builder = http::Request::builder().method("GET").uri("/index.html");
69
70 for (name, value) in headers {
71 builder = builder.header(*name, *value);
72 }
73
74 let body = RequestBody::from(Arc::<str>::from(body));
75
76 builder.body(body).unwrap()
77 }
78
79 #[test]
80 fn format() {
81 fn chk_format(body: &str, content_length_expected: &str) {
82 let req = build_request(body.to_string(), &[]);
83
84 assert_eq!(
85 request_to_string(&req),
86 format!("GET /index.html HTTP/1.0\r\n{content_length_expected}\r\n{body}")
87 );
88
89 let req = build_request(body.to_string(), &[("X-Marsupial", "Opossum")]);
90 assert_eq!(
91 request_to_string(&req),
92 format!(
93 "GET /index.html HTTP/1.0\r\nx-marsupial: Opossum\r\n{content_length_expected}\r\n{body}",
94 )
95 );
96 }
97
98 chk_format("", "");
99 chk_format("hello", "Content-Length: 5\r\n");
100 }
101}