From f6ff056b8a496d1e629ecab16ba50c7f8e5094a3 Mon Sep 17 00:00:00 2001 From: Nikolay Kim Date: Fri, 10 Jan 2020 11:26:54 +0600 Subject: [PATCH] Fix panic with already borrowed: BorrowMutError #1263 --- actix-identity/CHANGES.md | 4 +++ actix-identity/Cargo.toml | 7 ++--- actix-identity/src/lib.rs | 60 +++++++++++++++++++++++++++++++++++++-- 3 files changed, 65 insertions(+), 6 deletions(-) diff --git a/actix-identity/CHANGES.md b/actix-identity/CHANGES.md index 8e89acc15..594c21388 100644 --- a/actix-identity/CHANGES.md +++ b/actix-identity/CHANGES.md @@ -1,5 +1,9 @@ # Changes +## [0.2.1] - 2020-01-10 + +* Fix panic with already borrowed: BorrowMutError #1263 + ## [0.2.0] - 2019-12-20 * Use actix-web 2.0 diff --git a/actix-identity/Cargo.toml b/actix-identity/Cargo.toml index b30246f0b..8cd6b1271 100644 --- a/actix-identity/Cargo.toml +++ b/actix-identity/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "actix-identity" -version = "0.2.0" +version = "0.2.1" authors = ["Nikolay Kim "] description = "Identity service for actix web framework." readme = "README.md" @@ -10,15 +10,14 @@ repository = "https://github.com/actix/actix-web.git" documentation = "https://docs.rs/actix-identity/" license = "MIT/Apache-2.0" edition = "2018" -workspace = ".." [lib] name = "actix_identity" path = "src/lib.rs" [dependencies] -actix-web = { version = "2.0.0-rc", default-features = false, features = ["secure-cookies"] } -actix-service = "1.0.1" +actix-web = { version = "2.0.0", default-features = false, features = ["secure-cookies"] } +actix-service = "1.0.2" futures = "0.3.1" serde = "1.0" serde_json = "1.0" diff --git a/actix-identity/src/lib.rs b/actix-identity/src/lib.rs index b10a419dd..3b9626991 100644 --- a/actix-identity/src/lib.rs +++ b/actix-identity/src/lib.rs @@ -251,6 +251,15 @@ pub struct IdentityServiceMiddleware { service: Rc>, } +impl Clone for IdentityServiceMiddleware { + fn clone(&self) -> Self { + Self { + backend: self.backend.clone(), + service: self.service.clone(), + } + } +} + impl Service for IdentityServiceMiddleware where B: 'static, @@ -279,7 +288,9 @@ where req.extensions_mut() .insert(IdentityItem { id, changed: false }); - let mut res = srv.borrow_mut().call(req).await?; + // https://github.com/actix/actix-web/issues/1263 + let fut = { srv.borrow_mut().call(req) }; + let mut res = fut.await?; let id = res.request().extensions_mut().remove::(); if let Some(id) = id { @@ -606,9 +617,10 @@ mod tests { use std::borrow::Borrow; use super::*; + use actix_service::into_service; use actix_web::http::StatusCode; use actix_web::test::{self, TestRequest}; - use actix_web::{web, App, Error, HttpResponse}; + use actix_web::{error, web, App, Error, HttpResponse}; const COOKIE_KEY_MASTER: [u8; 32] = [0; 32]; const COOKIE_NAME: &'static str = "actix_auth"; @@ -1045,6 +1057,7 @@ mod tests { assert_logged_in(resp, Some(COOKIE_LOGIN)).await; } + // https://github.com/actix/actix-web/issues/1263 #[actix_rt::test] async fn test_identity_cookie_updated_on_visit_deadline() { let mut srv = create_identity_server(|c| { @@ -1069,4 +1082,47 @@ mod tests { ); assert_logged_in(resp, Some(COOKIE_LOGIN)).await; } + + #[actix_rt::test] + async fn test_borrowed_mut_error() { + use futures::future::{lazy, ok, Ready}; + + struct Ident; + impl IdentityPolicy for Ident { + type Future = Ready, Error>>; + type ResponseFuture = Ready>; + + fn from_request(&self, _: &mut ServiceRequest) -> Self::Future { + ok(Some("test".to_string())) + } + + fn to_response( + &self, + _: Option, + _: bool, + _: &mut ServiceResponse, + ) -> Self::ResponseFuture { + ok(()) + } + } + + let mut srv = IdentityServiceMiddleware { + backend: Rc::new(Ident), + service: Rc::new(RefCell::new(into_service(|_: ServiceRequest| { + async move { + actix_rt::time::delay_for(std::time::Duration::from_secs(100)).await; + Err::(error::ErrorBadRequest("error")) + } + }))), + }; + + let mut srv2 = srv.clone(); + let req = TestRequest::default().to_srv_request(); + actix_rt::spawn(async move { + let _ = srv2.call(req).await; + }); + actix_rt::time::delay_for(std::time::Duration::from_millis(50)).await; + + let _ = lazy(|cx| srv.poll_ready(cx)).await; + } }