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