diff --git a/src/application.rs b/src/application.rs index ca5e8786c..3c64e9254 100644 --- a/src/application.rs +++ b/src/application.rs @@ -4,7 +4,7 @@ use std::rc::Rc; use handler::{AsyncResult, FromRequest, Handler, Responder, RouteHandler, WrapHandler}; use header::ContentEncoding; -use http::Method; +use http::{Method, StatusCode}; use httprequest::HttpRequest; use httpresponse::HttpResponse; use middleware::Middleware; @@ -49,14 +49,21 @@ impl PipelineHandler for Inner { &mut self, req: HttpRequest, htype: HandlerType, ) -> AsyncResult { match htype { - HandlerType::Normal(idx) => { - self.resources[idx].handle(req, Some(&mut self.default)) - } + HandlerType::Normal(idx) => match self.resources[idx].handle(req) { + Ok(result) => result, + Err(req) => match self.default.handle(req) { + Ok(result) => result, + Err(_) => AsyncResult::ok(HttpResponse::new(StatusCode::NOT_FOUND)), + }, + }, HandlerType::Handler(idx) => match self.handlers[idx] { PrefixHandlerType::Handler(_, ref mut hnd) => hnd.handle(req), PrefixHandlerType::Scope(_, ref mut hnd, _) => hnd.handle(req), }, - HandlerType::Default => self.default.handle(req, None), + HandlerType::Default => match self.default.handle(req) { + Ok(result) => result, + Err(_) => AsyncResult::ok(HttpResponse::new(StatusCode::NOT_FOUND)), + }, } } } diff --git a/src/resource.rs b/src/resource.rs index 2b9c8538b..49e9ab0cc 100644 --- a/src/resource.rs +++ b/src/resource.rs @@ -1,9 +1,9 @@ +use std::cell::RefCell; use std::marker::PhantomData; use std::rc::Rc; -use std::cell::RefCell; use futures::Future; -use http::{Method, StatusCode}; +use http::Method; use smallvec::SmallVec; use error::Error; @@ -282,21 +282,18 @@ impl ResourceHandler { } pub(crate) fn handle( - &mut self, mut req: HttpRequest, default: Option<&mut ResourceHandler>, - ) -> AsyncResult { + &mut self, mut req: HttpRequest, + ) -> Result, HttpRequest> { for route in &mut self.routes { if route.check(&mut req) { return if self.middlewares.borrow().is_empty() { - route.handle(req) + Ok(route.handle(req)) } else { - route.compose(req, Rc::clone(&self.middlewares)) + Ok(route.compose(req, Rc::clone(&self.middlewares))) }; } } - if let Some(resource) = default { - resource.handle(req, None) - } else { - AsyncResult::ok(HttpResponse::new(StatusCode::NOT_FOUND)) - } + + Err(req) } } diff --git a/src/scope.rs b/src/scope.rs index 37fb78908..e57db7632 100644 --- a/src/scope.rs +++ b/src/scope.rs @@ -7,7 +7,7 @@ use futures::{Async, Future, Poll}; use error::Error; use handler::{AsyncResult, AsyncResultItem, FromRequest, Responder, RouteHandler}; -use http::Method; +use http::{Method, StatusCode}; use httprequest::HttpRequest; use httpresponse::HttpResponse; use middleware::{ @@ -18,8 +18,9 @@ use pred::Predicate; use resource::ResourceHandler; use router::Resource; +type ScopeResource = Rc>>; type Route = UnsafeCell>>; -type ScopeResources = Rc>>)>>; +type ScopeResources = Rc)>>; type NestedInfo = (Resource, Route, Vec>>); /// Resources scope @@ -57,7 +58,7 @@ pub struct Scope { filters: Vec>>, nested: Vec>, middlewares: Rc>>>>, - default: Rc>>, + default: Option>, resources: ScopeResources, } @@ -71,7 +72,7 @@ impl Scope { nested: Vec::new(), resources: Rc::new(Vec::new()), middlewares: Rc::new(RefCell::new(Vec::new())), - default: Rc::new(UnsafeCell::new(ResourceHandler::default_not_found())), + default: None, } } @@ -135,7 +136,7 @@ impl Scope { nested: Vec::new(), resources: Rc::new(Vec::new()), middlewares: Rc::new(RefCell::new(Vec::new())), - default: Rc::new(UnsafeCell::new(ResourceHandler::default_not_found())), + default: None, }; let mut scope = f(scope); @@ -178,7 +179,7 @@ impl Scope { nested: Vec::new(), resources: Rc::new(Vec::new()), middlewares: Rc::new(RefCell::new(Vec::new())), - default: Rc::new(UnsafeCell::new(ResourceHandler::default_not_found())), + default: None, }; let mut scope = f(scope); @@ -229,8 +230,7 @@ impl Scope { let slf: &Scope = unsafe { &*(&self as *const _) }; for &(ref pattern, ref resource) in slf.resources.iter() { if pattern.pattern() == path { - let resource = unsafe { &mut *resource.get() }; - resource.method(method).with(f); + resource.borrow_mut().method(method).with(f); return self; } } @@ -245,7 +245,7 @@ impl Scope { ); Rc::get_mut(&mut self.resources) .expect("Can not use after configuration") - .push((pattern, Rc::new(UnsafeCell::new(handler)))); + .push((pattern, Rc::new(RefCell::new(handler)))); self } @@ -289,18 +289,21 @@ impl Scope { ); Rc::get_mut(&mut self.resources) .expect("Can not use after configuration") - .push((pattern, Rc::new(UnsafeCell::new(handler)))); + .push((pattern, Rc::new(RefCell::new(handler)))); self } /// Default resource to be used if no matching route could be found. - pub fn default_resource(self, f: F) -> Scope + pub fn default_resource(mut self, f: F) -> Scope where F: FnOnce(&mut ResourceHandler) -> R + 'static, { - let default = unsafe { &mut *self.default.as_ref().get() }; - f(default); + if self.default.is_none() { + self.default = + Some(Rc::new(RefCell::new(ResourceHandler::default_not_found()))); + } + f(&mut *self.default.as_ref().unwrap().borrow_mut()); self } @@ -327,17 +330,27 @@ impl RouteHandler for Scope { // recognize resources for &(ref pattern, ref resource) in self.resources.iter() { if pattern.match_with_params(&mut req, tail, false) { - let default = unsafe { &mut *self.default.as_ref().get() }; - if self.middlewares.borrow().is_empty() { - let resource = unsafe { &mut *resource.get() }; - return resource.handle(req, Some(default)); + return match resource.borrow_mut().handle(req) { + Ok(result) => result, + Err(req) => { + if let Some(ref default) = self.default { + match default.borrow_mut().handle(req) { + Ok(result) => result, + Err(_) => AsyncResult::ok(HttpResponse::new( + StatusCode::NOT_FOUND, + )), + } + } else { + AsyncResult::ok(HttpResponse::new(StatusCode::NOT_FOUND)) + } + } + }; } else { return AsyncResult::async(Box::new(Compose::new( req, Rc::clone(&self.middlewares), Rc::clone(&resource), - Some(Rc::clone(&self.default)), ))); } } @@ -365,16 +378,23 @@ impl RouteHandler for Scope { } // default handler - let default = unsafe { &mut *self.default.as_ref().get() }; if self.middlewares.borrow().is_empty() { - default.handle(req, None) - } else { + if let Some(ref default) = self.default { + match default.borrow_mut().handle(req) { + Ok(result) => result, + Err(_) => AsyncResult::ok(HttpResponse::new(StatusCode::NOT_FOUND)), + } + } else { + AsyncResult::ok(HttpResponse::new(StatusCode::NOT_FOUND)) + } + } else if let Some(ref default) = self.default { AsyncResult::async(Box::new(Compose::new( req, Rc::clone(&self.middlewares), - Rc::clone(&self.default), - None, + Rc::clone(default), ))) + } else { + unimplemented!() } } } @@ -417,8 +437,7 @@ struct ComposeInfo { count: usize, req: HttpRequest, mws: Rc>>>>, - default: Option>>>, - resource: Rc>>, + resource: Rc>>, } enum ComposeState { @@ -444,15 +463,13 @@ impl ComposeState { impl Compose { fn new( req: HttpRequest, mws: Rc>>>>, - resource: Rc>>, - default: Option>>>, + resource: Rc>>, ) -> Self { let mut info = ComposeInfo { count: 0, req, mws, resource, - default, }; let state = StartMiddlewares::init(&mut info); @@ -492,12 +509,10 @@ impl StartMiddlewares { let len = info.mws.borrow().len(); loop { if info.count == len { - let resource = unsafe { &mut *info.resource.get() }; - let reply = if let Some(ref default) = info.default { - let d = unsafe { &mut *default.as_ref().get() }; - resource.handle(info.req.clone(), Some(d)) - } else { - resource.handle(info.req.clone(), None) + let reply = { + let req = info.req.clone(); + let mut resource = info.resource.borrow_mut(); + resource.handle(req).unwrap() }; return WaitingResponse::init(info, reply); } else { @@ -531,12 +546,10 @@ impl StartMiddlewares { } loop { if info.count == len { - let resource = unsafe { &mut *info.resource.get() }; - let reply = if let Some(ref default) = info.default { - let d = unsafe { &mut *default.as_ref().get() }; - resource.handle(info.req.clone(), Some(d)) - } else { - resource.handle(info.req.clone(), None) + let reply = { + let req = info.req.clone(); + let mut resource = info.resource.borrow_mut(); + resource.handle(req).unwrap() }; return Some(WaitingResponse::init(info, reply)); } else { diff --git a/src/server/h1writer.rs b/src/server/h1writer.rs index 01477464b..d174964b9 100644 --- a/src/server/h1writer.rs +++ b/src/server/h1writer.rs @@ -163,18 +163,18 @@ impl Writer for H1Writer { // status line helpers::write_status_line(version, msg.status().as_u16(), &mut buffer); - SharedBytes::extend_from_slice_(buffer, reason); + buffer.extend_from_slice(reason); match body { Body::Empty => if req.method != Method::HEAD { - SharedBytes::put_slice(buffer, b"\r\ncontent-length: 0\r\n"); + buffer.extend_from_slice(b"\r\ncontent-length: 0\r\n"); } else { - SharedBytes::put_slice(buffer, b"\r\n"); + buffer.extend_from_slice(b"\r\n"); }, Body::Binary(ref bytes) => { helpers::write_content_length(bytes.len(), &mut buffer) } - _ => SharedBytes::put_slice(buffer, b"\r\n"), + _ => buffer.extend_from_slice(b"\r\n"), } // write headers @@ -218,7 +218,7 @@ impl Writer for H1Writer { self.settings.set_date(&mut buffer); } else { // msg eof - SharedBytes::extend_from_slice_(buffer, b"\r\n"); + buffer.extend_from_slice(b"\r\n"); } self.headers_size = buffer.len() as u32; } diff --git a/src/server/shared.rs b/src/server/shared.rs index a36c46176..064130fb7 100644 --- a/src/server/shared.rs +++ b/src/server/shared.rs @@ -1,9 +1,10 @@ -use bytes::{BufMut, BytesMut}; use std::cell::RefCell; use std::collections::VecDeque; use std::io; use std::rc::Rc; +use bytes::BytesMut; + use body::Binary; #[derive(Debug)] @@ -80,31 +81,13 @@ impl SharedBytes { #[inline] pub fn extend(&mut self, data: &Binary) { let buf = self.get_mut(); - let data = data.as_ref(); - buf.reserve(data.len()); - SharedBytes::put_slice(buf, data); + buf.extend_from_slice(data.as_ref()); } #[inline] pub fn extend_from_slice(&mut self, data: &[u8]) { let buf = self.get_mut(); - buf.reserve(data.len()); - SharedBytes::put_slice(buf, data); - } - - #[inline] - pub(crate) fn put_slice(buf: &mut BytesMut, src: &[u8]) { - let len = src.len(); - unsafe { - buf.bytes_mut()[..len].copy_from_slice(src); - buf.advance_mut(len); - } - } - - #[inline] - pub(crate) fn extend_from_slice_(buf: &mut BytesMut, data: &[u8]) { - buf.reserve(data.len()); - SharedBytes::put_slice(buf, data); + buf.extend_from_slice(data); } }