1
0
mirror of https://github.com/fafhrd91/actix-web synced 2024-11-24 00:21:08 +01:00

Handler::handle uses &self instead of mutabble reference

This commit is contained in:
Nikolay Kim 2018-06-21 17:07:54 +06:00
parent 5a9992736f
commit 3de9284592
12 changed files with 57 additions and 50 deletions

View File

@ -37,7 +37,7 @@
* Use tokio instead of tokio-core * Use tokio instead of tokio-core
* Use `&mut self` instead of `&self` for Middleware trait * For safety and performance reasons `Handler::handle()` uses `&self` instead of `&mut self`
* Added header `User-Agent: Actix-web/<current_version>` to default headers when building a request * Added header `User-Agent: Actix-web/<current_version>` to default headers when building a request

View File

@ -17,6 +17,8 @@
fn index((query, json): (Query<..>, Json<MyStruct)) -> impl Responder {} fn index((query, json): (Query<..>, Json<MyStruct)) -> impl Responder {}
``` ```
* `Handler::handle()` uses `&self` instead of `&mut self`
* Removed deprecated `HttpServer::threads()`, use * Removed deprecated `HttpServer::threads()`, use
[HttpServer::workers()](https://actix.rs/actix-web/actix_web/server/struct.HttpServer.html#method.workers) instead. [HttpServer::workers()](https://actix.rs/actix-web/actix_web/server/struct.HttpServer.html#method.workers) instead.

View File

@ -29,7 +29,7 @@ pub struct HttpApplication<S = ()> {
#[doc(hidden)] #[doc(hidden)]
pub struct Inner<S> { pub struct Inner<S> {
prefix: usize, prefix: usize,
default: Rc<RefCell<ResourceHandler<S>>>, default: Rc<ResourceHandler<S>>,
encoding: ContentEncoding, encoding: ContentEncoding,
resources: Vec<ResourceHandler<S>>, resources: Vec<ResourceHandler<S>>,
handlers: Vec<PrefixHandlerType<S>>, handlers: Vec<PrefixHandlerType<S>>,
@ -51,7 +51,7 @@ impl<S: 'static> PipelineHandler<S> for Inner<S> {
match htype { match htype {
HandlerType::Normal(idx) => match self.resources[idx].handle(req) { HandlerType::Normal(idx) => match self.resources[idx].handle(req) {
Ok(result) => result, Ok(result) => result,
Err(req) => match self.default.borrow_mut().handle(req) { Err(req) => match self.default.handle(req) {
Ok(result) => result, Ok(result) => result,
Err(_) => AsyncResult::ok(HttpResponse::new(StatusCode::NOT_FOUND)), Err(_) => AsyncResult::ok(HttpResponse::new(StatusCode::NOT_FOUND)),
}, },
@ -60,7 +60,7 @@ impl<S: 'static> PipelineHandler<S> for Inner<S> {
PrefixHandlerType::Handler(_, ref mut hnd) => hnd.handle(req), PrefixHandlerType::Handler(_, ref mut hnd) => hnd.handle(req),
PrefixHandlerType::Scope(_, ref mut hnd, _) => hnd.handle(req), PrefixHandlerType::Scope(_, ref mut hnd, _) => hnd.handle(req),
}, },
HandlerType::Default => match self.default.borrow_mut().handle(req) { HandlerType::Default => match self.default.handle(req) {
Ok(result) => result, Ok(result) => result,
Err(_) => AsyncResult::ok(HttpResponse::new(StatusCode::NOT_FOUND)), Err(_) => AsyncResult::ok(HttpResponse::new(StatusCode::NOT_FOUND)),
}, },
@ -138,9 +138,7 @@ impl<S: 'static> HttpApplication<S> {
impl<S: 'static> HttpHandler for HttpApplication<S> { impl<S: 'static> HttpHandler for HttpApplication<S> {
type Task = Pipeline<S, Inner<S>>; type Task = Pipeline<S, Inner<S>>;
fn handle( fn handle(&self, req: HttpRequest) -> Result<Pipeline<S, Inner<S>>, HttpRequest> {
&mut self, req: HttpRequest,
) -> Result<Pipeline<S, Inner<S>>, HttpRequest> {
let m = { let m = {
let path = req.path(); let path = req.path();
path.starts_with(&self.prefix) path.starts_with(&self.prefix)
@ -172,7 +170,7 @@ struct ApplicationParts<S> {
state: S, state: S,
prefix: String, prefix: String,
settings: ServerSettings, settings: ServerSettings,
default: Rc<RefCell<ResourceHandler<S>>>, default: Rc<ResourceHandler<S>>,
resources: Vec<(Resource, Option<ResourceHandler<S>>)>, resources: Vec<(Resource, Option<ResourceHandler<S>>)>,
handlers: Vec<PrefixHandlerType<S>>, handlers: Vec<PrefixHandlerType<S>>,
external: HashMap<String, Resource>, external: HashMap<String, Resource>,
@ -223,7 +221,7 @@ where
state, state,
prefix: "/".to_owned(), prefix: "/".to_owned(),
settings: ServerSettings::default(), settings: ServerSettings::default(),
default: Rc::new(RefCell::new(ResourceHandler::default_not_found())), default: Rc::new(ResourceHandler::default_not_found()),
resources: Vec::new(), resources: Vec::new(),
handlers: Vec::new(), handlers: Vec::new(),
external: HashMap::new(), external: HashMap::new(),
@ -335,7 +333,8 @@ where
T: FromRequest<S> + 'static, T: FromRequest<S> + 'static,
{ {
{ {
let parts: &mut ApplicationParts<S> = self.parts.as_mut().expect("Use after finish"); let parts: &mut ApplicationParts<S> =
self.parts.as_mut().expect("Use after finish");
let out = { let out = {
// get resource handler // get resource handler
@ -474,7 +473,9 @@ where
{ {
{ {
let parts = self.parts.as_mut().expect("Use after finish"); let parts = self.parts.as_mut().expect("Use after finish");
f(&mut parts.default.borrow_mut()); let default = Rc::get_mut(&mut parts.default)
.expect("Multiple App instance references are not allowed");
f(default);
} }
self self
} }
@ -707,7 +708,7 @@ struct BoxedApplication<S> {
impl<S: 'static> HttpHandler for BoxedApplication<S> { impl<S: 'static> HttpHandler for BoxedApplication<S> {
type Task = Box<HttpHandlerTask>; type Task = Box<HttpHandlerTask>;
fn handle(&mut self, req: HttpRequest) -> Result<Self::Task, HttpRequest> { fn handle(&self, req: HttpRequest) -> Result<Self::Task, HttpRequest> {
self.app.handle(req).map(|t| { self.app.handle(req).map(|t| {
let task: Self::Task = Box::new(t); let task: Self::Task = Box::new(t);
task task

View File

@ -654,7 +654,7 @@ impl<S: 'static> StaticFiles<S> {
impl<S: 'static> Handler<S> for StaticFiles<S> { impl<S: 'static> Handler<S> for StaticFiles<S> {
type Result = Result<AsyncResult<HttpResponse>, Error>; type Result = Result<AsyncResult<HttpResponse>, Error>;
fn handle(&mut self, req: HttpRequest<S>) -> Self::Result { fn handle(&self, req: HttpRequest<S>) -> Self::Result {
if !self.accessible { if !self.accessible {
Ok(self.default.handle(req)) Ok(self.default.handle(req))
} else { } else {

View File

@ -1,4 +1,3 @@
use std::cell::RefCell;
use std::marker::PhantomData; use std::marker::PhantomData;
use std::ops::Deref; use std::ops::Deref;
use std::rc::Rc; use std::rc::Rc;
@ -19,7 +18,7 @@ pub trait Handler<S>: 'static {
type Result: Responder; type Result: Responder;
/// Handle request /// Handle request
fn handle(&mut self, req: HttpRequest<S>) -> Self::Result; fn handle(&self, req: HttpRequest<S>) -> Self::Result;
} }
/// Trait implemented by types that generate responses for clients. /// Trait implemented by types that generate responses for clients.
@ -209,7 +208,7 @@ where
{ {
type Result = R; type Result = R;
fn handle(&mut self, req: HttpRequest<S>) -> R { fn handle(&self, req: HttpRequest<S>) -> R {
(self)(req) (self)(req)
} }
} }
@ -405,13 +404,13 @@ where
// /// Trait defines object that could be registered as resource route // /// Trait defines object that could be registered as resource route
pub(crate) trait RouteHandler<S>: 'static { pub(crate) trait RouteHandler<S>: 'static {
fn handle(&mut self, req: HttpRequest<S>) -> AsyncResult<HttpResponse>; fn handle(&self, req: HttpRequest<S>) -> AsyncResult<HttpResponse>;
fn has_default_resource(&self) -> bool { fn has_default_resource(&self) -> bool {
false false
} }
fn default_resource(&mut self, default: Rc<RefCell<ResourceHandler<S>>>) { fn default_resource(&mut self, _: Rc<ResourceHandler<S>>) {
unimplemented!() unimplemented!()
} }
} }
@ -444,7 +443,7 @@ where
R: Responder + 'static, R: Responder + 'static,
S: 'static, S: 'static,
{ {
fn handle(&mut self, req: HttpRequest<S>) -> AsyncResult<HttpResponse> { fn handle(&self, req: HttpRequest<S>) -> AsyncResult<HttpResponse> {
match self.h.handle(req.clone()).respond_to(&req) { match self.h.handle(req.clone()).respond_to(&req) {
Ok(reply) => reply.into(), Ok(reply) => reply.into(),
Err(err) => AsyncResult::err(err.into()), Err(err) => AsyncResult::err(err.into()),
@ -489,7 +488,7 @@ where
E: Into<Error> + 'static, E: Into<Error> + 'static,
S: 'static, S: 'static,
{ {
fn handle(&mut self, req: HttpRequest<S>) -> AsyncResult<HttpResponse> { fn handle(&self, req: HttpRequest<S>) -> AsyncResult<HttpResponse> {
let fut = (self.h)(req.clone()).map_err(|e| e.into()).then(move |r| { let fut = (self.h)(req.clone()).map_err(|e| e.into()).then(move |r| {
match r.respond_to(&req) { match r.respond_to(&req) {
Ok(reply) => match reply.into().into() { Ok(reply) => match reply.into().into() {

View File

@ -86,7 +86,7 @@ impl NormalizePath {
impl<S> Handler<S> for NormalizePath { impl<S> Handler<S> for NormalizePath {
type Result = HttpResponse; type Result = HttpResponse;
fn handle(&mut self, req: HttpRequest<S>) -> Self::Result { fn handle(&self, req: HttpRequest<S>) -> Self::Result {
if let Some(router) = req.router() { if let Some(router) = req.router() {
let query = req.query_string(); let query = req.query_string();
if self.merge { if self.merge {

View File

@ -282,9 +282,9 @@ impl<S: 'static> ResourceHandler<S> {
} }
pub(crate) fn handle( pub(crate) fn handle(
&mut self, mut req: HttpRequest<S>, &self, mut req: HttpRequest<S>,
) -> Result<AsyncResult<HttpResponse>, HttpRequest<S>> { ) -> Result<AsyncResult<HttpResponse>, HttpRequest<S>> {
for route in &mut self.routes { for route in &self.routes {
if route.check(&mut req) { if route.check(&mut req) {
return if self.middlewares.borrow().is_empty() { return if self.middlewares.borrow().is_empty() {
Ok(route.handle(req)) Ok(route.handle(req))

View File

@ -49,13 +49,13 @@ impl<S: 'static> Route<S> {
} }
#[inline] #[inline]
pub(crate) fn handle(&mut self, req: HttpRequest<S>) -> AsyncResult<HttpResponse> { pub(crate) fn handle(&self, req: HttpRequest<S>) -> AsyncResult<HttpResponse> {
self.handler.handle(req) self.handler.handle(req)
} }
#[inline] #[inline]
pub(crate) fn compose( pub(crate) fn compose(
&mut self, req: HttpRequest<S>, mws: Rc<RefCell<Vec<Box<Middleware<S>>>>>, &self, req: HttpRequest<S>, mws: Rc<RefCell<Vec<Box<Middleware<S>>>>>,
) -> AsyncResult<HttpResponse> { ) -> AsyncResult<HttpResponse> {
AsyncResult::async(Box::new(Compose::new(req, mws, self.handler.clone()))) AsyncResult::async(Box::new(Compose::new(req, mws, self.handler.clone())))
} }

View File

@ -18,7 +18,7 @@ use pred::Predicate;
use resource::ResourceHandler; use resource::ResourceHandler;
use router::Resource; use router::Resource;
type ScopeResource<S> = Rc<RefCell<ResourceHandler<S>>>; type ScopeResource<S> = Rc<ResourceHandler<S>>;
type Route<S> = UnsafeCell<Box<RouteHandler<S>>>; type Route<S> = UnsafeCell<Box<RouteHandler<S>>>;
type ScopeResources<S> = Rc<Vec<(Resource, ScopeResource<S>)>>; type ScopeResources<S> = Rc<Vec<(Resource, ScopeResource<S>)>>;
type NestedInfo<S> = (Resource, Route<S>, Vec<Box<Predicate<S>>>); type NestedInfo<S> = (Resource, Route<S>, Vec<Box<Predicate<S>>>);
@ -236,9 +236,13 @@ impl<S: 'static> Scope<S> {
} }
if found { if found {
for &(ref pattern, ref resource) in self.resources.iter() { let resources = Rc::get_mut(&mut self.resources)
.expect("Multiple scope references are not allowed");
for &mut (ref pattern, ref mut resource) in resources.iter_mut() {
if pattern.pattern() == path { if pattern.pattern() == path {
resource.borrow_mut().method(method).with(f); let res = Rc::get_mut(resource)
.expect("Multiple scope references are not allowed");
res.method(method).with(f);
break; break;
} }
} }
@ -253,7 +257,7 @@ impl<S: 'static> Scope<S> {
); );
Rc::get_mut(&mut self.resources) Rc::get_mut(&mut self.resources)
.expect("Can not use after configuration") .expect("Can not use after configuration")
.push((pattern, Rc::new(RefCell::new(handler)))); .push((pattern, Rc::new(handler)));
} }
self self
} }
@ -297,7 +301,7 @@ impl<S: 'static> Scope<S> {
); );
Rc::get_mut(&mut self.resources) Rc::get_mut(&mut self.resources)
.expect("Can not use after configuration") .expect("Can not use after configuration")
.push((pattern, Rc::new(RefCell::new(handler)))); .push((pattern, Rc::new(handler)));
self self
} }
@ -308,10 +312,13 @@ impl<S: 'static> Scope<S> {
F: FnOnce(&mut ResourceHandler<S>) -> R + 'static, F: FnOnce(&mut ResourceHandler<S>) -> R + 'static,
{ {
if self.default.is_none() { if self.default.is_none() {
self.default = self.default = Some(Rc::new(ResourceHandler::default_not_found()));
Some(Rc::new(RefCell::new(ResourceHandler::default_not_found()))); }
{
let default = Rc::get_mut(self.default.as_mut().unwrap())
.expect("Multiple copies of default handler");
f(default);
} }
f(&mut *self.default.as_ref().unwrap().borrow_mut());
self self
} }
@ -332,18 +339,18 @@ impl<S: 'static> Scope<S> {
} }
impl<S: 'static> RouteHandler<S> for Scope<S> { impl<S: 'static> RouteHandler<S> for Scope<S> {
fn handle(&mut self, mut req: HttpRequest<S>) -> AsyncResult<HttpResponse> { fn handle(&self, mut req: HttpRequest<S>) -> AsyncResult<HttpResponse> {
let tail = req.match_info().tail as usize; let tail = req.match_info().tail as usize;
// recognize resources // recognize resources
for &(ref pattern, ref resource) in self.resources.iter() { for &(ref pattern, ref resource) in self.resources.iter() {
if pattern.match_with_params(&mut req, tail, false) { if pattern.match_with_params(&mut req, tail, false) {
if self.middlewares.borrow().is_empty() { if self.middlewares.borrow().is_empty() {
return match resource.borrow_mut().handle(req) { return match resource.handle(req) {
Ok(result) => result, Ok(result) => result,
Err(req) => { Err(req) => {
if let Some(ref default) = self.default { if let Some(ref default) = self.default {
match default.borrow_mut().handle(req) { match default.handle(req) {
Ok(result) => result, Ok(result) => result,
Err(_) => AsyncResult::ok(HttpResponse::new( Err(_) => AsyncResult::ok(HttpResponse::new(
StatusCode::NOT_FOUND, StatusCode::NOT_FOUND,
@ -388,7 +395,7 @@ impl<S: 'static> RouteHandler<S> for Scope<S> {
// default handler // default handler
if self.middlewares.borrow().is_empty() { if self.middlewares.borrow().is_empty() {
if let Some(ref default) = self.default { if let Some(ref default) = self.default {
match default.borrow_mut().handle(req) { match default.handle(req) {
Ok(result) => result, Ok(result) => result,
Err(_) => AsyncResult::ok(HttpResponse::new(StatusCode::NOT_FOUND)), Err(_) => AsyncResult::ok(HttpResponse::new(StatusCode::NOT_FOUND)),
} }
@ -421,7 +428,7 @@ struct Wrapper<S: 'static> {
} }
impl<S: 'static, S2: 'static> RouteHandler<S2> for Wrapper<S> { impl<S: 'static, S2: 'static> RouteHandler<S2> for Wrapper<S> {
fn handle(&mut self, req: HttpRequest<S2>) -> AsyncResult<HttpResponse> { fn handle(&self, req: HttpRequest<S2>) -> AsyncResult<HttpResponse> {
self.scope.handle(req.change_state(Rc::clone(&self.state))) self.scope.handle(req.change_state(Rc::clone(&self.state)))
} }
} }
@ -453,7 +460,7 @@ struct ComposeInfo<S: 'static> {
count: usize, count: usize,
req: HttpRequest<S>, req: HttpRequest<S>,
mws: Rc<RefCell<Vec<Box<Middleware<S>>>>>, mws: Rc<RefCell<Vec<Box<Middleware<S>>>>>,
resource: Rc<RefCell<ResourceHandler<S>>>, resource: Rc<ResourceHandler<S>>,
} }
enum ComposeState<S: 'static> { enum ComposeState<S: 'static> {
@ -479,7 +486,7 @@ impl<S: 'static> ComposeState<S> {
impl<S: 'static> Compose<S> { impl<S: 'static> Compose<S> {
fn new( fn new(
req: HttpRequest<S>, mws: Rc<RefCell<Vec<Box<Middleware<S>>>>>, req: HttpRequest<S>, mws: Rc<RefCell<Vec<Box<Middleware<S>>>>>,
resource: Rc<RefCell<ResourceHandler<S>>>, resource: Rc<ResourceHandler<S>>,
) -> Self { ) -> Self {
let mut info = ComposeInfo { let mut info = ComposeInfo {
count: 0, count: 0,
@ -527,8 +534,7 @@ impl<S: 'static> StartMiddlewares<S> {
if info.count == len { if info.count == len {
let reply = { let reply = {
let req = info.req.clone(); let req = info.req.clone();
let mut resource = info.resource.borrow_mut(); info.resource.handle(req).unwrap()
resource.handle(req).unwrap()
}; };
return WaitingResponse::init(info, reply); return WaitingResponse::init(info, reply);
} else { } else {
@ -564,8 +570,7 @@ impl<S: 'static> StartMiddlewares<S> {
if info.count == len { if info.count == len {
let reply = { let reply = {
let req = info.req.clone(); let req = info.req.clone();
let mut resource = info.resource.borrow_mut(); info.resource.handle(req).unwrap()
resource.handle(req).unwrap()
}; };
return Some(WaitingResponse::init(info, reply)); return Some(WaitingResponse::init(info, reply));
} else { } else {

View File

@ -126,14 +126,14 @@ pub trait HttpHandler: 'static {
type Task: HttpHandlerTask; type Task: HttpHandlerTask;
/// Handle request /// Handle request
fn handle(&mut self, req: HttpRequest) -> Result<Self::Task, HttpRequest>; fn handle(&self, req: HttpRequest) -> Result<Self::Task, HttpRequest>;
} }
impl HttpHandler for Box<HttpHandler<Task = Box<HttpHandlerTask>>> { impl HttpHandler for Box<HttpHandler<Task = Box<HttpHandlerTask>>> {
type Task = Box<HttpHandlerTask>; type Task = Box<HttpHandlerTask>;
fn handle(&mut self, req: HttpRequest) -> Result<Box<HttpHandlerTask>, HttpRequest> { fn handle(&self, req: HttpRequest) -> Result<Box<HttpHandlerTask>, HttpRequest> {
self.as_mut().handle(req) self.as_ref().handle(req)
} }
} }

View File

@ -564,7 +564,7 @@ impl<S: 'static> TestRequest<S> {
/// with generated request. /// with generated request.
/// ///
/// This method panics is handler returns actor or async result. /// This method panics is handler returns actor or async result.
pub fn run<H: Handler<S>>(self, mut h: H) -> Result<HttpResponse, Error> { pub fn run<H: Handler<S>>(self, h: H) -> Result<HttpResponse, Error> {
let req = self.finish(); let req = self.finish();
let resp = h.handle(req.clone()); let resp = h.handle(req.clone());

View File

@ -56,7 +56,7 @@ where
{ {
type Result = AsyncResult<HttpResponse>; type Result = AsyncResult<HttpResponse>;
fn handle(&mut self, req: HttpRequest<S>) -> Self::Result { fn handle(&self, req: HttpRequest<S>) -> Self::Result {
let mut fut = WithHandlerFut { let mut fut = WithHandlerFut {
req, req,
started: false, started: false,
@ -192,7 +192,7 @@ where
{ {
type Result = AsyncResult<HttpResponse>; type Result = AsyncResult<HttpResponse>;
fn handle(&mut self, req: HttpRequest<S>) -> Self::Result { fn handle(&self, req: HttpRequest<S>) -> Self::Result {
let mut fut = WithAsyncHandlerFut { let mut fut = WithAsyncHandlerFut {
req, req,
started: false, started: false,