1use std::any::{Any, TypeId};
6use std::marker::PhantomData;
7use std::mem;
8use std::io::{self, Write};
9use std::ptr;
10use std::thread;
11
12use time::now_utc;
13
14use crate::header;
15use crate::http::h1::{LINE_ENDING, HttpWriter};
16use crate::http::h1::HttpWriter::{ThroughWriter, ChunkedWriter, SizedWriter, EmptyWriter};
17use crate::status;
18use crate::net::{Fresh, Streaming};
19use crate::version;
20
21
22#[derive(Debug)]
30pub struct Response<'a, W: Any = Fresh> {
31 pub version: version::HttpVersion,
33 pub body: HttpWriter<&'a mut (dyn Write + 'a)>,
35 pub status: status::StatusCode,
37 pub headers: &'a mut header::Headers,
39
40 _writing: PhantomData<W>
41}
42
43impl<'a, W: Any> Response<'a, W> {
44 #[inline]
46 pub fn status(&self) -> status::StatusCode { self.status }
47
48 #[inline]
50 pub fn headers(&self) -> &header::Headers { &*self.headers }
51
52 #[inline]
54 pub fn construct(version: version::HttpVersion,
55 body: HttpWriter<&'a mut (dyn Write + 'a)>,
56 status: status::StatusCode,
57 headers: &'a mut header::Headers) -> Response<'a, Fresh> {
58 Response {
59 status: status,
60 version: version,
61 body: body,
62 headers: headers,
63 _writing: PhantomData,
64 }
65 }
66
67 #[inline]
69 pub fn deconstruct(self) -> (version::HttpVersion, HttpWriter<&'a mut (dyn Write + 'a)>,
70 status::StatusCode, &'a mut header::Headers) {
71 unsafe {
72 let parts = (
73 self.version,
74 ptr::read(&self.body),
75 self.status,
76 ptr::read(&self.headers)
77 );
78 mem::forget(self);
79 parts
80 }
81 }
82
83 fn write_head(&mut self) -> io::Result<Body> {
84 debug!("writing head: {:?} {:?}", self.version, self.status);
85 write!(&mut self.body, "{} {}\r\n", self.version, self.status)?;
86
87 if !self.headers.has::<header::Date>() {
88 self.headers.set(header::Date(header::HttpDate(now_utc())));
89 }
90
91 let body_type = match self.status {
92 status::StatusCode::NoContent | status::StatusCode::NotModified => Body::Empty,
93 c if c.class() == status::StatusClass::Informational => Body::Empty,
94 _ => if let Some(cl) = self.headers.get::<header::ContentLength>() {
95 Body::Sized(**cl)
96 } else {
97 Body::Chunked
98 }
99 };
100
101 if body_type == Body::Chunked {
103 let encodings = match self.headers.get_mut::<header::TransferEncoding>() {
104 Some(&mut header::TransferEncoding(ref mut encodings)) => {
105 encodings.push(header::Encoding::Chunked);
107 false
108 },
109 None => true
110 };
111
112 if encodings {
113 self.headers.set::<header::TransferEncoding>(
114 header::TransferEncoding(vec![header::Encoding::Chunked]))
115 }
116 }
117
118
119 debug!("headers [\n{:?}]", self.headers);
120 write!(&mut self.body, "{}", self.headers)?;
121 write!(&mut self.body, "{}", LINE_ENDING)?;
122
123 Ok(body_type)
124 }
125}
126
127impl<'a> Response<'a, Fresh> {
128 #[inline]
130 pub fn new(stream: &'a mut (dyn Write + 'a), headers: &'a mut header::Headers) ->
131 Response<'a, Fresh> {
132 Response {
133 status: status::StatusCode::Ok,
134 version: version::HttpVersion::Http11,
135 headers: headers,
136 body: ThroughWriter(stream),
137 _writing: PhantomData,
138 }
139 }
140
141 #[inline]
169 pub fn send(self, body: &[u8]) -> io::Result<()> {
170 self.headers.set(header::ContentLength(body.len() as u64));
171 let mut stream = self.start()?;
172 stream.write_all(body)?;
173 stream.end()
174 }
175
176 pub fn start(mut self) -> io::Result<Response<'a, Streaming>> {
179 let body_type = self.write_head()?;
180 let (version, body, status, headers) = self.deconstruct();
181 let stream = match body_type {
182 Body::Chunked => ChunkedWriter(body.into_inner()),
183 Body::Sized(len) => SizedWriter(body.into_inner(), len),
184 Body::Empty => EmptyWriter(body.into_inner()),
185 };
186
187 Ok(Response {
189 version: version,
190 body: stream,
191 status: status,
192 headers: headers,
193 _writing: PhantomData,
194 })
195 }
196 #[inline]
198 pub fn status_mut(&mut self) -> &mut status::StatusCode { &mut self.status }
199
200 #[inline]
202 pub fn headers_mut(&mut self) -> &mut header::Headers { self.headers }
203}
204
205
206impl<'a> Response<'a, Streaming> {
207 #[inline]
209 pub fn end(self) -> io::Result<()> {
210 trace!("ending");
211 let (_, body, _, _) = self.deconstruct();
212 body.end()?;
213 Ok(())
214 }
215}
216
217impl<'a> Write for Response<'a, Streaming> {
218 #[inline]
219 fn write(&mut self, msg: &[u8]) -> io::Result<usize> {
220 debug!("write {:?} bytes", msg.len());
221 self.body.write(msg)
222 }
223
224 #[inline]
225 fn flush(&mut self) -> io::Result<()> {
226 self.body.flush()
227 }
228}
229
230#[derive(PartialEq)]
231enum Body {
232 Chunked,
233 Sized(u64),
234 Empty,
235}
236
237impl<'a, T: Any> Drop for Response<'a, T> {
238 fn drop(&mut self) {
239 if TypeId::of::<T>() == TypeId::of::<Fresh>() {
240 if thread::panicking() {
241 self.status = status::StatusCode::InternalServerError;
242 }
243
244 let mut body = match self.write_head() {
245 Ok(Body::Chunked) => ChunkedWriter(self.body.get_mut()),
246 Ok(Body::Sized(len)) => SizedWriter(self.body.get_mut(), len),
247 Ok(Body::Empty) => EmptyWriter(self.body.get_mut()),
248 Err(e) => {
249 debug!("error dropping request: {:?}", e);
250 return;
251 }
252 };
253 end(&mut body);
254 } else {
255 end(&mut self.body);
256 };
257
258
259 #[inline]
260 fn end<W: Write>(w: &mut W) {
261 match w.write(&[]) {
262 Ok(_) => match w.flush() {
263 Ok(_) => debug!("drop successful"),
264 Err(e) => debug!("error dropping request: {:?}", e)
265 },
266 Err(e) => debug!("error dropping request: {:?}", e)
267 }
268 }
269 }
270}
271
272#[cfg(test)]
273mod tests {
274 use crate::header::Headers;
275 use crate::mock::MockStream;
276 use crate::runtime;
277 use super::Response;
278
279 macro_rules! lines {
280 ($s:ident = $($line:pat),+) => ({
281 let s = String::from_utf8($s.write).unwrap();
282 let mut lines = s.split_terminator("\r\n");
283
284 $(
285 match lines.next() {
286 Some($line) => (),
287 other => panic!("line mismatch: {:?} != {:?}", other, stringify!($line))
288 }
289 )+
290
291 assert_eq!(lines.next(), None);
292 })
293 }
294
295 #[test]
296 fn test_fresh_start() {
297 let mut headers = Headers::new();
298 let mut stream = MockStream::new();
299 {
300 let res = Response::new(&mut stream, &mut headers);
301 res.start().unwrap().deconstruct();
302 }
303
304 lines! { stream =
305 "HTTP/1.1 200 OK",
306 _date,
307 _transfer_encoding,
308 ""
309 }
310 }
311
312 #[test]
313 fn test_streaming_end() {
314 let mut headers = Headers::new();
315 let mut stream = MockStream::new();
316 {
317 let res = Response::new(&mut stream, &mut headers);
318 res.start().unwrap().end().unwrap();
319 }
320
321 lines! { stream =
322 "HTTP/1.1 200 OK",
323 _date,
324 _transfer_encoding,
325 "",
326 "0",
327 "" }
329 }
330
331 #[test]
332 fn test_fresh_drop() {
333 use crate::status::StatusCode;
334 let mut headers = Headers::new();
335 let mut stream = MockStream::new();
336 {
337 let mut res = Response::new(&mut stream, &mut headers);
338 *res.status_mut() = StatusCode::NotFound;
339 }
340
341 lines! { stream =
342 "HTTP/1.1 404 Not Found",
343 _date,
344 _transfer_encoding,
345 "",
346 "0",
347 "" }
349 }
350
351 #[cfg(not(all(windows, target_arch="x86", target_env="msvc")))]
354 #[test]
355 fn test_fresh_drop_panicing() {
356 use std::sync::{Arc, Mutex};
357
358 use crate::status::StatusCode;
359
360 let stream = crate::mock::MockStream::new();
361 let stream = Arc::new(Mutex::new(stream));
362 let inner_stream = stream.clone();
363 let join_handle = runtime::spawn(move || {
364 let mut headers = Headers::new();
365 let mut stream = inner_stream.lock().unwrap();
366 let mut res = Response::new(&mut *stream, &mut headers);
367 *res.status_mut() = StatusCode::NotFound;
368
369 panic!("inside")
370 });
371
372 assert!(join_handle.join().is_err());
373
374 let stream = match stream.lock() {
375 Err(poisoned) => poisoned.into_inner().clone(),
376 Ok(_) => unreachable!()
377 };
378
379 lines! { stream =
380 "HTTP/1.1 500 Internal Server Error",
381 _date,
382 _transfer_encoding,
383 "",
384 "0",
385 "" }
387 }
388
389
390 #[test]
391 fn test_streaming_drop() {
392 use std::io::Write;
393 use crate::status::StatusCode;
394 let mut headers = Headers::new();
395 let mut stream = MockStream::new();
396 {
397 let mut res = Response::new(&mut stream, &mut headers);
398 *res.status_mut() = StatusCode::NotFound;
399 let mut stream = res.start().unwrap();
400 stream.write_all(b"foo").unwrap();
401 }
402
403 lines! { stream =
404 "HTTP/1.1 404 Not Found",
405 _date,
406 _transfer_encoding,
407 "",
408 "3",
409 "foo",
410 "0",
411 "" }
413 }
414
415 #[test]
416 fn test_no_content() {
417 use crate::status::StatusCode;
418 let mut headers = Headers::new();
419 let mut stream = MockStream::new();
420 {
421 let mut res = Response::new(&mut stream, &mut headers);
422 *res.status_mut() = StatusCode::NoContent;
423 res.start().unwrap();
424 }
425
426 lines! { stream =
427 "HTTP/1.1 204 No Content",
428 _date,
429 ""
430 }
431 }
432}