1 //! Server Responses
2 //!
3 //! These are responses sent by a `hyper::Server` to clients, after
4 //! receiving a request.
5 use std::any::{Any, TypeId};
6 use std::marker::PhantomData;
7 use std::mem;
8 use std::io::{self, Write};
9 use std::ptr;
10 use std::thread;
11 
12 use time::now_utc;
13 
14 use header;
15 use http::h1::{LINE_ENDING, HttpWriter};
16 use http::h1::HttpWriter::{ThroughWriter, ChunkedWriter, SizedWriter, EmptyWriter};
17 use status;
18 use net::{Fresh, Streaming};
19 use version;
20 
21 
22 /// The outgoing half for a Tcp connection, created by a `Server` and given to a `Handler`.
23 ///
24 /// The default `StatusCode` for a `Response` is `200 OK`.
25 ///
26 /// There is a `Drop` implementation for `Response` that will automatically
27 /// write the head and flush the body, if the handler has not already done so,
28 /// so that the server doesn't accidentally leave dangling requests.
29 #[derive(Debug)]
30 pub struct Response<'a, W: Any = Fresh> {
31     /// The HTTP version of this response.
32     pub version: version::HttpVersion,
33     // Stream the Response is writing to, not accessible through UnwrittenResponse
34     body: HttpWriter<&'a mut (Write + 'a)>,
35     // The status code for the request.
36     status: status::StatusCode,
37     // The outgoing headers on this response.
38     headers: &'a mut header::Headers,
39 
40     _writing: PhantomData<W>
41 }
42 
43 impl<'a, W: Any> Response<'a, W> {
44     /// The status of this response.
45     #[inline]
status(&self) -> status::StatusCode46     pub fn status(&self) -> status::StatusCode { self.status }
47 
48     /// The headers of this response.
49     #[inline]
headers(&self) -> &header::Headers50     pub fn headers(&self) -> &header::Headers { &*self.headers }
51 
52     /// Construct a Response from its constituent parts.
53     #[inline]
construct(version: version::HttpVersion, body: HttpWriter<&'a mut (Write + 'a)>, status: status::StatusCode, headers: &'a mut header::Headers) -> Response<'a, Fresh>54     pub fn construct(version: version::HttpVersion,
55                      body: HttpWriter<&'a mut (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     /// Deconstruct this Response into its constituent parts.
68     #[inline]
deconstruct(self) -> (version::HttpVersion, HttpWriter<&'a mut (Write + 'a)>, status::StatusCode, &'a mut header::Headers)69     pub fn deconstruct(self) -> (version::HttpVersion, HttpWriter<&'a mut (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 
write_head(&mut self) -> io::Result<Body>83     fn write_head(&mut self) -> io::Result<Body> {
84         debug!("writing head: {:?} {:?}", self.version, self.status);
85         try!(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         // can't do in match above, thanks borrowck
102         if body_type == Body::Chunked {
103             let encodings = match self.headers.get_mut::<header::TransferEncoding>() {
104                 Some(&mut header::TransferEncoding(ref mut encodings)) => {
105                     //TODO: check if chunked is already in encodings. use HashSet?
106                     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         try!(write!(&mut self.body, "{}", self.headers));
121         try!(write!(&mut self.body, "{}", LINE_ENDING));
122 
123         Ok(body_type)
124     }
125 }
126 
127 impl<'a> Response<'a, Fresh> {
128     /// Creates a new Response that can be used to write to a network stream.
129     #[inline]
new(stream: &'a mut (Write + 'a), headers: &'a mut header::Headers) -> Response<'a, Fresh>130     pub fn new(stream: &'a mut (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     /// Writes the body and ends the response.
142     ///
143     /// This is a shortcut method for when you have a response with a fixed
144     /// size, and would only need a single `write` call normally.
145     ///
146     /// # Example
147     ///
148     /// ```
149     /// # use hyper::server::Response;
150     /// fn handler(res: Response) {
151     ///     res.send(b"Hello World!").unwrap();
152     /// }
153     /// ```
154     ///
155     /// The above is the same, but shorter, than the longer:
156     ///
157     /// ```
158     /// # use hyper::server::Response;
159     /// use std::io::Write;
160     /// use hyper::header::ContentLength;
161     /// fn handler(mut res: Response) {
162     ///     let body = b"Hello World!";
163     ///     res.headers_mut().set(ContentLength(body.len() as u64));
164     ///     let mut res = res.start().unwrap();
165     ///     res.write_all(body).unwrap();
166     /// }
167     /// ```
168     #[inline]
send(self, body: &[u8]) -> io::Result<()>169     pub fn send(self, body: &[u8]) -> io::Result<()> {
170         self.headers.set(header::ContentLength(body.len() as u64));
171         let mut stream = try!(self.start());
172         try!(stream.write_all(body));
173         stream.end()
174     }
175 
176     /// Consume this Response<Fresh>, writing the Headers and Status and
177     /// creating a Response<Streaming>
start(mut self) -> io::Result<Response<'a, Streaming>>178     pub fn start(mut self) -> io::Result<Response<'a, Streaming>> {
179         let body_type = try!(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         // "copy" to change the phantom type
188         Ok(Response {
189             version: version,
190             body: stream,
191             status: status,
192             headers: headers,
193             _writing: PhantomData,
194         })
195     }
196     /// Get a mutable reference to the status.
197     #[inline]
status_mut(&mut self) -> &mut status::StatusCode198     pub fn status_mut(&mut self) -> &mut status::StatusCode { &mut self.status }
199 
200     /// Get a mutable reference to the Headers.
201     #[inline]
headers_mut(&mut self) -> &mut header::Headers202     pub fn headers_mut(&mut self) -> &mut header::Headers { self.headers }
203 }
204 
205 
206 impl<'a> Response<'a, Streaming> {
207     /// Flushes all writing of a response to the client.
208     #[inline]
end(self) -> io::Result<()>209     pub fn end(self) -> io::Result<()> {
210         trace!("ending");
211         let (_, body, _, _) = self.deconstruct();
212         try!(body.end());
213         Ok(())
214     }
215 }
216 
217 impl<'a> Write for Response<'a, Streaming> {
218     #[inline]
write(&mut self, msg: &[u8]) -> io::Result<usize>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]
flush(&mut self) -> io::Result<()>225     fn flush(&mut self) -> io::Result<()> {
226         self.body.flush()
227     }
228 }
229 
230 #[derive(PartialEq)]
231 enum Body {
232     Chunked,
233     Sized(u64),
234     Empty,
235 }
236 
237 impl<'a, T: Any> Drop for Response<'a, T> {
drop(&mut self)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)]
273 mod tests {
274     use header::Headers;
275     use mock::MockStream;
276     use super::Response;
277 
278     macro_rules! lines {
279         ($s:ident = $($line:pat),+) => ({
280             let s = String::from_utf8($s.write).unwrap();
281             let mut lines = s.split_terminator("\r\n");
282 
283             $(
284                 match lines.next() {
285                     Some($line) => (),
286                     other => panic!("line mismatch: {:?} != {:?}", other, stringify!($line))
287                 }
288             )+
289 
290             assert_eq!(lines.next(), None);
291         })
292     }
293 
294     #[test]
test_fresh_start()295     fn test_fresh_start() {
296         let mut headers = Headers::new();
297         let mut stream = MockStream::new();
298         {
299             let res = Response::new(&mut stream, &mut headers);
300             res.start().unwrap().deconstruct();
301         }
302 
303         lines! { stream =
304             "HTTP/1.1 200 OK",
305             _date,
306             _transfer_encoding,
307             ""
308         }
309     }
310 
311     #[test]
test_streaming_end()312     fn test_streaming_end() {
313         let mut headers = Headers::new();
314         let mut stream = MockStream::new();
315         {
316             let res = Response::new(&mut stream, &mut headers);
317             res.start().unwrap().end().unwrap();
318         }
319 
320         lines! { stream =
321             "HTTP/1.1 200 OK",
322             _date,
323             _transfer_encoding,
324             "",
325             "0",
326             "" // empty zero body
327         }
328     }
329 
330     #[test]
test_fresh_drop()331     fn test_fresh_drop() {
332         use status::StatusCode;
333         let mut headers = Headers::new();
334         let mut stream = MockStream::new();
335         {
336             let mut res = Response::new(&mut stream, &mut headers);
337             *res.status_mut() = StatusCode::NotFound;
338         }
339 
340         lines! { stream =
341             "HTTP/1.1 404 Not Found",
342             _date,
343             _transfer_encoding,
344             "",
345             "0",
346             "" // empty zero body
347         }
348     }
349 
350     // x86 windows msvc does not support unwinding
351     // See https://github.com/rust-lang/rust/issues/25869
352     #[cfg(not(all(windows, target_arch="x86", target_env="msvc")))]
353     #[test]
test_fresh_drop_panicing()354     fn test_fresh_drop_panicing() {
355         use std::thread;
356         use std::sync::{Arc, Mutex};
357 
358         use status::StatusCode;
359 
360         let stream = MockStream::new();
361         let stream = Arc::new(Mutex::new(stream));
362         let inner_stream = stream.clone();
363         let join_handle = thread::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             "" // empty zero body
386         }
387     }
388 
389 
390     #[test]
test_streaming_drop()391     fn test_streaming_drop() {
392         use std::io::Write;
393         use 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             "" // empty zero body
412         }
413     }
414 
415     #[test]
test_no_content()416     fn test_no_content() {
417         use 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 }
433