mirror of
https://github.com/tokio-rs/axum.git
synced 2025-04-26 13:56:22 +02:00
Add sync constructors to CookieJar
, SignedCookieJar
, and PrivateCookieJar
(#1264)
* Add sync constructors to `CookieJar`, `SignedCookieJar`, and `PrivateCookieJar` * Move to constructor * use `RequestParts::extract`
This commit is contained in:
parent
fb32fcc07c
commit
01630cfef6
4 changed files with 105 additions and 18 deletions
axum-extra
|
@ -18,6 +18,8 @@ and this project adheres to [Semantic Versioning].
|
|||
- **added:** Support chaining handlers with `HandlerCallWithExtractors::or` ([#1170])
|
||||
- **change:** axum-extra's MSRV is now 1.60 ([#1239])
|
||||
- **added:** Add Protocol Buffer extractor and response ([#1239])
|
||||
- **added:** Add sync constructors to `CookieJar`, `PrivateCookieJar`, and
|
||||
`SignedCookieJar` so they're easier to use in custom middleware
|
||||
|
||||
[#1086]: https://github.com/tokio-rs/axum/pull/1086
|
||||
[#1119]: https://github.com/tokio-rs/axum/pull/1119
|
||||
|
|
|
@ -82,7 +82,7 @@ pub use cookie::Key;
|
|||
/// .route("/me", get(me));
|
||||
/// # let app: Router<axum::body::Body> = app;
|
||||
/// ```
|
||||
#[derive(Debug)]
|
||||
#[derive(Debug, Default)]
|
||||
pub struct CookieJar {
|
||||
jar: cookie::CookieJar,
|
||||
}
|
||||
|
@ -95,18 +95,12 @@ where
|
|||
type Rejection = Infallible;
|
||||
|
||||
async fn from_request(req: &mut RequestParts<B>) -> Result<Self, Self::Rejection> {
|
||||
let mut jar = cookie::CookieJar::new();
|
||||
for cookie in cookies_from_request(req) {
|
||||
jar.add_original(cookie);
|
||||
}
|
||||
Ok(Self { jar })
|
||||
Ok(Self::from_headers(req.headers()))
|
||||
}
|
||||
}
|
||||
|
||||
fn cookies_from_request<B>(
|
||||
req: &mut RequestParts<B>,
|
||||
) -> impl Iterator<Item = Cookie<'static>> + '_ {
|
||||
req.headers()
|
||||
fn cookies_from_request(headers: &HeaderMap) -> impl Iterator<Item = Cookie<'static>> + '_ {
|
||||
headers
|
||||
.get_all(COOKIE)
|
||||
.into_iter()
|
||||
.filter_map(|value| value.to_str().ok())
|
||||
|
@ -115,6 +109,31 @@ fn cookies_from_request<B>(
|
|||
}
|
||||
|
||||
impl CookieJar {
|
||||
/// Create a new `CookieJar` from a map of request headers.
|
||||
///
|
||||
/// The cookies in `headers` will be added to the jar.
|
||||
///
|
||||
/// This is inteded to be used in middleware and other places where it might be difficult to
|
||||
/// run extractors. Normally you should create `CookieJar`s through [`FromRequest`].
|
||||
pub fn from_headers(headers: &HeaderMap) -> Self {
|
||||
let mut jar = cookie::CookieJar::new();
|
||||
for cookie in cookies_from_request(headers) {
|
||||
jar.add_original(cookie);
|
||||
}
|
||||
Self { jar }
|
||||
}
|
||||
|
||||
/// Create a new empty `CookieJar`.
|
||||
///
|
||||
/// This is inteded to be used in middleware and other places where it might be difficult to
|
||||
/// run extractors. Normally you should create `CookieJar`s through [`FromRequest`].
|
||||
///
|
||||
/// If you need a jar that contains the headers from a request use `impl From<&HeaderMap> for
|
||||
/// CookieJar`.
|
||||
pub fn new() -> Self {
|
||||
Self::default()
|
||||
}
|
||||
|
||||
/// Get a cookie from the jar.
|
||||
///
|
||||
/// # Example
|
||||
|
|
|
@ -6,6 +6,7 @@ use axum::{
|
|||
Extension,
|
||||
};
|
||||
use cookie::PrivateJar;
|
||||
use http::HeaderMap;
|
||||
use std::{convert::Infallible, fmt, marker::PhantomData};
|
||||
|
||||
/// Extractor that grabs private cookies from the request and manages the jar.
|
||||
|
@ -82,21 +83,53 @@ where
|
|||
type Rejection = <axum::Extension<K> as FromRequest<B>>::Rejection;
|
||||
|
||||
async fn from_request(req: &mut RequestParts<B>) -> Result<Self, Self::Rejection> {
|
||||
let key = Extension::<K>::from_request(req).await?.0.into();
|
||||
let key = req.extract::<Extension<K>>().await?.0.into();
|
||||
let PrivateCookieJar {
|
||||
jar,
|
||||
key,
|
||||
_marker: _,
|
||||
} = PrivateCookieJar::from_headers(req.headers(), key);
|
||||
Ok(PrivateCookieJar {
|
||||
jar,
|
||||
key,
|
||||
_marker: PhantomData,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl PrivateCookieJar {
|
||||
/// Create a new `PrivateCookieJar` from a map of request headers.
|
||||
///
|
||||
/// The valid cookies in `headers` will be added to the jar.
|
||||
///
|
||||
/// This is inteded to be used in middleware and other where places it might be difficult to
|
||||
/// run extractors. Normally you should create `PrivateCookieJar`s through [`FromRequest`].
|
||||
pub fn from_headers(headers: &HeaderMap, key: Key) -> Self {
|
||||
let mut jar = cookie::CookieJar::new();
|
||||
let mut private_jar = jar.private_mut(&key);
|
||||
for cookie in cookies_from_request(req) {
|
||||
for cookie in cookies_from_request(headers) {
|
||||
if let Some(cookie) = private_jar.decrypt(cookie) {
|
||||
private_jar.add_original(cookie);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(Self {
|
||||
Self {
|
||||
jar,
|
||||
key,
|
||||
_marker: PhantomData,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a new empty `PrivateCookieJarIter`.
|
||||
///
|
||||
/// This is inteded to be used in middleware and other places where it might be difficult to
|
||||
/// run extractors. Normally you should create `PrivateCookieJar`s through [`FromRequest`].
|
||||
pub fn new(key: Key) -> Self {
|
||||
Self {
|
||||
jar: Default::default(),
|
||||
key,
|
||||
_marker: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -7,6 +7,7 @@ use axum::{
|
|||
};
|
||||
use cookie::SignedJar;
|
||||
use cookie::{Cookie, Key};
|
||||
use http::HeaderMap;
|
||||
use std::{convert::Infallible, fmt, marker::PhantomData};
|
||||
|
||||
/// Extractor that grabs signed cookies from the request and manages the jar.
|
||||
|
@ -100,21 +101,53 @@ where
|
|||
type Rejection = <axum::Extension<K> as FromRequest<B>>::Rejection;
|
||||
|
||||
async fn from_request(req: &mut RequestParts<B>) -> Result<Self, Self::Rejection> {
|
||||
let key = Extension::<K>::from_request(req).await?.0.into();
|
||||
let key = req.extract::<Extension<K>>().await?.0.into();
|
||||
let SignedCookieJar {
|
||||
jar,
|
||||
key,
|
||||
_marker: _,
|
||||
} = SignedCookieJar::from_headers(req.headers(), key);
|
||||
Ok(SignedCookieJar {
|
||||
jar,
|
||||
key,
|
||||
_marker: PhantomData,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl SignedCookieJar {
|
||||
/// Create a new `SignedCookieJar` from a map of request headers.
|
||||
///
|
||||
/// The valid cookies in `headers` will be added to the jar.
|
||||
///
|
||||
/// This is inteded to be used in middleware and other places where it might be difficult to
|
||||
/// run extractors. Normally you should create `SignedCookieJar`s through [`FromRequest`].
|
||||
pub fn from_headers(headers: &HeaderMap, key: Key) -> Self {
|
||||
let mut jar = cookie::CookieJar::new();
|
||||
let mut signed_jar = jar.signed_mut(&key);
|
||||
for cookie in cookies_from_request(req) {
|
||||
for cookie in cookies_from_request(headers) {
|
||||
if let Some(cookie) = signed_jar.verify(cookie) {
|
||||
signed_jar.add_original(cookie);
|
||||
}
|
||||
}
|
||||
|
||||
Ok(Self {
|
||||
Self {
|
||||
jar,
|
||||
key,
|
||||
_marker: PhantomData,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// Create a new empty `SignedCookieJar`.
|
||||
///
|
||||
/// This is inteded to be used in middleware and other places where it might be difficult to
|
||||
/// run extractors. Normally you should create `SignedCookieJar`s through [`FromRequest`].
|
||||
pub fn new(key: Key) -> Self {
|
||||
Self {
|
||||
jar: Default::default(),
|
||||
key,
|
||||
_marker: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue