mirror of
https://github.com/fafhrd91/actix-web
synced 2025-07-04 18:06:23 +02:00
Compare commits
29 Commits
web-v1.0.3
...
session-v0
Author | SHA1 | Date | |
---|---|---|---|
f410f3330f | |||
e1fcd203f8 | |||
0d8a4304a9 | |||
14cc5a5d6b | |||
287c2b1d18 | |||
7596ab69e0 | |||
1fdd77bffa | |||
2d424957fb | |||
dabc4fe00b | |||
5bf5b0acd2 | |||
099a8ff7d8 | |||
a28b7139e6 | |||
a0a469fe85 | |||
dbab55dd6b | |||
d2eb1edac3 | |||
5901dfee1a | |||
0e05b37082 | |||
37f4ce8604 | |||
12b5174850 | |||
50a9d9e2c5 | |||
93855b889a | |||
fa7e0fe6df | |||
382d4ca216 | |||
32a66a99bf | |||
73ae801a13 | |||
ca4ed0932e | |||
9fc7c8b1af | |||
65732197b8 | |||
959eef05ae |
@ -3,7 +3,7 @@ sudo: required
|
|||||||
dist: trusty
|
dist: trusty
|
||||||
|
|
||||||
cache:
|
cache:
|
||||||
cargo: true
|
# cargo: true
|
||||||
apt: true
|
apt: true
|
||||||
|
|
||||||
matrix:
|
matrix:
|
||||||
|
@ -1,5 +1,11 @@
|
|||||||
# Changes
|
# Changes
|
||||||
|
|
||||||
|
## [1.0.4] - TBD
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
* Upgrade `rand` dependency version to 0.7
|
||||||
|
|
||||||
## [1.0.3] - 2019-06-28
|
## [1.0.3] - 2019-06-28
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
@ -105,7 +105,7 @@ rustls = { version = "0.15", optional = true }
|
|||||||
actix = { version = "0.8.3" }
|
actix = { version = "0.8.3" }
|
||||||
actix-http = { version = "0.2.5", features=["ssl", "brotli", "flate2-zlib"] }
|
actix-http = { version = "0.2.5", features=["ssl", "brotli", "flate2-zlib"] }
|
||||||
actix-http-test = { version = "0.2.2", features=["ssl"] }
|
actix-http-test = { version = "0.2.2", features=["ssl"] }
|
||||||
rand = "0.6"
|
rand = "0.7"
|
||||||
env_logger = "0.6"
|
env_logger = "0.6"
|
||||||
serde_derive = "1.0"
|
serde_derive = "1.0"
|
||||||
tokio-timer = "0.2.8"
|
tokio-timer = "0.2.8"
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
## Documentation & community resources
|
## Documentation & community resources
|
||||||
|
|
||||||
* [User Guide](https://actix.rs/docs/)
|
* [User Guide](https://actix.rs/docs/)
|
||||||
* [API Documentation](https://docs.rs/actix-identity/)
|
* [API Documentation](https://docs.rs/actix-cors/)
|
||||||
* [Chat on gitter](https://gitter.im/actix/actix)
|
* [Chat on gitter](https://gitter.im/actix/actix)
|
||||||
* Cargo package: [actix-session](https://crates.io/crates/actix-identity)
|
* Cargo package: [actix-cors](https://crates.io/crates/actix-cors)
|
||||||
* Minimum supported Rust version: 1.34 or later
|
* Minimum supported Rust version: 1.34 or later
|
||||||
|
@ -1,5 +1,11 @@
|
|||||||
# Changes
|
# Changes
|
||||||
|
|
||||||
|
## [0.2.6] - TBD
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
* Upgrade `rand` dependency version to 0.7
|
||||||
|
|
||||||
## [0.2.5] - 2019-06-28
|
## [0.2.5] - 2019-06-28
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
@ -55,7 +55,7 @@ base64 = "0.10"
|
|||||||
bitflags = "1.0"
|
bitflags = "1.0"
|
||||||
bytes = "0.4"
|
bytes = "0.4"
|
||||||
byteorder = "1.2"
|
byteorder = "1.2"
|
||||||
copyless = "0.1.2"
|
copyless = "0.1.4"
|
||||||
derive_more = "0.15.0"
|
derive_more = "0.15.0"
|
||||||
either = "1.5.2"
|
either = "1.5.2"
|
||||||
encoding_rs = "0.8"
|
encoding_rs = "0.8"
|
||||||
@ -70,7 +70,7 @@ language-tags = "0.2"
|
|||||||
log = "0.4"
|
log = "0.4"
|
||||||
mime = "0.3"
|
mime = "0.3"
|
||||||
percent-encoding = "1.0"
|
percent-encoding = "1.0"
|
||||||
rand = "0.6"
|
rand = "0.7"
|
||||||
regex = "1.0"
|
regex = "1.0"
|
||||||
serde = "1.0"
|
serde = "1.0"
|
||||||
serde_json = "1.0"
|
serde_json = "1.0"
|
||||||
|
@ -1,5 +1,12 @@
|
|||||||
# Changes
|
# Changes
|
||||||
|
|
||||||
|
## [0.2.0] - 2019-07-08
|
||||||
|
|
||||||
|
* Enhanced ``actix-session`` to facilitate state changes. Use ``Session.renew()``
|
||||||
|
at successful login to cycle a session (new key/cookie but keeps state).
|
||||||
|
Use ``Session.purge()`` at logout to invalid a session cookie (and remove
|
||||||
|
from redis cache, if applicable).
|
||||||
|
|
||||||
## [0.1.1] - 2019-06-03
|
## [0.1.1] - 2019-06-03
|
||||||
|
|
||||||
* Fix optional cookie session support
|
* Fix optional cookie session support
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "actix-session"
|
name = "actix-session"
|
||||||
version = "0.1.1"
|
version = "0.2.0"
|
||||||
authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
|
authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
|
||||||
description = "Session for actix web framework."
|
description = "Session for actix web framework."
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
|
@ -6,4 +6,4 @@
|
|||||||
* [API Documentation](https://docs.rs/actix-session/)
|
* [API Documentation](https://docs.rs/actix-session/)
|
||||||
* [Chat on gitter](https://gitter.im/actix/actix)
|
* [Chat on gitter](https://gitter.im/actix/actix)
|
||||||
* Cargo package: [actix-session](https://crates.io/crates/actix-session)
|
* Cargo package: [actix-session](https://crates.io/crates/actix-session)
|
||||||
* Minimum supported Rust version: 1.33 or later
|
* Minimum supported Rust version: 1.34 or later
|
||||||
|
@ -28,7 +28,7 @@ use futures::future::{ok, Future, FutureResult};
|
|||||||
use futures::Poll;
|
use futures::Poll;
|
||||||
use serde_json::error::Error as JsonError;
|
use serde_json::error::Error as JsonError;
|
||||||
|
|
||||||
use crate::Session;
|
use crate::{Session, SessionStatus};
|
||||||
|
|
||||||
/// Errors that can occur during handling cookie session
|
/// Errors that can occur during handling cookie session
|
||||||
#[derive(Debug, From, Display)]
|
#[derive(Debug, From, Display)]
|
||||||
@ -119,7 +119,20 @@ impl CookieSessionInner {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn load(&self, req: &ServiceRequest) -> HashMap<String, String> {
|
/// invalidates session cookie
|
||||||
|
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(time::Duration::seconds(0));
|
||||||
|
cookie.set_expires(time::now() - time::Duration::days(365));
|
||||||
|
|
||||||
|
let val = HeaderValue::from_str(&cookie.to_string())?;
|
||||||
|
res.headers_mut().append(SET_COOKIE, val);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn load(&self, req: &ServiceRequest) -> (bool, HashMap<String, String>) {
|
||||||
if let Ok(cookies) = req.cookies() {
|
if let Ok(cookies) = req.cookies() {
|
||||||
for cookie in cookies.iter() {
|
for cookie in cookies.iter() {
|
||||||
if cookie.name() == self.name {
|
if cookie.name() == self.name {
|
||||||
@ -134,13 +147,13 @@ impl CookieSessionInner {
|
|||||||
};
|
};
|
||||||
if let Some(cookie) = cookie_opt {
|
if let Some(cookie) = cookie_opt {
|
||||||
if let Ok(val) = serde_json::from_str(cookie.value()) {
|
if let Ok(val) = serde_json::from_str(cookie.value()) {
|
||||||
return val;
|
return (false, val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
HashMap::new()
|
(true, HashMap::new())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -302,16 +315,37 @@ where
|
|||||||
self.service.poll_ready()
|
self.service.poll_ready()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// On first request, a new session cookie is returned in response, regardless
|
||||||
|
/// of whether any session state is set. With subsequent requests, if the
|
||||||
|
/// session state changes, then set-cookie is returned in response. As
|
||||||
|
/// a user logs out, call session.purge() to set SessionStatus accordingly
|
||||||
|
/// and this will trigger removal of the session cookie in the response.
|
||||||
fn call(&mut self, mut req: ServiceRequest) -> Self::Future {
|
fn call(&mut self, mut req: ServiceRequest) -> Self::Future {
|
||||||
let inner = self.inner.clone();
|
let inner = self.inner.clone();
|
||||||
let state = self.inner.load(&req);
|
let (is_new, state) = self.inner.load(&req);
|
||||||
Session::set_session(state.into_iter(), &mut req);
|
Session::set_session(state.into_iter(), &mut req);
|
||||||
|
|
||||||
Box::new(self.service.call(req).map(move |mut res| {
|
Box::new(self.service.call(req).map(move |mut res| {
|
||||||
if let Some(state) = Session::get_changes(&mut res) {
|
match Session::get_changes(&mut res) {
|
||||||
res.checked_expr(|res| inner.set_cookie(res, state))
|
(SessionStatus::Changed, Some(state))
|
||||||
} else {
|
| (SessionStatus::Renewed, Some(state)) => {
|
||||||
res
|
res.checked_expr(|res| inner.set_cookie(res, state))
|
||||||
|
}
|
||||||
|
(SessionStatus::Unchanged, _) =>
|
||||||
|
// set a new session cookie upon first request (new client)
|
||||||
|
{
|
||||||
|
if is_new {
|
||||||
|
let state: HashMap<String, String> = HashMap::new();
|
||||||
|
res.checked_expr(|res| inner.set_cookie(res, state.into_iter()))
|
||||||
|
} else {
|
||||||
|
res
|
||||||
|
}
|
||||||
|
}
|
||||||
|
(SessionStatus::Purged, _) => {
|
||||||
|
inner.remove_cookie(&mut res);
|
||||||
|
res
|
||||||
|
}
|
||||||
|
_ => res,
|
||||||
}
|
}
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
@ -98,10 +98,23 @@ impl UserSession for ServiceRequest {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(PartialEq, Clone, Debug)]
|
||||||
|
pub enum SessionStatus {
|
||||||
|
Changed,
|
||||||
|
Purged,
|
||||||
|
Renewed,
|
||||||
|
Unchanged,
|
||||||
|
}
|
||||||
|
impl Default for SessionStatus {
|
||||||
|
fn default() -> SessionStatus {
|
||||||
|
SessionStatus::Unchanged
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
struct SessionInner {
|
struct SessionInner {
|
||||||
state: HashMap<String, String>,
|
state: HashMap<String, String>,
|
||||||
changed: bool,
|
pub status: SessionStatus,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Session {
|
impl Session {
|
||||||
@ -117,25 +130,46 @@ impl Session {
|
|||||||
/// Set a `value` from the session.
|
/// Set a `value` from the session.
|
||||||
pub fn set<T: Serialize>(&self, key: &str, value: T) -> Result<(), Error> {
|
pub fn set<T: Serialize>(&self, key: &str, value: T) -> Result<(), Error> {
|
||||||
let mut inner = self.0.borrow_mut();
|
let mut inner = self.0.borrow_mut();
|
||||||
inner.changed = true;
|
if inner.status != SessionStatus::Purged {
|
||||||
inner
|
inner.status = SessionStatus::Changed;
|
||||||
.state
|
inner
|
||||||
.insert(key.to_owned(), serde_json::to_string(&value)?);
|
.state
|
||||||
|
.insert(key.to_owned(), serde_json::to_string(&value)?);
|
||||||
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Remove value from the session.
|
/// Remove value from the session.
|
||||||
pub fn remove(&self, key: &str) {
|
pub fn remove(&self, key: &str) {
|
||||||
let mut inner = self.0.borrow_mut();
|
let mut inner = self.0.borrow_mut();
|
||||||
inner.changed = true;
|
if inner.status != SessionStatus::Purged {
|
||||||
inner.state.remove(key);
|
inner.status = SessionStatus::Changed;
|
||||||
|
inner.state.remove(key);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Clear the session.
|
/// Clear the session.
|
||||||
pub fn clear(&self) {
|
pub fn clear(&self) {
|
||||||
let mut inner = self.0.borrow_mut();
|
let mut inner = self.0.borrow_mut();
|
||||||
inner.changed = true;
|
if inner.status != SessionStatus::Purged {
|
||||||
inner.state.clear()
|
inner.status = SessionStatus::Changed;
|
||||||
|
inner.state.clear()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Removes session, both client and server side.
|
||||||
|
pub fn purge(&self) {
|
||||||
|
let mut inner = self.0.borrow_mut();
|
||||||
|
inner.status = SessionStatus::Purged;
|
||||||
|
inner.state.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Renews the session key, assigning existing session state to new key.
|
||||||
|
pub fn renew(&self) {
|
||||||
|
let mut inner = self.0.borrow_mut();
|
||||||
|
if inner.status != SessionStatus::Purged {
|
||||||
|
inner.status = SessionStatus::Renewed;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_session(
|
pub fn set_session(
|
||||||
@ -149,7 +183,10 @@ impl Session {
|
|||||||
|
|
||||||
pub fn get_changes<B>(
|
pub fn get_changes<B>(
|
||||||
res: &mut ServiceResponse<B>,
|
res: &mut ServiceResponse<B>,
|
||||||
) -> Option<impl Iterator<Item = (String, String)>> {
|
) -> (
|
||||||
|
SessionStatus,
|
||||||
|
Option<impl Iterator<Item = (String, String)>>,
|
||||||
|
) {
|
||||||
if let Some(s_impl) = res
|
if let Some(s_impl) = res
|
||||||
.request()
|
.request()
|
||||||
.extensions()
|
.extensions()
|
||||||
@ -157,9 +194,9 @@ impl Session {
|
|||||||
{
|
{
|
||||||
let state =
|
let state =
|
||||||
std::mem::replace(&mut s_impl.borrow_mut().state, HashMap::new());
|
std::mem::replace(&mut s_impl.borrow_mut().state, HashMap::new());
|
||||||
Some(state.into_iter())
|
(s_impl.borrow().status.clone(), Some(state.into_iter()))
|
||||||
} else {
|
} else {
|
||||||
None
|
(SessionStatus::Unchanged, None)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -224,7 +261,8 @@ mod tests {
|
|||||||
session.remove("key");
|
session.remove("key");
|
||||||
|
|
||||||
let mut res = req.into_response(HttpResponse::Ok().finish());
|
let mut res = req.into_response(HttpResponse::Ok().finish());
|
||||||
let changes: Vec<_> = Session::get_changes(&mut res).unwrap().collect();
|
let (_status, state) = Session::get_changes(&mut res);
|
||||||
|
let changes: Vec<_> = state.unwrap().collect();
|
||||||
assert_eq!(changes, [("key2".to_string(), "\"value2\"".to_string())]);
|
assert_eq!(changes, [("key2".to_string(), "\"value2\"".to_string())]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -241,4 +279,22 @@ mod tests {
|
|||||||
let res = session.get::<String>("key").unwrap();
|
let res = session.get::<String>("key").unwrap();
|
||||||
assert_eq!(res, Some("value".to_string()));
|
assert_eq!(res, Some("value".to_string()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn purge_session() {
|
||||||
|
let mut req = test::TestRequest::default().to_srv_request();
|
||||||
|
let session = Session::get_session(&mut *req.extensions_mut());
|
||||||
|
assert_eq!(session.0.borrow().status, SessionStatus::Unchanged);
|
||||||
|
session.purge();
|
||||||
|
assert_eq!(session.0.borrow().status, SessionStatus::Purged);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn renew_session() {
|
||||||
|
let mut req = test::TestRequest::default().to_srv_request();
|
||||||
|
let session = Session::get_session(&mut *req.extensions_mut());
|
||||||
|
assert_eq!(session.0.borrow().status, SessionStatus::Unchanged);
|
||||||
|
session.renew();
|
||||||
|
assert_eq!(session.0.borrow().status, SessionStatus::Renewed);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,8 +19,8 @@ path = "src/lib.rs"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
actix = "0.8.3"
|
actix = "0.8.3"
|
||||||
actix-web = "1.0.2"
|
actix-web = "1.0.3"
|
||||||
actix-http = "0.2.4"
|
actix-http = "0.2.5"
|
||||||
actix-codec = "0.1.2"
|
actix-codec = "0.1.2"
|
||||||
bytes = "0.4"
|
bytes = "0.4"
|
||||||
futures = "0.1.25"
|
futures = "0.1.25"
|
||||||
|
@ -1,5 +1,14 @@
|
|||||||
# Changes
|
# Changes
|
||||||
|
|
||||||
|
## [0.2.2] - 2019-07-01
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
* Always append a colon after username in basic auth
|
||||||
|
|
||||||
|
* Upgrade `rand` dependency version to 0.7
|
||||||
|
|
||||||
|
|
||||||
## [0.2.1] - 2019-06-05
|
## [0.2.1] - 2019-06-05
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "awc"
|
name = "awc"
|
||||||
version = "0.2.1"
|
version = "0.2.2"
|
||||||
authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
|
authors = ["Nikolay Kim <fafhrd91@gmail.com>"]
|
||||||
description = "Actix http client."
|
description = "Actix http client."
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
@ -49,7 +49,7 @@ futures = "0.1.25"
|
|||||||
log =" 0.4"
|
log =" 0.4"
|
||||||
mime = "0.3"
|
mime = "0.3"
|
||||||
percent-encoding = "1.0"
|
percent-encoding = "1.0"
|
||||||
rand = "0.6"
|
rand = "0.7"
|
||||||
serde = "1.0"
|
serde = "1.0"
|
||||||
serde_json = "1.0"
|
serde_json = "1.0"
|
||||||
serde_urlencoded = "0.5.3"
|
serde_urlencoded = "0.5.3"
|
||||||
@ -66,5 +66,5 @@ actix-server = { version = "0.5.1", features=["ssl"] }
|
|||||||
brotli2 = { version="0.3.2" }
|
brotli2 = { version="0.3.2" }
|
||||||
flate2 = { version="1.0.2" }
|
flate2 = { version="1.0.2" }
|
||||||
env_logger = "0.6"
|
env_logger = "0.6"
|
||||||
rand = "0.6"
|
rand = "0.7"
|
||||||
tokio-tcp = "0.1"
|
tokio-tcp = "0.1"
|
||||||
|
@ -115,7 +115,7 @@ impl ClientBuilder {
|
|||||||
{
|
{
|
||||||
let auth = match password {
|
let auth = match password {
|
||||||
Some(password) => format!("{}:{}", username, password),
|
Some(password) => format!("{}:{}", username, password),
|
||||||
None => format!("{}", username),
|
None => format!("{}:", username),
|
||||||
};
|
};
|
||||||
self.header(
|
self.header(
|
||||||
header::AUTHORIZATION,
|
header::AUTHORIZATION,
|
||||||
@ -164,7 +164,7 @@ mod tests {
|
|||||||
.unwrap()
|
.unwrap()
|
||||||
.to_str()
|
.to_str()
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
"Basic dXNlcm5hbWU="
|
"Basic dXNlcm5hbWU6"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -280,7 +280,7 @@ impl ClientRequest {
|
|||||||
{
|
{
|
||||||
let auth = match password {
|
let auth = match password {
|
||||||
Some(password) => format!("{}:{}", username, password),
|
Some(password) => format!("{}:{}", username, password),
|
||||||
None => format!("{}", username),
|
None => format!("{}:", username),
|
||||||
};
|
};
|
||||||
self.header(
|
self.header(
|
||||||
header::AUTHORIZATION,
|
header::AUTHORIZATION,
|
||||||
@ -664,7 +664,7 @@ mod tests {
|
|||||||
.unwrap()
|
.unwrap()
|
||||||
.to_str()
|
.to_str()
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
"Basic dXNlcm5hbWU="
|
"Basic dXNlcm5hbWU6"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -195,7 +195,7 @@ impl WebsocketsRequest {
|
|||||||
{
|
{
|
||||||
let auth = match password {
|
let auth = match password {
|
||||||
Some(password) => format!("{}:{}", username, password),
|
Some(password) => format!("{}:{}", username, password),
|
||||||
None => format!("{}", username),
|
None => format!("{}:", username),
|
||||||
};
|
};
|
||||||
self.header(AUTHORIZATION, format!("Basic {}", base64::encode(&auth)))
|
self.header(AUTHORIZATION, format!("Basic {}", base64::encode(&auth)))
|
||||||
}
|
}
|
||||||
@ -443,7 +443,7 @@ mod tests {
|
|||||||
.unwrap()
|
.unwrap()
|
||||||
.to_str()
|
.to_str()
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
"Basic dXNlcm5hbWU="
|
"Basic dXNlcm5hbWU6"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,7 +64,7 @@ where
|
|||||||
RT.with(move |rt| rt.borrow_mut().get_mut().block_on(f.into_future()))
|
RT.with(move |rt| rt.borrow_mut().get_mut().block_on(f.into_future()))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Runs the provided function, blocking the current thread until the resul
|
/// Runs the provided function, blocking the current thread until the result
|
||||||
/// future completes.
|
/// future completes.
|
||||||
///
|
///
|
||||||
/// This function can be used to synchronously block the current thread
|
/// This function can be used to synchronously block the current thread
|
||||||
|
@ -13,7 +13,7 @@ use crate::extract::FromRequest;
|
|||||||
use crate::request::HttpRequest;
|
use crate::request::HttpRequest;
|
||||||
|
|
||||||
#[derive(PartialEq, Eq, PartialOrd, Ord)]
|
#[derive(PartialEq, Eq, PartialOrd, Ord)]
|
||||||
/// Extract typed information from from the request's query.
|
/// Extract typed information from the request's query.
|
||||||
///
|
///
|
||||||
/// ## Example
|
/// ## Example
|
||||||
///
|
///
|
||||||
@ -90,7 +90,7 @@ impl<T: fmt::Display> fmt::Display for Query<T> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Extract typed information from from the request's query.
|
/// Extract typed information from the request's query.
|
||||||
///
|
///
|
||||||
/// ## Example
|
/// ## Example
|
||||||
///
|
///
|
||||||
|
Reference in New Issue
Block a user