diff --git a/actix_redis/all.html b/actix_redis/all.html index c538c3a4f..43f7fdb76 100644 --- a/actix_redis/all.html +++ b/actix_redis/all.html @@ -1,4 +1,6 @@ -
Crate actix_redis
Version 0.9.1
Back to index
Enum Error
actix_redis
pub enum Error { Redis(Error), NotConnected, @@ -16,16 +18,20 @@
impl !RefUnwindSafe for Error
impl Send for Error
impl Sync for Error
impl Unpin for Error
impl !UnwindSafe for Error
impl<T> Any for T where T: 'static + ?Sized,
fn type_id(&self) -> TypeId
Gets the TypeId of self. Read more
TypeId
self
impl<T> Borrow<T> for T where T: ?Sized,
fn borrow(&self) -> &T
Immutably borrows from an owned value. Read more
impl<T> BorrowMut<T> for T where T: ?Sized,
fn borrow_mut(&mut self) -> &mut T
Mutably borrows from an owned value. Read more
impl<T> From<T> for T
fn from(t: T) -> T
Performs the conversion.
impl<T> Instrument for T
fn instrument(self, span: Span) -> Instrumented<Self>
Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Span
Instrumented
fn in_current_span(self) -> Instrumented<Self>
Instruments this type with the [current] Span, returning an Instrumented wrapper. Read more
impl<T, U> Into<U> for T where U: From<T>,
fn into(self) -> U
Instruments this type with the provided Span, returning an +Instrumented wrapper. Read more
Instruments this type with the current Span, returning an +Instrumented wrapper. Read more
impl<T> Same<T> for T
type Output = T
Should always be Self
Self
impl<T> ToString for T where T: Display + ?Sized,
default fn to_string(&self) -> String
Converts the given value to a String. Read more
String
impl<T, U> TryFrom<U> for T where U: Into<T>,
type Error = Infallible
The type returned in the event of a conversion error.
fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>
impl<T, U> TryInto<U> for T where U: TryFrom<T>,
type Error = <U as TryFrom<T>>::Error
fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>
impl<V, T> VZip<V> for T where V: MultiLane<T>,
fn vzip(self) -> V
Enum RespError
pub enum RespError { Internal(String), IO(Error), @@ -19,29 +21,32 @@ chains of futures; but it occurring at runtime should be considered a catastroph failure. If any error is propagated this way that needs to be handled, then it should be made into a proper option. -
If any error is propagated this way that needs to be handled, then it should be made into a proper option.
impl Debug for Error
fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), Error>
Formats the value using the given formatter. Read more
impl Display for Error
impl Error for Error
fn source(&self) -> Option<&(dyn Error + 'static)>
The lower-level source of this error, if any. Read more
fn backtrace(&self) -> Option<&Backtrace>
backtrace
Returns a stack backtrace, if available, of where this error occurred. Read more
fn description(&self) -> &str
use the Display impl or to_string()
if let Err(e) = "xc".parse::<u32>() { // Print e itself, no need for description(). eprintln!("Error: {}", e); } Read more
if let Err(e) = "xc".parse::<u32>() { // Print
itself, no need for description(). eprintln!("Error: {}", e); }
fn cause(&self) -> Option<&dyn Error>
replaced by Error::source, which can support downcasting
impl From<Error> for Error
fn from(err: Error) -> Error
fn from(original: Error) -> Error
impl<T> From<TrySendError<T>> for Error where T: 'static + Send,
fn from(err: TrySendError<T>) -> Error
Enum RespValue
pub enum RespValue { Nil, Array(Vec<RespValue>), @@ -21,34 +23,40 @@ https://redis.io/topics/protocol#resp-integers arguments, e.g. RPUSH This will panic if called for anything other than arrays
This will panic if called for anything other than arrays
impl Clone for RespValue
fn clone(&self) -> RespValue
Returns a copy of the value. Read more
fn clone_from(&mut self, source: &Self)
Performs copy-assignment from source. Read more
source
impl Debug for RespValue
impl Eq for RespValue
impl<'a> From<&'a [u8]> for RespValue
fn from(from: &'a [u8]) -> RespValue
impl<'a> From<&'a String> for RespValue
fn from(from: &'a String) -> RespValue
impl<'a> From<&'a str> for RespValue
fn from(from: &'a str) -> RespValue
impl<'a> From<String> for RespValue
fn from(from: String) -> RespValue
impl<'a> From<Vec<u8>> for RespValue
fn from(from: Vec<u8>) -> RespValue
impl<'a> From<usize> for RespValue
fn from(from: usize) -> RespValue
impl FromResp for RespValue
fn from_resp_int(resp: RespValue) -> Result<RespValue, Error>
fn from_resp(resp: RespValue) -> Result<Self, Error>
Return a Result containing either Self or Error. Errors can occur due to either: a) the particular RespValue being incompatible with the required type, or b) a remote Redis error occuring. Read more
Result
Error
RespValue
impl PartialEq<RespValue> for RespValue
fn eq(&self, other: &RespValue) -> bool
This method tests for self and other values to be equal, and is used by ==. Read more
other
==
Return a Result containing either Self or Error. Errors can occur due to either: a) the particular +RespValue being incompatible with the required type, or b) a remote Redis error occuring. Read more
This method tests for self and other values to be equal, and is used +by ==. Read more
fn ne(&self, other: &RespValue) -> bool
This method tests for !=.
!=
impl StructuralEq for RespValue
impl StructuralPartialEq for RespValue
impl RefUnwindSafe for RespValue
impl Send for RespValue
impl Sync for RespValue
impl Unpin for RespValue
impl UnwindSafe for RespValue
impl<Q, K> Equivalent<K> for Q where K: Borrow<Q> + ?Sized, Q: Eq + ?Sized,
fn equivalent(&self, key: &K) -> bool
Compare self to key and return true if they are equal.
key
true
impl<T> ToOwned for T where T: Clone,
type Owned = T
The resulting type after obtaining ownership.
fn to_owned(&self) -> T
Creates owned data from borrowed data, usually by cloning. Read more
fn clone_into(&self, target: &mut T)
toowned_clone_into
recently added
Uses borrowed data to replace owned data, usually by cloning. Read more
Enum SameSite
pub enum SameSite { Strict, Lax, @@ -15,7 +17,7 @@ This library automatically sets the "Secure" flag on cookies when same_site is set to SameSite::None as long as secure is not explicitly set to false. If the SameSite attribute is not present (by not setting SameSite -initally or passing None to Cookie::set_same_site()), then the cookie +initally or passing None to Cookie::set_same_site()), then the cookie will be sent as normal. Note: This cookie attribute is an HTTP draft! Its meaning and definition are subject to change. @@ -52,31 +54,36 @@ definition are subject to change. assert!(!none.is_lax()); assert!(!none.is_strict());
same_site
SameSite::None
secure
false
If the SameSite attribute is not present (by not setting SameSite -initally or passing None to Cookie::set_same_site()), then the cookie +initally or passing None to Cookie::set_same_site()), then the cookie will be sent as normal.
SameSite
None
Cookie::set_same_site()
Note: This cookie attribute is an HTTP draft! Its meaning and definition are subject to change.
impl Clone for SameSite
fn clone(&self) -> SameSite
impl Copy for SameSite
impl Debug for SameSite
impl Display for SameSite
impl Eq for SameSite
impl Hash for SameSite
fn hash<__H>(&self, state: &mut __H) where __H: Hasher,
Feeds this value into the given [Hasher]. Read more
Hasher
fn hash_slice<H>(data: &[Self], state: &mut H) where H: Hasher,
Feeds a slice of this type into the given [Hasher]. Read more
impl PartialEq<SameSite> for SameSite
fn eq(&self, other: &SameSite) -> bool
Feeds this value into the given Hasher. Read more
Feeds a slice of this type into the given Hasher. Read more
#[must_use]fn ne(&self, other: &Rhs) -> bool
impl StructuralEq for SameSite
impl StructuralPartialEq for SameSite
impl RefUnwindSafe for SameSite
impl Send for SameSite
impl Sync for SameSite
impl Unpin for SameSite
impl UnwindSafe for SameSite
See all actix_redis's items
Redis integration for Actix framework.
Struct Command
pub struct Command(pub RespValue);
Command for send data to Redis
impl Debug for Command
fn fmt(&self, f: &mut Formatter<'_>) -> Result
impl Handler<Command> for RedisActor
type Result = ResponseFuture<Result<RespValue, Error>>
The type of value that this handler will return. Read more
fn handle(&mut self, msg: Command, _: &mut Self::Context) -> Self::Result
This method is called for every message received by this actor.
impl Message for Command
type Result = Result<RespValue, Error>
The type of value that this message will resolved with if it is successful. Read more
The type of value that this message will resolved with if it is +successful. Read more
impl RefUnwindSafe for Command
impl Send for Command
impl Sync for Command
impl Unpin for Command
impl UnwindSafe for Command
Struct RedisActor
pub struct RedisActor { /* fields omitted */ }
Redis comminucation actor
impl RedisActor
pub fn start<S: Into<String>>(addr: S) -> Addr<RedisActor>
Start new Supervisor with RedisActor.
Supervisor
RedisActor
impl Actor for RedisActor
type Context = Context<Self>
Actor execution context type
fn stopping(&mut self, ctx: &mut Self::Context) -> Running
Called after an actor is in Actor::Stopping state. Read more
Actor::Stopping
fn stopped(&mut self, ctx: &mut Self::Context)
Called after an actor is stopped. Read more
fn start(self) -> Addr<Self> where Self: Actor<Context = Context<Self>>,
Start a new asynchronous actor, returning its address. Read more
fn start_default() -> Addr<Self> where Self: Actor<Context = Context<Self>> + Default,
Construct and start a new asynchronous actor, returning its address. Read more
Construct and start a new asynchronous actor, returning its +address. Read more
fn start_in_arbiter<F>(arb: &Arbiter, f: F) -> Addr<Self> where F: FnOnce(&mut Context<Self>) -> Self + Send + 'static, Self: Actor<Context = Context<Self>>,
Start new actor in arbiter's thread.
fn create<F>(f: F) -> Addr<Self> where F: FnOnce(&mut Context<Self>) -> Self, Self: Actor<Context = Context<Self>>,
Start a new asynchronous actor given a Context. Read more
Context
impl StreamHandler<Result<RespValue, Error>> for RedisActor
fn handle(&mut self, msg: Result<RespValue, RespError>, ctx: &mut Self::Context)
Method is called for every message received by this Actor
fn started(&mut self, ctx: &mut Self::Context)
Method is called when stream get polled first time.
fn finished(&mut self, ctx: &mut Self::Context)
Method is called when stream finishes. Read more
fn add_stream<S>(fut: S, ctx: &mut Self::Context) -> SpawnHandle where I: 'static, S: Stream<Item = I> + 'static, Self::Context: AsyncContext<Self>,
This method register stream to an actor context and allows to handle Stream in similar way as normal actor messages. Read more
Stream
This method register stream to an actor context and +allows to handle Stream in similar way as normal actor messages. Read more
impl Supervised for RedisActor
fn restarting(&mut self, _: &mut Self::Context)
Called when the supervisor restarts a failed actor.
impl WriteHandler<Error> for RedisActor
fn error(&mut self, err: Error, _: &mut Self::Context) -> Running
Called when the writer emits error. Read more
Called when the writer finishes. Read more
impl !RefUnwindSafe for RedisActor
impl !Send for RedisActor
impl !Sync for RedisActor
impl Unpin for RedisActor
impl !UnwindSafe for RedisActor
Struct RedisSession
pub struct RedisSession(_);
Use redis as session storage.
You need to pass an address of the redis server and random value to the constructor of RedisSession. This is private key for cookie @@ -26,19 +28,24 @@ connection is secure - i.e. https
RedisSession
https
type Transform = RedisSessionMiddleware<S>
The TransformService value created by this factory
TransformService
type Future = Ready<Result<Self::Transform, Self::InitError>>
The future response value.
fn new_transform(&self, service: S) -> Self::Future
Creates and returns a new Transform component, asynchronously
fn map_init_err<F, E>(self, f: F) -> TransformMapInitErr<Self, S, F, E> where F: Fn(Self::InitError) -> E + Clone,
Map this transforms's factory error to a different error, returning a new transform service factory. Read more
Map this transforms's factory error to a different error, +returning a new transform service factory. Read more
impl !RefUnwindSafe for RedisSession
impl !Send for RedisSession
impl !Sync for RedisSession
impl Unpin for RedisSession
impl !UnwindSafe for RedisSession
"+code.outerHTML+"
fn:
fn
mod
struct
enum
trait
type
macro
const
vec -> usize
* -> vec
str,u8
String,struct:Vec,test
\"string\"
vec::Vec
"+x+"
Settings
1 2 3 diff --git a/src/actix_redis/redis.rs.html b/src/actix_redis/redis.rs.html index fa556fec9..fd809c6ca 100644 --- a/src/actix_redis/redis.rs.html +++ b/src/actix_redis/redis.rs.html @@ -1,4 +1,6 @@ -redis.rs.html -- source☰All crates? +redis.rs.html -- source + +☰All crates? 1 2 3 @@ -178,13 +180,13 @@ pub struct RedisActor { addr: String, backoff: ExponentialBackoff, - cell: Option<actix::io::FramedWrite<RespValue, WriteHalf<TcpStream>, RespCodec>>, - queue: VecDeque<oneshot::Sender<Result<RespValue, Error>>>, + cell: Option<actix::io::FramedWrite<RespValue, WriteHalf<TcpStream>, RespCodec>>, + queue: VecDeque<oneshot::Sender<Result<RespValue, Error>>>, } impl RedisActor { /// Start new `Supervisor` with `RedisActor`. - pub fn start<S: Into<String>>(addr: S) -> Addr<RedisActor> { + pub fn start<S: Into<String>>(addr: S) -> Addr<RedisActor> { let addr = addr.into(); let mut backoff = ExponentialBackoff::default(); @@ -207,8 +209,8 @@ .send(Connect::host(self.addr.as_str())) .into_actor(self) .map(|res, act, ctx| match res { - Ok(res) => match res { - Ok(stream) => { + Ok(res) => match res { + Ok(stream) => { info!("Connected to redis server: {}", act.addr); let (r, w) = split(stream); @@ -222,7 +224,7 @@ act.backoff.reset(); } - Err(err) => { + Err(err) => { error!("Can not connect to redis server: {}", err); // re-connect with backoff time. // we stop current context, supervisor will restart it. @@ -231,7 +233,7 @@ } } }, - Err(err) => { + Err(err) => { error!("Can not connect to redis server: {}", err); // re-connect with backoff time. // we stop current context, supervisor will restart it. @@ -254,22 +256,22 @@ } impl actix::io::WriteHandler<io::Error> for RedisActor { - fn error(&mut self, err: io::Error, _: &mut Self::Context) -> Running { + fn error(&mut self, err: io::Error, _: &mut Self::Context) -> Running { warn!("Redis connection dropped: {} error: {}", self.addr, err); Running::Stop } } -impl StreamHandler<Result<RespValue, RespError>> for RedisActor { +impl StreamHandler<Result<RespValue, RespError>> for RedisActor { fn handle(&mut self, msg: Result<RespValue, RespError>, ctx: &mut Self::Context) { match msg { - Err(e) => { + Err(e) => { if let Some(tx) = self.queue.pop_front() { let _ = tx.send(Err(e.into())); } ctx.stop(); } - Ok(val) => { + Ok(val) => { if let Some(tx) = self.queue.pop_front() { let _ = tx.send(Ok(val)); } @@ -279,9 +281,9 @@ } impl Handler<Command> for RedisActor { - type Result = ResponseFuture<Result<RespValue, Error>>; + type Result = ResponseFuture<Result<RespValue, Error>>; - fn handle(&mut self, msg: Command, _: &mut Self::Context) -> Self::Result { + fn handle(&mut self, msg: Command, _: &mut Self::Context) -> Self::Result { let (tx, rx) = oneshot::channel(); if let Some(ref mut cell) = self.cell { self.queue.push_back(tx); @@ -291,8 +293,8 @@ } Box::pin(rx.map(|res| match res { - Ok(res) => res, - Err(_) => Err(Error::Disconnected), + Ok(res) => res, + Err(_) => Err(Error::Disconnected), })) } } diff --git a/src/actix_redis/session.rs.html b/src/actix_redis/session.rs.html index dcdf3e3d6..029303c3a 100644 --- a/src/actix_redis/session.rs.html +++ b/src/actix_redis/session.rs.html @@ -1,4 +1,6 @@ -session.rs.html -- source☰All crates? +session.rs.html -- source + +☰All crates? 1 2 3 @@ -702,7 +704,7 @@ /// Create new redis session backend /// /// * `addr` - address of the redis server - pub fn new<S: Into<String>>(addr: S, key: &[u8]) -> RedisSession { + pub fn new<S: Into<String>>(addr: S, key: &[u8]) -> RedisSession { RedisSession(Rc::new(Inner { key: Key::derive_from(key), cache_keygen: Box::new(|key: &str| format!("session:{}", &key)), @@ -719,25 +721,25 @@ } /// Set time to live in seconds for session value - pub fn ttl(mut self, ttl: u32) -> Self { + pub fn ttl(mut self, ttl: u32) -> Self { Rc::get_mut(&mut self.0).unwrap().ttl = format!("{}", ttl); self } /// Set custom cookie name for session id - pub fn cookie_name(mut self, name: &str) -> Self { + pub fn cookie_name(mut self, name: &str) -> Self { Rc::get_mut(&mut self.0).unwrap().name = name.to_owned(); self } /// Set custom cookie path - pub fn cookie_path(mut self, path: &str) -> Self { + pub fn cookie_path(mut self, path: &str) -> Self { Rc::get_mut(&mut self.0).unwrap().path = path.to_owned(); self } /// Set custom cookie domain - pub fn cookie_domain(mut self, domain: &str) -> Self { + pub fn cookie_domain(mut self, domain: &str) -> Self { Rc::get_mut(&mut self.0).unwrap().domain = Some(domain.to_owned()); self } @@ -745,31 +747,31 @@ /// Set custom cookie secure /// If the `secure` field is set, a cookie will only be transmitted when the /// connection is secure - i.e. `https` - pub fn cookie_secure(mut self, secure: bool) -> Self { + pub fn cookie_secure(mut self, secure: bool) -> Self { Rc::get_mut(&mut self.0).unwrap().secure = secure; self } /// Set custom cookie max-age - pub fn cookie_max_age(mut self, max_age: Duration) -> Self { + pub fn cookie_max_age(mut self, max_age: Duration) -> Self { Rc::get_mut(&mut self.0).unwrap().max_age = Some(max_age); self } /// Set custom cookie SameSite - pub fn cookie_same_site(mut self, same_site: SameSite) -> Self { + pub fn cookie_same_site(mut self, same_site: SameSite) -> Self { Rc::get_mut(&mut self.0).unwrap().same_site = Some(same_site); self } /// Set custom cookie HttpOnly policy - pub fn cookie_http_only(mut self, http_only: bool) -> Self { + pub fn cookie_http_only(mut self, http_only: bool) -> Self { Rc::get_mut(&mut self.0).unwrap().http_only = Some(http_only); self } /// Set a custom cache key generation strategy, expecting session key as input - pub fn cache_keygen(mut self, keygen: Box<dyn Fn(&str) -> String>) -> Self { + pub fn cache_keygen(mut self, keygen: Box<dyn Fn(&str) -> String>) -> Self { Rc::get_mut(&mut self.0).unwrap().cache_keygen = keygen; self } @@ -787,9 +789,9 @@ type Error = S::Error; type InitError = (); type Transform = RedisSessionMiddleware<S>; - type Future = Ready<Result<Self::Transform, Self::InitError>>; + type Future = Ready<Result<Self::Transform, Self::InitError>>; - fn new_transform(&self, service: S) -> Self::Future { + fn new_transform(&self, service: S) -> Self::Future { ok(RedisSessionMiddleware { service: Rc::new(RefCell::new(service)), inner: self.0.clone(), @@ -799,7 +801,7 @@ /// Cookie session middleware pub struct RedisSessionMiddleware<S: 'static> { - service: Rc<RefCell<S>>, + service: Rc<RefCell<S>>, inner: Rc<Inner>, } @@ -814,18 +816,18 @@ type Response = ServiceResponse<B>; type Error = Error; #[allow(clippy::type_complexity)] - type Future = Pin<Box<dyn Future<Output = Result<Self::Response, Self::Error>>>>; + type Future = Pin<Box<dyn Future<Output = Result<Self::Response, Self::Error>>>>; - fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> { + fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> { self.service.borrow_mut().poll_ready(cx) } - fn call(&mut self, mut req: ServiceRequest) -> Self::Future { + fn call(&mut self, mut req: ServiceRequest) -> Self::Future { let mut srv = self.service.clone(); let inner = self.inner.clone(); - Box::pin(async move { - let state = inner.load(&req).await?; + Box::pin(async move { + let state = inner.load(&req).await?; let value = if let Some((state, value)) = state { Session::set_session(state, &mut req); Some(value) @@ -833,41 +835,41 @@ None }; - let mut res = srv.call(req).await?; + let mut res = srv.call(req).await?; match Session::get_changes(&mut res) { - (SessionStatus::Unchanged, None) => Ok(res), - (SessionStatus::Unchanged, Some(state)) => { + (SessionStatus::Unchanged, None) => Ok(res), + (SessionStatus::Unchanged, Some(state)) => { if value.is_none() { // implies the session is new - inner.update(res, state, value).await + inner.update(res, state, value).await } else { Ok(res) } } - (SessionStatus::Changed, Some(state)) => { - inner.update(res, state, value).await + (SessionStatus::Changed, Some(state)) => { + inner.update(res, state, value).await } - (SessionStatus::Purged, Some(_)) => { + (SessionStatus::Purged, Some(_)) => { if let Some(val) = value { - inner.clear_cache(val).await?; + inner.clear_cache(val).await?; match inner.remove_cookie(&mut res) { - Ok(_) => Ok(res), - Err(_err) => Err(error::ErrorInternalServerError(_err)), + Ok(_) => Ok(res), + Err(_err) => Err(error::ErrorInternalServerError(_err)), } } else { Err(error::ErrorInternalServerError("unexpected")) } } - (SessionStatus::Renewed, Some(state)) => { + (SessionStatus::Renewed, Some(state)) => { if let Some(val) = value { - inner.clear_cache(val).await?; - inner.update(res, state, None).await + inner.clear_cache(val).await?; + inner.update(res, state, None).await } else { - inner.update(res, state, None).await + inner.update(res, state, None).await } } - (_, None) => unreachable!(), + (_, None) => unreachable!(), } }) } @@ -875,7 +877,7 @@ struct Inner { key: Key, - cache_keygen: Box<dyn Fn(&str) -> String>, + cache_keygen: Box<dyn Fn(&str) -> String>, ttl: String, addr: Addr<RedisActor>, name: String, @@ -888,13 +890,13 @@ } impl Inner { - async fn load( + async fn load( &self, req: &ServiceRequest, - ) -> Result<Option<(HashMap<String, String>, String)>, Error> { + ) -> Result<Option<(HashMap<String, String>, String)>, Error> { if let Ok(cookies) = req.cookies() { for cookie in cookies.iter() { - if cookie.name() == self.name { + if cookie.name() == self.name { let mut jar = CookieJar::new(); jar.add_original(cookie.clone()); if let Some(cookie) = jar.signed(&self.key).get(&self.name) { @@ -903,32 +905,32 @@ return match self .addr .send(Command(resp_array!["GET", cachekey])) - .await + .await { - Err(e) => Err(Error::from(e)), - Ok(res) => match res { - Ok(val) => { + Err(e) => Err(Error::from(e)), + Ok(res) => match res { + Ok(val) => { match val { - RespValue::Error(err) => { + RespValue::Error(err) => { return Err( error::ErrorInternalServerError(err), ); } - RespValue::SimpleString(s) => { + RespValue::SimpleString(s) => { if let Ok(val) = serde_json::from_str(&s) { return Ok(Some((val, value))); } } - RespValue::BulkString(s) => { + RespValue::BulkString(s) => { if let Ok(val) = serde_json::from_slice(&s) { return Ok(Some((val, value))); } } - _ => (), + _ => (), } Ok(None) } - Err(err) => Err(error::ErrorInternalServerError(err)), + Err(err) => Err(error::ErrorInternalServerError(err)), }, }; } else { @@ -940,12 +942,12 @@ Ok(None) } - async fn update<B>( + async fn update<B>( &self, mut res: ServiceResponse<B>, state: impl Iterator<Item = (String, String)>, value: Option<String>, - ) -> Result<ServiceResponse<B>, Error> { + ) -> Result<ServiceResponse<B>, Error> { let (value, jar) = if let Some(value) = value { (value, None) } else { @@ -983,16 +985,16 @@ let state: HashMap<_, _> = state.collect(); match serde_json::to_string(&state) { - Err(e) => Err(e.into()), - Ok(body) => { + Err(e) => Err(e.into()), + Ok(body) => { match self .addr .send(Command(resp_array!["SET", cachekey, body, "EX", &self.ttl])) - .await + .await { - Err(e) => Err(Error::from(e)), - Ok(redis_result) => match redis_result { - Ok(_) => { + Err(e) => Err(Error::from(e)), + Ok(redis_result) => match redis_result { + Ok(_) => { if let Some(jar) = jar { for cookie in jar.delta() { let val = @@ -1002,7 +1004,7 @@ } Ok(res) } - Err(err) => Err(error::ErrorInternalServerError(err)), + Err(err) => Err(error::ErrorInternalServerError(err)), }, } } @@ -1010,16 +1012,16 @@ } /// removes cache entry - async fn clear_cache(&self, key: String) -> Result<(), Error> { + async fn clear_cache(&self, key: String) -> Result<(), Error> { let cachekey = (self.cache_keygen)(&key); - match self.addr.send(Command(resp_array!["DEL", cachekey])).await { - Err(e) => Err(Error::from(e)), - Ok(res) => { + match self.addr.send(Command(resp_array!["DEL", cachekey])).await { + Err(e) => Err(Error::from(e)), + Ok(res) => { match res { // redis responds with number of deleted records - Ok(RespValue::Integer(x)) if x > 0 => Ok(()), - _ => Err(error::ErrorInternalServerError( + Ok(RespValue::Integer(x)) if x > 0 => Ok(()), + _ => Err(error::ErrorInternalServerError( "failed to remove session from cache", )), } @@ -1028,7 +1030,7 @@ } /// invalidates session cookie - fn remove_cookie<B>(&self, res: &mut ServiceResponse<B>) -> Result<(), Error> { + fn remove_cookie<B>(&self, res: &mut ServiceResponse<B>) -> Result<(), Error> { let mut cookie = Cookie::named(self.name.clone()); cookie.set_value(""); cookie.set_max_age(Duration::zero()); @@ -1060,7 +1062,7 @@ counter: i32, } - async fn index(session: Session) -> Result<HttpResponse> { + async fn index(session: Session) -> Result<HttpResponse> { let user_id: Option<String> = session.get::<String>("user_id").unwrap(); let counter: i32 = session .get::<i32>("counter") @@ -1070,7 +1072,7 @@ Ok(HttpResponse::Ok().json(IndexResponse { user_id, counter })) } - async fn do_something(session: Session) -> Result<HttpResponse> { + async fn do_something(session: Session) -> Result<HttpResponse> { let user_id: Option<String> = session.get::<String>("user_id").unwrap(); let counter: i32 = session .get::<i32>("counter") @@ -1086,10 +1088,10 @@ user_id: String, } - async fn login( + async fn login( user_id: web::Json<Identity>, session: Session, - ) -> Result<HttpResponse> { + ) -> Result<HttpResponse> { let id = user_id.into_inner().user_id; session.set("user_id", &id)?; session.renew(); @@ -1105,7 +1107,7 @@ })) } - async fn logout(session: Session) -> Result<HttpResponse> { + async fn logout(session: Session) -> Result<HttpResponse> { let id: Option<String> = session.get("user_id")?; if let Some(x) = id { session.purge(); @@ -1116,7 +1118,7 @@ } #[actix_rt::test] - async fn test_workflow() { + async fn test_workflow() { // Step 1: GET index // - set-cookie actix-session will be in response (session cookie #1) // - response should be: {"counter": 0, "user_id": None} @@ -1147,7 +1149,7 @@ // - set-cookie actix-session will be in response (session cookie #3) // - response should be: {"counter": 0, "user_id": None} - let srv = test::start(|| { + let srv = test::start(|| { App::new() .wrap( RedisSession::new("127.0.0.1:6379", &[0; 32]) @@ -1164,15 +1166,15 @@ // - set-cookie actix-session will be in response (session cookie #1) // - response should be: {"counter": 0, "user_id": None} let req_1a = srv.get("/").send(); - let mut resp_1 = req_1a.await.unwrap(); + let mut resp_1 = req_1a.await.unwrap(); let cookie_1 = resp_1 .cookies() .unwrap() .clone() .into_iter() - .find(|c| c.name() == "test-session") + .find(|c| c.name() == "test-session") .unwrap(); - let result_1 = resp_1.json::<IndexResponse>().await.unwrap(); + let result_1 = resp_1.json::<IndexResponse>().await.unwrap(); assert_eq!( result_1, IndexResponse { @@ -1185,21 +1187,21 @@ // - set-cookie will *not* be in response // - response should be: {"counter": 0, "user_id": None} let req_2 = srv.get("/").cookie(cookie_1.clone()).send(); - let resp_2 = req_2.await.unwrap(); + let resp_2 = req_2.await.unwrap(); let cookie_2 = resp_2 .cookies() .unwrap() .clone() .into_iter() - .find(|c| c.name() == "test-session"); + .find(|c| c.name() == "test-session"); assert_eq!(cookie_2, None); // Step 3: POST to do_something, including session cookie #1 in request // - adds new session state in redis: {"counter": 1} // - response should be: {"counter": 1, "user_id": None} let req_3 = srv.post("/do_something").cookie(cookie_1.clone()).send(); - let mut resp_3 = req_3.await.unwrap(); - let result_3 = resp_3.json::<IndexResponse>().await.unwrap(); + let mut resp_3 = req_3.await.unwrap(); + let result_3 = resp_3.json::<IndexResponse>().await.unwrap(); assert_eq!( result_3, IndexResponse { @@ -1212,8 +1214,8 @@ // - updates session state in redis: {"counter": 2} // - response should be: {"counter": 2, "user_id": None} let req_4 = srv.post("/do_something").cookie(cookie_1.clone()).send(); - let mut resp_4 = req_4.await.unwrap(); - let result_4 = resp_4.json::<IndexResponse>().await.unwrap(); + let mut resp_4 = req_4.await.unwrap(); + let result_4 = resp_4.json::<IndexResponse>().await.unwrap(); assert_eq!( result_4, IndexResponse { @@ -1229,17 +1231,17 @@ .post("/login") .cookie(cookie_1.clone()) .send_json(&json!({"user_id": "ferris"})); - let mut resp_5 = req_5.await.unwrap(); + let mut resp_5 = req_5.await.unwrap(); let cookie_2 = resp_5 .cookies() .unwrap() .clone() .into_iter() - .find(|c| c.name() == "test-session") + .find(|c| c.name() == "test-session") .unwrap(); assert_ne!(cookie_1.value(), cookie_2.value()); - let result_5 = resp_5.json::<IndexResponse>().await.unwrap(); + let result_5 = resp_5.json::<IndexResponse>().await.unwrap(); assert_eq!( result_5, IndexResponse { @@ -1251,8 +1253,8 @@ // Step 6: GET index, including session cookie #2 in request // - response should be: {"counter": 2, "user_id": "ferris"} let req_6 = srv.get("/").cookie(cookie_2.clone()).send(); - let mut resp_6 = req_6.await.unwrap(); - let result_6 = resp_6.json::<IndexResponse>().await.unwrap(); + let mut resp_6 = req_6.await.unwrap(); + let result_6 = resp_6.json::<IndexResponse>().await.unwrap(); assert_eq!( result_6, IndexResponse { @@ -1265,8 +1267,8 @@ // - updates session state in redis: {"counter": 3, "user_id": "ferris"} // - response should be: {"counter": 2, "user_id": None} let req_7 = srv.post("/do_something").cookie(cookie_2.clone()).send(); - let mut resp_7 = req_7.await.unwrap(); - let result_7 = resp_7.json::<IndexResponse>().await.unwrap(); + let mut resp_7 = req_7.await.unwrap(); + let result_7 = resp_7.json::<IndexResponse>().await.unwrap(); assert_eq!( result_7, IndexResponse { @@ -1279,15 +1281,15 @@ // - set-cookie actix-session will be in response (session cookie #3) // - response should be: {"counter": 0, "user_id": None} let req_8 = srv.get("/").cookie(cookie_1.clone()).send(); - let mut resp_8 = req_8.await.unwrap(); + let mut resp_8 = req_8.await.unwrap(); let cookie_3 = resp_8 .cookies() .unwrap() .clone() .into_iter() - .find(|c| c.name() == "test-session") + .find(|c| c.name() == "test-session") .unwrap(); - let result_8 = resp_8.json::<IndexResponse>().await.unwrap(); + let result_8 = resp_8.json::<IndexResponse>().await.unwrap(); assert_eq!( result_8, IndexResponse { @@ -1301,13 +1303,13 @@ // - set-cookie actix-session will be in response with session cookie #2 // invalidation logic let req_9 = srv.post("/logout").cookie(cookie_2.clone()).send(); - let resp_9 = req_9.await.unwrap(); + let resp_9 = req_9.await.unwrap(); let cookie_4 = resp_9 .cookies() .unwrap() .clone() .into_iter() - .find(|c| c.name() == "test-session") + .find(|c| c.name() == "test-session") .unwrap(); assert_ne!( OffsetDateTime::now_utc().year(), @@ -1318,8 +1320,8 @@ // - set-cookie actix-session will be in response (session cookie #3) // - response should be: {"counter": 0, "user_id": None} let req_10 = srv.get("/").cookie(cookie_2.clone()).send(); - let mut resp_10 = req_10.await.unwrap(); - let result_10 = resp_10.json::<IndexResponse>().await.unwrap(); + let mut resp_10 = req_10.await.unwrap(); + let result_10 = resp_10.json::<IndexResponse>().await.unwrap(); assert_eq!( result_10, IndexResponse { @@ -1333,7 +1335,7 @@ .unwrap() .clone() .into_iter() - .find(|c| c.name() == "test-session") + .find(|c| c.name() == "test-session") .unwrap(); assert_ne!(cookie_5.value(), cookie_2.value()); }
1 2 3 @@ -178,13 +180,13 @@ pub struct RedisActor { addr: String, backoff: ExponentialBackoff, - cell: Option<actix::io::FramedWrite<RespValue, WriteHalf<TcpStream>, RespCodec>>, - queue: VecDeque<oneshot::Sender<Result<RespValue, Error>>>, + cell: Option<actix::io::FramedWrite<RespValue, WriteHalf<TcpStream>, RespCodec>>, + queue: VecDeque<oneshot::Sender<Result<RespValue, Error>>>, } impl RedisActor { /// Start new `Supervisor` with `RedisActor`. - pub fn start<S: Into<String>>(addr: S) -> Addr<RedisActor> { + pub fn start<S: Into<String>>(addr: S) -> Addr<RedisActor> { let addr = addr.into(); let mut backoff = ExponentialBackoff::default(); @@ -207,8 +209,8 @@ .send(Connect::host(self.addr.as_str())) .into_actor(self) .map(|res, act, ctx| match res { - Ok(res) => match res { - Ok(stream) => { + Ok(res) => match res { + Ok(stream) => { info!("Connected to redis server: {}", act.addr); let (r, w) = split(stream); @@ -222,7 +224,7 @@ act.backoff.reset(); } - Err(err) => { + Err(err) => { error!("Can not connect to redis server: {}", err); // re-connect with backoff time. // we stop current context, supervisor will restart it. @@ -231,7 +233,7 @@ } } }, - Err(err) => { + Err(err) => { error!("Can not connect to redis server: {}", err); // re-connect with backoff time. // we stop current context, supervisor will restart it. @@ -254,22 +256,22 @@ } impl actix::io::WriteHandler<io::Error> for RedisActor { - fn error(&mut self, err: io::Error, _: &mut Self::Context) -> Running { + fn error(&mut self, err: io::Error, _: &mut Self::Context) -> Running { warn!("Redis connection dropped: {} error: {}", self.addr, err); Running::Stop } } -impl StreamHandler<Result<RespValue, RespError>> for RedisActor { +impl StreamHandler<Result<RespValue, RespError>> for RedisActor { fn handle(&mut self, msg: Result<RespValue, RespError>, ctx: &mut Self::Context) { match msg { - Err(e) => { + Err(e) => { if let Some(tx) = self.queue.pop_front() { let _ = tx.send(Err(e.into())); } ctx.stop(); } - Ok(val) => { + Ok(val) => { if let Some(tx) = self.queue.pop_front() { let _ = tx.send(Ok(val)); } @@ -279,9 +281,9 @@ } impl Handler<Command> for RedisActor { - type Result = ResponseFuture<Result<RespValue, Error>>; + type Result = ResponseFuture<Result<RespValue, Error>>; - fn handle(&mut self, msg: Command, _: &mut Self::Context) -> Self::Result { + fn handle(&mut self, msg: Command, _: &mut Self::Context) -> Self::Result { let (tx, rx) = oneshot::channel(); if let Some(ref mut cell) = self.cell { self.queue.push_back(tx); @@ -291,8 +293,8 @@ } Box::pin(rx.map(|res| match res { - Ok(res) => res, - Err(_) => Err(Error::Disconnected), + Ok(res) => res, + Err(_) => Err(Error::Disconnected), })) } } diff --git a/src/actix_redis/session.rs.html b/src/actix_redis/session.rs.html index dcdf3e3d6..029303c3a 100644 --- a/src/actix_redis/session.rs.html +++ b/src/actix_redis/session.rs.html @@ -1,4 +1,6 @@ -session.rs.html -- source☰All crates? +session.rs.html -- source + +☰All crates? 1 2 3 @@ -702,7 +704,7 @@ /// Create new redis session backend /// /// * `addr` - address of the redis server - pub fn new<S: Into<String>>(addr: S, key: &[u8]) -> RedisSession { + pub fn new<S: Into<String>>(addr: S, key: &[u8]) -> RedisSession { RedisSession(Rc::new(Inner { key: Key::derive_from(key), cache_keygen: Box::new(|key: &str| format!("session:{}", &key)), @@ -719,25 +721,25 @@ } /// Set time to live in seconds for session value - pub fn ttl(mut self, ttl: u32) -> Self { + pub fn ttl(mut self, ttl: u32) -> Self { Rc::get_mut(&mut self.0).unwrap().ttl = format!("{}", ttl); self } /// Set custom cookie name for session id - pub fn cookie_name(mut self, name: &str) -> Self { + pub fn cookie_name(mut self, name: &str) -> Self { Rc::get_mut(&mut self.0).unwrap().name = name.to_owned(); self } /// Set custom cookie path - pub fn cookie_path(mut self, path: &str) -> Self { + pub fn cookie_path(mut self, path: &str) -> Self { Rc::get_mut(&mut self.0).unwrap().path = path.to_owned(); self } /// Set custom cookie domain - pub fn cookie_domain(mut self, domain: &str) -> Self { + pub fn cookie_domain(mut self, domain: &str) -> Self { Rc::get_mut(&mut self.0).unwrap().domain = Some(domain.to_owned()); self } @@ -745,31 +747,31 @@ /// Set custom cookie secure /// If the `secure` field is set, a cookie will only be transmitted when the /// connection is secure - i.e. `https` - pub fn cookie_secure(mut self, secure: bool) -> Self { + pub fn cookie_secure(mut self, secure: bool) -> Self { Rc::get_mut(&mut self.0).unwrap().secure = secure; self } /// Set custom cookie max-age - pub fn cookie_max_age(mut self, max_age: Duration) -> Self { + pub fn cookie_max_age(mut self, max_age: Duration) -> Self { Rc::get_mut(&mut self.0).unwrap().max_age = Some(max_age); self } /// Set custom cookie SameSite - pub fn cookie_same_site(mut self, same_site: SameSite) -> Self { + pub fn cookie_same_site(mut self, same_site: SameSite) -> Self { Rc::get_mut(&mut self.0).unwrap().same_site = Some(same_site); self } /// Set custom cookie HttpOnly policy - pub fn cookie_http_only(mut self, http_only: bool) -> Self { + pub fn cookie_http_only(mut self, http_only: bool) -> Self { Rc::get_mut(&mut self.0).unwrap().http_only = Some(http_only); self } /// Set a custom cache key generation strategy, expecting session key as input - pub fn cache_keygen(mut self, keygen: Box<dyn Fn(&str) -> String>) -> Self { + pub fn cache_keygen(mut self, keygen: Box<dyn Fn(&str) -> String>) -> Self { Rc::get_mut(&mut self.0).unwrap().cache_keygen = keygen; self } @@ -787,9 +789,9 @@ type Error = S::Error; type InitError = (); type Transform = RedisSessionMiddleware<S>; - type Future = Ready<Result<Self::Transform, Self::InitError>>; + type Future = Ready<Result<Self::Transform, Self::InitError>>; - fn new_transform(&self, service: S) -> Self::Future { + fn new_transform(&self, service: S) -> Self::Future { ok(RedisSessionMiddleware { service: Rc::new(RefCell::new(service)), inner: self.0.clone(), @@ -799,7 +801,7 @@ /// Cookie session middleware pub struct RedisSessionMiddleware<S: 'static> { - service: Rc<RefCell<S>>, + service: Rc<RefCell<S>>, inner: Rc<Inner>, } @@ -814,18 +816,18 @@ type Response = ServiceResponse<B>; type Error = Error; #[allow(clippy::type_complexity)] - type Future = Pin<Box<dyn Future<Output = Result<Self::Response, Self::Error>>>>; + type Future = Pin<Box<dyn Future<Output = Result<Self::Response, Self::Error>>>>; - fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> { + fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> { self.service.borrow_mut().poll_ready(cx) } - fn call(&mut self, mut req: ServiceRequest) -> Self::Future { + fn call(&mut self, mut req: ServiceRequest) -> Self::Future { let mut srv = self.service.clone(); let inner = self.inner.clone(); - Box::pin(async move { - let state = inner.load(&req).await?; + Box::pin(async move { + let state = inner.load(&req).await?; let value = if let Some((state, value)) = state { Session::set_session(state, &mut req); Some(value) @@ -833,41 +835,41 @@ None }; - let mut res = srv.call(req).await?; + let mut res = srv.call(req).await?; match Session::get_changes(&mut res) { - (SessionStatus::Unchanged, None) => Ok(res), - (SessionStatus::Unchanged, Some(state)) => { + (SessionStatus::Unchanged, None) => Ok(res), + (SessionStatus::Unchanged, Some(state)) => { if value.is_none() { // implies the session is new - inner.update(res, state, value).await + inner.update(res, state, value).await } else { Ok(res) } } - (SessionStatus::Changed, Some(state)) => { - inner.update(res, state, value).await + (SessionStatus::Changed, Some(state)) => { + inner.update(res, state, value).await } - (SessionStatus::Purged, Some(_)) => { + (SessionStatus::Purged, Some(_)) => { if let Some(val) = value { - inner.clear_cache(val).await?; + inner.clear_cache(val).await?; match inner.remove_cookie(&mut res) { - Ok(_) => Ok(res), - Err(_err) => Err(error::ErrorInternalServerError(_err)), + Ok(_) => Ok(res), + Err(_err) => Err(error::ErrorInternalServerError(_err)), } } else { Err(error::ErrorInternalServerError("unexpected")) } } - (SessionStatus::Renewed, Some(state)) => { + (SessionStatus::Renewed, Some(state)) => { if let Some(val) = value { - inner.clear_cache(val).await?; - inner.update(res, state, None).await + inner.clear_cache(val).await?; + inner.update(res, state, None).await } else { - inner.update(res, state, None).await + inner.update(res, state, None).await } } - (_, None) => unreachable!(), + (_, None) => unreachable!(), } }) } @@ -875,7 +877,7 @@ struct Inner { key: Key, - cache_keygen: Box<dyn Fn(&str) -> String>, + cache_keygen: Box<dyn Fn(&str) -> String>, ttl: String, addr: Addr<RedisActor>, name: String, @@ -888,13 +890,13 @@ } impl Inner { - async fn load( + async fn load( &self, req: &ServiceRequest, - ) -> Result<Option<(HashMap<String, String>, String)>, Error> { + ) -> Result<Option<(HashMap<String, String>, String)>, Error> { if let Ok(cookies) = req.cookies() { for cookie in cookies.iter() { - if cookie.name() == self.name { + if cookie.name() == self.name { let mut jar = CookieJar::new(); jar.add_original(cookie.clone()); if let Some(cookie) = jar.signed(&self.key).get(&self.name) { @@ -903,32 +905,32 @@ return match self .addr .send(Command(resp_array!["GET", cachekey])) - .await + .await { - Err(e) => Err(Error::from(e)), - Ok(res) => match res { - Ok(val) => { + Err(e) => Err(Error::from(e)), + Ok(res) => match res { + Ok(val) => { match val { - RespValue::Error(err) => { + RespValue::Error(err) => { return Err( error::ErrorInternalServerError(err), ); } - RespValue::SimpleString(s) => { + RespValue::SimpleString(s) => { if let Ok(val) = serde_json::from_str(&s) { return Ok(Some((val, value))); } } - RespValue::BulkString(s) => { + RespValue::BulkString(s) => { if let Ok(val) = serde_json::from_slice(&s) { return Ok(Some((val, value))); } } - _ => (), + _ => (), } Ok(None) } - Err(err) => Err(error::ErrorInternalServerError(err)), + Err(err) => Err(error::ErrorInternalServerError(err)), }, }; } else { @@ -940,12 +942,12 @@ Ok(None) } - async fn update<B>( + async fn update<B>( &self, mut res: ServiceResponse<B>, state: impl Iterator<Item = (String, String)>, value: Option<String>, - ) -> Result<ServiceResponse<B>, Error> { + ) -> Result<ServiceResponse<B>, Error> { let (value, jar) = if let Some(value) = value { (value, None) } else { @@ -983,16 +985,16 @@ let state: HashMap<_, _> = state.collect(); match serde_json::to_string(&state) { - Err(e) => Err(e.into()), - Ok(body) => { + Err(e) => Err(e.into()), + Ok(body) => { match self .addr .send(Command(resp_array!["SET", cachekey, body, "EX", &self.ttl])) - .await + .await { - Err(e) => Err(Error::from(e)), - Ok(redis_result) => match redis_result { - Ok(_) => { + Err(e) => Err(Error::from(e)), + Ok(redis_result) => match redis_result { + Ok(_) => { if let Some(jar) = jar { for cookie in jar.delta() { let val = @@ -1002,7 +1004,7 @@ } Ok(res) } - Err(err) => Err(error::ErrorInternalServerError(err)), + Err(err) => Err(error::ErrorInternalServerError(err)), }, } } @@ -1010,16 +1012,16 @@ } /// removes cache entry - async fn clear_cache(&self, key: String) -> Result<(), Error> { + async fn clear_cache(&self, key: String) -> Result<(), Error> { let cachekey = (self.cache_keygen)(&key); - match self.addr.send(Command(resp_array!["DEL", cachekey])).await { - Err(e) => Err(Error::from(e)), - Ok(res) => { + match self.addr.send(Command(resp_array!["DEL", cachekey])).await { + Err(e) => Err(Error::from(e)), + Ok(res) => { match res { // redis responds with number of deleted records - Ok(RespValue::Integer(x)) if x > 0 => Ok(()), - _ => Err(error::ErrorInternalServerError( + Ok(RespValue::Integer(x)) if x > 0 => Ok(()), + _ => Err(error::ErrorInternalServerError( "failed to remove session from cache", )), } @@ -1028,7 +1030,7 @@ } /// invalidates session cookie - fn remove_cookie<B>(&self, res: &mut ServiceResponse<B>) -> Result<(), Error> { + fn remove_cookie<B>(&self, res: &mut ServiceResponse<B>) -> Result<(), Error> { let mut cookie = Cookie::named(self.name.clone()); cookie.set_value(""); cookie.set_max_age(Duration::zero()); @@ -1060,7 +1062,7 @@ counter: i32, } - async fn index(session: Session) -> Result<HttpResponse> { + async fn index(session: Session) -> Result<HttpResponse> { let user_id: Option<String> = session.get::<String>("user_id").unwrap(); let counter: i32 = session .get::<i32>("counter") @@ -1070,7 +1072,7 @@ Ok(HttpResponse::Ok().json(IndexResponse { user_id, counter })) } - async fn do_something(session: Session) -> Result<HttpResponse> { + async fn do_something(session: Session) -> Result<HttpResponse> { let user_id: Option<String> = session.get::<String>("user_id").unwrap(); let counter: i32 = session .get::<i32>("counter") @@ -1086,10 +1088,10 @@ user_id: String, } - async fn login( + async fn login( user_id: web::Json<Identity>, session: Session, - ) -> Result<HttpResponse> { + ) -> Result<HttpResponse> { let id = user_id.into_inner().user_id; session.set("user_id", &id)?; session.renew(); @@ -1105,7 +1107,7 @@ })) } - async fn logout(session: Session) -> Result<HttpResponse> { + async fn logout(session: Session) -> Result<HttpResponse> { let id: Option<String> = session.get("user_id")?; if let Some(x) = id { session.purge(); @@ -1116,7 +1118,7 @@ } #[actix_rt::test] - async fn test_workflow() { + async fn test_workflow() { // Step 1: GET index // - set-cookie actix-session will be in response (session cookie #1) // - response should be: {"counter": 0, "user_id": None} @@ -1147,7 +1149,7 @@ // - set-cookie actix-session will be in response (session cookie #3) // - response should be: {"counter": 0, "user_id": None} - let srv = test::start(|| { + let srv = test::start(|| { App::new() .wrap( RedisSession::new("127.0.0.1:6379", &[0; 32]) @@ -1164,15 +1166,15 @@ // - set-cookie actix-session will be in response (session cookie #1) // - response should be: {"counter": 0, "user_id": None} let req_1a = srv.get("/").send(); - let mut resp_1 = req_1a.await.unwrap(); + let mut resp_1 = req_1a.await.unwrap(); let cookie_1 = resp_1 .cookies() .unwrap() .clone() .into_iter() - .find(|c| c.name() == "test-session") + .find(|c| c.name() == "test-session") .unwrap(); - let result_1 = resp_1.json::<IndexResponse>().await.unwrap(); + let result_1 = resp_1.json::<IndexResponse>().await.unwrap(); assert_eq!( result_1, IndexResponse { @@ -1185,21 +1187,21 @@ // - set-cookie will *not* be in response // - response should be: {"counter": 0, "user_id": None} let req_2 = srv.get("/").cookie(cookie_1.clone()).send(); - let resp_2 = req_2.await.unwrap(); + let resp_2 = req_2.await.unwrap(); let cookie_2 = resp_2 .cookies() .unwrap() .clone() .into_iter() - .find(|c| c.name() == "test-session"); + .find(|c| c.name() == "test-session"); assert_eq!(cookie_2, None); // Step 3: POST to do_something, including session cookie #1 in request // - adds new session state in redis: {"counter": 1} // - response should be: {"counter": 1, "user_id": None} let req_3 = srv.post("/do_something").cookie(cookie_1.clone()).send(); - let mut resp_3 = req_3.await.unwrap(); - let result_3 = resp_3.json::<IndexResponse>().await.unwrap(); + let mut resp_3 = req_3.await.unwrap(); + let result_3 = resp_3.json::<IndexResponse>().await.unwrap(); assert_eq!( result_3, IndexResponse { @@ -1212,8 +1214,8 @@ // - updates session state in redis: {"counter": 2} // - response should be: {"counter": 2, "user_id": None} let req_4 = srv.post("/do_something").cookie(cookie_1.clone()).send(); - let mut resp_4 = req_4.await.unwrap(); - let result_4 = resp_4.json::<IndexResponse>().await.unwrap(); + let mut resp_4 = req_4.await.unwrap(); + let result_4 = resp_4.json::<IndexResponse>().await.unwrap(); assert_eq!( result_4, IndexResponse { @@ -1229,17 +1231,17 @@ .post("/login") .cookie(cookie_1.clone()) .send_json(&json!({"user_id": "ferris"})); - let mut resp_5 = req_5.await.unwrap(); + let mut resp_5 = req_5.await.unwrap(); let cookie_2 = resp_5 .cookies() .unwrap() .clone() .into_iter() - .find(|c| c.name() == "test-session") + .find(|c| c.name() == "test-session") .unwrap(); assert_ne!(cookie_1.value(), cookie_2.value()); - let result_5 = resp_5.json::<IndexResponse>().await.unwrap(); + let result_5 = resp_5.json::<IndexResponse>().await.unwrap(); assert_eq!( result_5, IndexResponse { @@ -1251,8 +1253,8 @@ // Step 6: GET index, including session cookie #2 in request // - response should be: {"counter": 2, "user_id": "ferris"} let req_6 = srv.get("/").cookie(cookie_2.clone()).send(); - let mut resp_6 = req_6.await.unwrap(); - let result_6 = resp_6.json::<IndexResponse>().await.unwrap(); + let mut resp_6 = req_6.await.unwrap(); + let result_6 = resp_6.json::<IndexResponse>().await.unwrap(); assert_eq!( result_6, IndexResponse { @@ -1265,8 +1267,8 @@ // - updates session state in redis: {"counter": 3, "user_id": "ferris"} // - response should be: {"counter": 2, "user_id": None} let req_7 = srv.post("/do_something").cookie(cookie_2.clone()).send(); - let mut resp_7 = req_7.await.unwrap(); - let result_7 = resp_7.json::<IndexResponse>().await.unwrap(); + let mut resp_7 = req_7.await.unwrap(); + let result_7 = resp_7.json::<IndexResponse>().await.unwrap(); assert_eq!( result_7, IndexResponse { @@ -1279,15 +1281,15 @@ // - set-cookie actix-session will be in response (session cookie #3) // - response should be: {"counter": 0, "user_id": None} let req_8 = srv.get("/").cookie(cookie_1.clone()).send(); - let mut resp_8 = req_8.await.unwrap(); + let mut resp_8 = req_8.await.unwrap(); let cookie_3 = resp_8 .cookies() .unwrap() .clone() .into_iter() - .find(|c| c.name() == "test-session") + .find(|c| c.name() == "test-session") .unwrap(); - let result_8 = resp_8.json::<IndexResponse>().await.unwrap(); + let result_8 = resp_8.json::<IndexResponse>().await.unwrap(); assert_eq!( result_8, IndexResponse { @@ -1301,13 +1303,13 @@ // - set-cookie actix-session will be in response with session cookie #2 // invalidation logic let req_9 = srv.post("/logout").cookie(cookie_2.clone()).send(); - let resp_9 = req_9.await.unwrap(); + let resp_9 = req_9.await.unwrap(); let cookie_4 = resp_9 .cookies() .unwrap() .clone() .into_iter() - .find(|c| c.name() == "test-session") + .find(|c| c.name() == "test-session") .unwrap(); assert_ne!( OffsetDateTime::now_utc().year(), @@ -1318,8 +1320,8 @@ // - set-cookie actix-session will be in response (session cookie #3) // - response should be: {"counter": 0, "user_id": None} let req_10 = srv.get("/").cookie(cookie_2.clone()).send(); - let mut resp_10 = req_10.await.unwrap(); - let result_10 = resp_10.json::<IndexResponse>().await.unwrap(); + let mut resp_10 = req_10.await.unwrap(); + let result_10 = resp_10.json::<IndexResponse>().await.unwrap(); assert_eq!( result_10, IndexResponse { @@ -1333,7 +1335,7 @@ .unwrap() .clone() .into_iter() - .find(|c| c.name() == "test-session") + .find(|c| c.name() == "test-session") .unwrap(); assert_ne!(cookie_5.value(), cookie_2.value()); }
1 2 3 @@ -702,7 +704,7 @@ /// Create new redis session backend /// /// * `addr` - address of the redis server - pub fn new<S: Into<String>>(addr: S, key: &[u8]) -> RedisSession { + pub fn new<S: Into<String>>(addr: S, key: &[u8]) -> RedisSession { RedisSession(Rc::new(Inner { key: Key::derive_from(key), cache_keygen: Box::new(|key: &str| format!("session:{}", &key)), @@ -719,25 +721,25 @@ } /// Set time to live in seconds for session value - pub fn ttl(mut self, ttl: u32) -> Self { + pub fn ttl(mut self, ttl: u32) -> Self { Rc::get_mut(&mut self.0).unwrap().ttl = format!("{}", ttl); self } /// Set custom cookie name for session id - pub fn cookie_name(mut self, name: &str) -> Self { + pub fn cookie_name(mut self, name: &str) -> Self { Rc::get_mut(&mut self.0).unwrap().name = name.to_owned(); self } /// Set custom cookie path - pub fn cookie_path(mut self, path: &str) -> Self { + pub fn cookie_path(mut self, path: &str) -> Self { Rc::get_mut(&mut self.0).unwrap().path = path.to_owned(); self } /// Set custom cookie domain - pub fn cookie_domain(mut self, domain: &str) -> Self { + pub fn cookie_domain(mut self, domain: &str) -> Self { Rc::get_mut(&mut self.0).unwrap().domain = Some(domain.to_owned()); self } @@ -745,31 +747,31 @@ /// Set custom cookie secure /// If the `secure` field is set, a cookie will only be transmitted when the /// connection is secure - i.e. `https` - pub fn cookie_secure(mut self, secure: bool) -> Self { + pub fn cookie_secure(mut self, secure: bool) -> Self { Rc::get_mut(&mut self.0).unwrap().secure = secure; self } /// Set custom cookie max-age - pub fn cookie_max_age(mut self, max_age: Duration) -> Self { + pub fn cookie_max_age(mut self, max_age: Duration) -> Self { Rc::get_mut(&mut self.0).unwrap().max_age = Some(max_age); self } /// Set custom cookie SameSite - pub fn cookie_same_site(mut self, same_site: SameSite) -> Self { + pub fn cookie_same_site(mut self, same_site: SameSite) -> Self { Rc::get_mut(&mut self.0).unwrap().same_site = Some(same_site); self } /// Set custom cookie HttpOnly policy - pub fn cookie_http_only(mut self, http_only: bool) -> Self { + pub fn cookie_http_only(mut self, http_only: bool) -> Self { Rc::get_mut(&mut self.0).unwrap().http_only = Some(http_only); self } /// Set a custom cache key generation strategy, expecting session key as input - pub fn cache_keygen(mut self, keygen: Box<dyn Fn(&str) -> String>) -> Self { + pub fn cache_keygen(mut self, keygen: Box<dyn Fn(&str) -> String>) -> Self { Rc::get_mut(&mut self.0).unwrap().cache_keygen = keygen; self } @@ -787,9 +789,9 @@ type Error = S::Error; type InitError = (); type Transform = RedisSessionMiddleware<S>; - type Future = Ready<Result<Self::Transform, Self::InitError>>; + type Future = Ready<Result<Self::Transform, Self::InitError>>; - fn new_transform(&self, service: S) -> Self::Future { + fn new_transform(&self, service: S) -> Self::Future { ok(RedisSessionMiddleware { service: Rc::new(RefCell::new(service)), inner: self.0.clone(), @@ -799,7 +801,7 @@ /// Cookie session middleware pub struct RedisSessionMiddleware<S: 'static> { - service: Rc<RefCell<S>>, + service: Rc<RefCell<S>>, inner: Rc<Inner>, } @@ -814,18 +816,18 @@ type Response = ServiceResponse<B>; type Error = Error; #[allow(clippy::type_complexity)] - type Future = Pin<Box<dyn Future<Output = Result<Self::Response, Self::Error>>>>; + type Future = Pin<Box<dyn Future<Output = Result<Self::Response, Self::Error>>>>; - fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> { + fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> { self.service.borrow_mut().poll_ready(cx) } - fn call(&mut self, mut req: ServiceRequest) -> Self::Future { + fn call(&mut self, mut req: ServiceRequest) -> Self::Future { let mut srv = self.service.clone(); let inner = self.inner.clone(); - Box::pin(async move { - let state = inner.load(&req).await?; + Box::pin(async move { + let state = inner.load(&req).await?; let value = if let Some((state, value)) = state { Session::set_session(state, &mut req); Some(value) @@ -833,41 +835,41 @@ None }; - let mut res = srv.call(req).await?; + let mut res = srv.call(req).await?; match Session::get_changes(&mut res) { - (SessionStatus::Unchanged, None) => Ok(res), - (SessionStatus::Unchanged, Some(state)) => { + (SessionStatus::Unchanged, None) => Ok(res), + (SessionStatus::Unchanged, Some(state)) => { if value.is_none() { // implies the session is new - inner.update(res, state, value).await + inner.update(res, state, value).await } else { Ok(res) } } - (SessionStatus::Changed, Some(state)) => { - inner.update(res, state, value).await + (SessionStatus::Changed, Some(state)) => { + inner.update(res, state, value).await } - (SessionStatus::Purged, Some(_)) => { + (SessionStatus::Purged, Some(_)) => { if let Some(val) = value { - inner.clear_cache(val).await?; + inner.clear_cache(val).await?; match inner.remove_cookie(&mut res) { - Ok(_) => Ok(res), - Err(_err) => Err(error::ErrorInternalServerError(_err)), + Ok(_) => Ok(res), + Err(_err) => Err(error::ErrorInternalServerError(_err)), } } else { Err(error::ErrorInternalServerError("unexpected")) } } - (SessionStatus::Renewed, Some(state)) => { + (SessionStatus::Renewed, Some(state)) => { if let Some(val) = value { - inner.clear_cache(val).await?; - inner.update(res, state, None).await + inner.clear_cache(val).await?; + inner.update(res, state, None).await } else { - inner.update(res, state, None).await + inner.update(res, state, None).await } } - (_, None) => unreachable!(), + (_, None) => unreachable!(), } }) } @@ -875,7 +877,7 @@ struct Inner { key: Key, - cache_keygen: Box<dyn Fn(&str) -> String>, + cache_keygen: Box<dyn Fn(&str) -> String>, ttl: String, addr: Addr<RedisActor>, name: String, @@ -888,13 +890,13 @@ } impl Inner { - async fn load( + async fn load( &self, req: &ServiceRequest, - ) -> Result<Option<(HashMap<String, String>, String)>, Error> { + ) -> Result<Option<(HashMap<String, String>, String)>, Error> { if let Ok(cookies) = req.cookies() { for cookie in cookies.iter() { - if cookie.name() == self.name { + if cookie.name() == self.name { let mut jar = CookieJar::new(); jar.add_original(cookie.clone()); if let Some(cookie) = jar.signed(&self.key).get(&self.name) { @@ -903,32 +905,32 @@ return match self .addr .send(Command(resp_array!["GET", cachekey])) - .await + .await { - Err(e) => Err(Error::from(e)), - Ok(res) => match res { - Ok(val) => { + Err(e) => Err(Error::from(e)), + Ok(res) => match res { + Ok(val) => { match val { - RespValue::Error(err) => { + RespValue::Error(err) => { return Err( error::ErrorInternalServerError(err), ); } - RespValue::SimpleString(s) => { + RespValue::SimpleString(s) => { if let Ok(val) = serde_json::from_str(&s) { return Ok(Some((val, value))); } } - RespValue::BulkString(s) => { + RespValue::BulkString(s) => { if let Ok(val) = serde_json::from_slice(&s) { return Ok(Some((val, value))); } } - _ => (), + _ => (), } Ok(None) } - Err(err) => Err(error::ErrorInternalServerError(err)), + Err(err) => Err(error::ErrorInternalServerError(err)), }, }; } else { @@ -940,12 +942,12 @@ Ok(None) } - async fn update<B>( + async fn update<B>( &self, mut res: ServiceResponse<B>, state: impl Iterator<Item = (String, String)>, value: Option<String>, - ) -> Result<ServiceResponse<B>, Error> { + ) -> Result<ServiceResponse<B>, Error> { let (value, jar) = if let Some(value) = value { (value, None) } else { @@ -983,16 +985,16 @@ let state: HashMap<_, _> = state.collect(); match serde_json::to_string(&state) { - Err(e) => Err(e.into()), - Ok(body) => { + Err(e) => Err(e.into()), + Ok(body) => { match self .addr .send(Command(resp_array!["SET", cachekey, body, "EX", &self.ttl])) - .await + .await { - Err(e) => Err(Error::from(e)), - Ok(redis_result) => match redis_result { - Ok(_) => { + Err(e) => Err(Error::from(e)), + Ok(redis_result) => match redis_result { + Ok(_) => { if let Some(jar) = jar { for cookie in jar.delta() { let val = @@ -1002,7 +1004,7 @@ } Ok(res) } - Err(err) => Err(error::ErrorInternalServerError(err)), + Err(err) => Err(error::ErrorInternalServerError(err)), }, } } @@ -1010,16 +1012,16 @@ } /// removes cache entry - async fn clear_cache(&self, key: String) -> Result<(), Error> { + async fn clear_cache(&self, key: String) -> Result<(), Error> { let cachekey = (self.cache_keygen)(&key); - match self.addr.send(Command(resp_array!["DEL", cachekey])).await { - Err(e) => Err(Error::from(e)), - Ok(res) => { + match self.addr.send(Command(resp_array!["DEL", cachekey])).await { + Err(e) => Err(Error::from(e)), + Ok(res) => { match res { // redis responds with number of deleted records - Ok(RespValue::Integer(x)) if x > 0 => Ok(()), - _ => Err(error::ErrorInternalServerError( + Ok(RespValue::Integer(x)) if x > 0 => Ok(()), + _ => Err(error::ErrorInternalServerError( "failed to remove session from cache", )), } @@ -1028,7 +1030,7 @@ } /// invalidates session cookie - fn remove_cookie<B>(&self, res: &mut ServiceResponse<B>) -> Result<(), Error> { + fn remove_cookie<B>(&self, res: &mut ServiceResponse<B>) -> Result<(), Error> { let mut cookie = Cookie::named(self.name.clone()); cookie.set_value(""); cookie.set_max_age(Duration::zero()); @@ -1060,7 +1062,7 @@ counter: i32, } - async fn index(session: Session) -> Result<HttpResponse> { + async fn index(session: Session) -> Result<HttpResponse> { let user_id: Option<String> = session.get::<String>("user_id").unwrap(); let counter: i32 = session .get::<i32>("counter") @@ -1070,7 +1072,7 @@ Ok(HttpResponse::Ok().json(IndexResponse { user_id, counter })) } - async fn do_something(session: Session) -> Result<HttpResponse> { + async fn do_something(session: Session) -> Result<HttpResponse> { let user_id: Option<String> = session.get::<String>("user_id").unwrap(); let counter: i32 = session .get::<i32>("counter") @@ -1086,10 +1088,10 @@ user_id: String, } - async fn login( + async fn login( user_id: web::Json<Identity>, session: Session, - ) -> Result<HttpResponse> { + ) -> Result<HttpResponse> { let id = user_id.into_inner().user_id; session.set("user_id", &id)?; session.renew(); @@ -1105,7 +1107,7 @@ })) } - async fn logout(session: Session) -> Result<HttpResponse> { + async fn logout(session: Session) -> Result<HttpResponse> { let id: Option<String> = session.get("user_id")?; if let Some(x) = id { session.purge(); @@ -1116,7 +1118,7 @@ } #[actix_rt::test] - async fn test_workflow() { + async fn test_workflow() { // Step 1: GET index // - set-cookie actix-session will be in response (session cookie #1) // - response should be: {"counter": 0, "user_id": None} @@ -1147,7 +1149,7 @@ // - set-cookie actix-session will be in response (session cookie #3) // - response should be: {"counter": 0, "user_id": None} - let srv = test::start(|| { + let srv = test::start(|| { App::new() .wrap( RedisSession::new("127.0.0.1:6379", &[0; 32]) @@ -1164,15 +1166,15 @@ // - set-cookie actix-session will be in response (session cookie #1) // - response should be: {"counter": 0, "user_id": None} let req_1a = srv.get("/").send(); - let mut resp_1 = req_1a.await.unwrap(); + let mut resp_1 = req_1a.await.unwrap(); let cookie_1 = resp_1 .cookies() .unwrap() .clone() .into_iter() - .find(|c| c.name() == "test-session") + .find(|c| c.name() == "test-session") .unwrap(); - let result_1 = resp_1.json::<IndexResponse>().await.unwrap(); + let result_1 = resp_1.json::<IndexResponse>().await.unwrap(); assert_eq!( result_1, IndexResponse { @@ -1185,21 +1187,21 @@ // - set-cookie will *not* be in response // - response should be: {"counter": 0, "user_id": None} let req_2 = srv.get("/").cookie(cookie_1.clone()).send(); - let resp_2 = req_2.await.unwrap(); + let resp_2 = req_2.await.unwrap(); let cookie_2 = resp_2 .cookies() .unwrap() .clone() .into_iter() - .find(|c| c.name() == "test-session"); + .find(|c| c.name() == "test-session"); assert_eq!(cookie_2, None); // Step 3: POST to do_something, including session cookie #1 in request // - adds new session state in redis: {"counter": 1} // - response should be: {"counter": 1, "user_id": None} let req_3 = srv.post("/do_something").cookie(cookie_1.clone()).send(); - let mut resp_3 = req_3.await.unwrap(); - let result_3 = resp_3.json::<IndexResponse>().await.unwrap(); + let mut resp_3 = req_3.await.unwrap(); + let result_3 = resp_3.json::<IndexResponse>().await.unwrap(); assert_eq!( result_3, IndexResponse { @@ -1212,8 +1214,8 @@ // - updates session state in redis: {"counter": 2} // - response should be: {"counter": 2, "user_id": None} let req_4 = srv.post("/do_something").cookie(cookie_1.clone()).send(); - let mut resp_4 = req_4.await.unwrap(); - let result_4 = resp_4.json::<IndexResponse>().await.unwrap(); + let mut resp_4 = req_4.await.unwrap(); + let result_4 = resp_4.json::<IndexResponse>().await.unwrap(); assert_eq!( result_4, IndexResponse { @@ -1229,17 +1231,17 @@ .post("/login") .cookie(cookie_1.clone()) .send_json(&json!({"user_id": "ferris"})); - let mut resp_5 = req_5.await.unwrap(); + let mut resp_5 = req_5.await.unwrap(); let cookie_2 = resp_5 .cookies() .unwrap() .clone() .into_iter() - .find(|c| c.name() == "test-session") + .find(|c| c.name() == "test-session") .unwrap(); assert_ne!(cookie_1.value(), cookie_2.value()); - let result_5 = resp_5.json::<IndexResponse>().await.unwrap(); + let result_5 = resp_5.json::<IndexResponse>().await.unwrap(); assert_eq!( result_5, IndexResponse { @@ -1251,8 +1253,8 @@ // Step 6: GET index, including session cookie #2 in request // - response should be: {"counter": 2, "user_id": "ferris"} let req_6 = srv.get("/").cookie(cookie_2.clone()).send(); - let mut resp_6 = req_6.await.unwrap(); - let result_6 = resp_6.json::<IndexResponse>().await.unwrap(); + let mut resp_6 = req_6.await.unwrap(); + let result_6 = resp_6.json::<IndexResponse>().await.unwrap(); assert_eq!( result_6, IndexResponse { @@ -1265,8 +1267,8 @@ // - updates session state in redis: {"counter": 3, "user_id": "ferris"} // - response should be: {"counter": 2, "user_id": None} let req_7 = srv.post("/do_something").cookie(cookie_2.clone()).send(); - let mut resp_7 = req_7.await.unwrap(); - let result_7 = resp_7.json::<IndexResponse>().await.unwrap(); + let mut resp_7 = req_7.await.unwrap(); + let result_7 = resp_7.json::<IndexResponse>().await.unwrap(); assert_eq!( result_7, IndexResponse { @@ -1279,15 +1281,15 @@ // - set-cookie actix-session will be in response (session cookie #3) // - response should be: {"counter": 0, "user_id": None} let req_8 = srv.get("/").cookie(cookie_1.clone()).send(); - let mut resp_8 = req_8.await.unwrap(); + let mut resp_8 = req_8.await.unwrap(); let cookie_3 = resp_8 .cookies() .unwrap() .clone() .into_iter() - .find(|c| c.name() == "test-session") + .find(|c| c.name() == "test-session") .unwrap(); - let result_8 = resp_8.json::<IndexResponse>().await.unwrap(); + let result_8 = resp_8.json::<IndexResponse>().await.unwrap(); assert_eq!( result_8, IndexResponse { @@ -1301,13 +1303,13 @@ // - set-cookie actix-session will be in response with session cookie #2 // invalidation logic let req_9 = srv.post("/logout").cookie(cookie_2.clone()).send(); - let resp_9 = req_9.await.unwrap(); + let resp_9 = req_9.await.unwrap(); let cookie_4 = resp_9 .cookies() .unwrap() .clone() .into_iter() - .find(|c| c.name() == "test-session") + .find(|c| c.name() == "test-session") .unwrap(); assert_ne!( OffsetDateTime::now_utc().year(), @@ -1318,8 +1320,8 @@ // - set-cookie actix-session will be in response (session cookie #3) // - response should be: {"counter": 0, "user_id": None} let req_10 = srv.get("/").cookie(cookie_2.clone()).send(); - let mut resp_10 = req_10.await.unwrap(); - let result_10 = resp_10.json::<IndexResponse>().await.unwrap(); + let mut resp_10 = req_10.await.unwrap(); + let result_10 = resp_10.json::<IndexResponse>().await.unwrap(); assert_eq!( result_10, IndexResponse { @@ -1333,7 +1335,7 @@ .unwrap() .clone() .into_iter() - .find(|c| c.name() == "test-session") + .find(|c| c.name() == "test-session") .unwrap(); assert_ne!(cookie_5.value(), cookie_2.value()); }