1use super::date;
2use super::status;
3use super::writer;
4
5use bytes::{BufMut, BytesMut};
6use tokio::prelude::*;
7
8pub struct Response {
25 body: Option<Vec<u8>>,
27 status: Option<&'static str>,
28 headers: Vec<(&'static str, &'static str)>,
29}
30
31impl Response {
32 pub fn new() -> Response {
38 Response {
39 body: None,
40 status: None,
41 headers: Vec::with_capacity(50),
42 }
43 }
44
45 pub fn status(&mut self, status: &'static str) {
51 self.status = Some(status);
52 }
53
54 pub fn header(&mut self, name: &'static str, value: &'static str) {
60 self.headers.push((name, value));
61 }
62
63 pub fn body_vec(&mut self, body: Vec<u8>) {
71 self.body = Some(body);
72 }
73
74 pub fn body_str(&mut self, body: &str) {
80 self.body = Some(body.as_bytes().to_vec());
81 }
82
83 pub fn write<S: AsyncWrite>(&self, writer: S) -> writer::WriteAll<S> {
92 let mut buf = BytesMut::with_capacity(4096);
94
95 push(&mut buf, b"HTTP/1.1 ");
97 push(&mut buf, self.status.unwrap_or(status::OK).as_bytes());
98 push(&mut buf, b"\r\n");
99
100 for val in &self.headers {
102 push(&mut buf, val.0.as_bytes());
103 push(&mut buf, b": ");
104 push(&mut buf, val.1.as_bytes());
105 push(&mut buf, b"\r\n");
106 }
107
108 date::set_date_header(&mut buf);
110
111 match &self.body {
113 Some(body) => {
114 push(&mut buf, b"content-length: ");
115 push(&mut buf, body.len().to_string().as_bytes());
116 push(&mut buf, b"\r\n\r\n");
117 push(&mut buf, body.as_slice());
118 }
119 None => push(&mut buf, b"content-length: 0\r\n\r\n"),
120 };
121
122 writer::write_all(writer, buf)
124 }
125}
126
127pub(crate) fn push(buf: &mut BytesMut, data: &[u8]) {
129 if buf.remaining_mut() < data.len() {
130 buf.reserve(data.len());
131 }
132
133 unsafe {
134 buf.bytes_mut()[..data.len()].copy_from_slice(data);
135 buf.advance_mut(data.len());
136 }
137}