1use std::{
2 collections::HashMap,
3 io::{self, BufReader, Read},
4};
5
6use builders::Builder;
7use parse::parse_response;
8
9use crate::HttpStream;
10
11mod parse;
12
13#[derive(Builder)]
14pub struct HttpResponse {
15 #[builder(each = "header")]
16 headers: HashMap<String, String>,
17 #[builder(disabled = true)]
18 #[builder(def = { BufReader::new(HttpStream::dummy()) })]
19 stream: BufReader<HttpStream>,
20 #[builder(def = 200u16)]
21 status: u16,
22 #[builder(optional = true)]
23 body: Option<Vec<u8>>,
24 #[builder(def = 1.0)]
25 version: f32,
26}
27
28impl HttpResponse {
29 pub fn parse(stream: impl Into<HttpStream>) -> crate::Result<Self> {
30 let stream = BufReader::new(stream.into());
31 parse_response(stream)
32 }
33 #[inline]
34 #[must_use]
35 pub fn status(&self) -> u16 {
36 self.status
37 }
38
39 #[inline]
40 #[must_use]
41 pub fn content_length(&self) -> usize {
42 match self.headers.get("Content-Length") {
43 Some(l) => l.parse().unwrap_or(0),
44 None => 0,
45 }
46 }
47 #[inline]
49 #[must_use]
50 pub fn header(&self, key: &str) -> Option<&str> {
51 self.headers.get(key).map(String::as_str)
52 }
53
54 #[inline]
55 #[must_use]
56 pub fn version(&self) -> f32 {
57 self.version
58 }
59
60 #[inline]
61 #[must_use]
62 pub fn headers(&self) -> &HashMap<String, String> {
63 &self.headers
64 }
65
66 pub fn body(&mut self) -> Option<&[u8]> {
67 let len = self.content_length();
68 let mut buf: Vec<u8> = Vec::with_capacity(len);
69 if self.stream.read_to_end(&mut buf).is_ok() {
70 self.body = Some(buf);
71 }
72 self.body.as_deref()
73 }
74 pub fn write_to(&mut self, out: &mut dyn io::Write) -> io::Result<usize> {
75 let mut buf = [0_u8; 1024];
76 let mut total = 0;
77 while let Ok(n) = self.stream.read(&mut buf) {
78 out.write_all(&buf[0..n])?;
79 total += n;
80 if n == 0 {
81 break;
82 }
83 }
84 out.flush()?;
85 Ok(total)
86 }
87}