mirror of
https://github.com/fafhrd91/actix-web
synced 2024-11-27 17:52:56 +01:00
optional cookies features (#1981)
This commit is contained in:
parent
b37669cb3b
commit
3279070f9f
@ -1,6 +1,10 @@
|
|||||||
# Changes
|
# Changes
|
||||||
|
|
||||||
## Unreleased - 2021-xx-xx
|
## Unreleased - 2021-xx-xx
|
||||||
|
### Changed
|
||||||
|
* Feature `cookies` is now optional and enabled by default. [#1981]
|
||||||
|
|
||||||
|
[#1981]: https://github.com/actix/actix-web/pull/1981
|
||||||
|
|
||||||
|
|
||||||
## 4.0.0-beta.3 - 2021-02-10
|
## 4.0.0-beta.3 - 2021-02-10
|
||||||
|
17
Cargo.toml
17
Cargo.toml
@ -15,6 +15,7 @@ license = "MIT OR Apache-2.0"
|
|||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
[package.metadata.docs.rs]
|
[package.metadata.docs.rs]
|
||||||
|
# features that docs.rs will build with
|
||||||
features = ["openssl", "rustls", "compress", "secure-cookies"]
|
features = ["openssl", "rustls", "compress", "secure-cookies"]
|
||||||
|
|
||||||
[badges]
|
[badges]
|
||||||
@ -38,12 +39,15 @@ members = [
|
|||||||
]
|
]
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["compress"]
|
default = ["compress", "cookies"]
|
||||||
|
|
||||||
# content-encoding support
|
# content-encoding support
|
||||||
compress = ["actix-http/compress", "awc/compress"]
|
compress = ["actix-http/compress", "awc/compress"]
|
||||||
|
|
||||||
# sessions feature
|
# support for cookies
|
||||||
|
cookies = ["actix-http/cookies", "awc/cookies"]
|
||||||
|
|
||||||
|
# secure cookies feature
|
||||||
secure-cookies = ["actix-http/secure-cookies"]
|
secure-cookies = ["actix-http/secure-cookies"]
|
||||||
|
|
||||||
# openssl
|
# openssl
|
||||||
@ -95,17 +99,17 @@ futures-core = { version = "0.3.7", default-features = false }
|
|||||||
futures-util = { version = "0.3.7", default-features = false }
|
futures-util = { version = "0.3.7", default-features = false }
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
mime = "0.3"
|
mime = "0.3"
|
||||||
socket2 = "0.3.16"
|
|
||||||
pin-project = "1.0.0"
|
pin-project = "1.0.0"
|
||||||
regex = "1.4"
|
regex = "1.4"
|
||||||
serde = { version = "1.0", features = ["derive"] }
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
serde_json = "1.0"
|
serde_json = "1.0"
|
||||||
serde_urlencoded = "0.7"
|
serde_urlencoded = "0.7"
|
||||||
|
smallvec = "1.6"
|
||||||
|
socket2 = "0.3.16"
|
||||||
time = { version = "0.2.23", default-features = false, features = ["std"] }
|
time = { version = "0.2.23", default-features = false, features = ["std"] }
|
||||||
url = "2.1"
|
|
||||||
tls-openssl = { package = "openssl", version = "0.10.9", optional = true }
|
tls-openssl = { package = "openssl", version = "0.10.9", optional = true }
|
||||||
tls-rustls = { package = "rustls", version = "0.19.0", optional = true }
|
tls-rustls = { package = "rustls", version = "0.19.0", optional = true }
|
||||||
smallvec = "1.6"
|
url = "2.1"
|
||||||
|
|
||||||
[target.'cfg(windows)'.dependencies.tls-openssl]
|
[target.'cfg(windows)'.dependencies.tls-openssl]
|
||||||
version = "0.10.9"
|
version = "0.10.9"
|
||||||
@ -122,9 +126,6 @@ brotli2 = "0.3.2"
|
|||||||
flate2 = "1.0.13"
|
flate2 = "1.0.13"
|
||||||
criterion = "0.3"
|
criterion = "0.3"
|
||||||
|
|
||||||
[profile.dev]
|
|
||||||
debug = false
|
|
||||||
|
|
||||||
[profile.release]
|
[profile.release]
|
||||||
lto = true
|
lto = true
|
||||||
opt-level = 3
|
opt-level = 3
|
||||||
|
@ -1,6 +1,10 @@
|
|||||||
# Changes
|
# Changes
|
||||||
|
|
||||||
## Unreleased - 2021-xx-xx
|
## Unreleased - 2021-xx-xx
|
||||||
|
### Changed
|
||||||
|
* Feature `cookies` is now optional and disabled by default. [#1981]
|
||||||
|
|
||||||
|
[#1981]: https://github.com/actix/actix-web/pull/1981
|
||||||
|
|
||||||
|
|
||||||
## 3.0.0-beta.3 - 2021-02-10
|
## 3.0.0-beta.3 - 2021-02-10
|
||||||
|
@ -15,7 +15,8 @@ license = "MIT OR Apache-2.0"
|
|||||||
edition = "2018"
|
edition = "2018"
|
||||||
|
|
||||||
[package.metadata.docs.rs]
|
[package.metadata.docs.rs]
|
||||||
features = ["openssl", "rustls", "compress", "secure-cookies"]
|
# features that docs.rs will build with
|
||||||
|
features = ["openssl", "rustls", "compress", "cookies", "secure-cookies"]
|
||||||
|
|
||||||
[lib]
|
[lib]
|
||||||
name = "actix_http"
|
name = "actix_http"
|
||||||
@ -30,11 +31,14 @@ openssl = ["actix-tls/openssl"]
|
|||||||
# rustls support
|
# rustls support
|
||||||
rustls = ["actix-tls/rustls"]
|
rustls = ["actix-tls/rustls"]
|
||||||
|
|
||||||
# enable compressison support
|
# enable compression support
|
||||||
compress = ["flate2", "brotli2"]
|
compress = ["flate2", "brotli2"]
|
||||||
|
|
||||||
|
# support for cookies
|
||||||
|
cookies = ["cookie"]
|
||||||
|
|
||||||
# support for secure cookies
|
# support for secure cookies
|
||||||
secure-cookies = ["cookie/secure"]
|
secure-cookies = ["cookies", "cookie/secure"]
|
||||||
|
|
||||||
# trust-dns as client dns resolver
|
# trust-dns as client dns resolver
|
||||||
trust-dns = ["trust-dns-resolver"]
|
trust-dns = ["trust-dns-resolver"]
|
||||||
@ -46,24 +50,25 @@ actix-utils = "3.0.0-beta.2"
|
|||||||
actix-rt = "2"
|
actix-rt = "2"
|
||||||
actix-tls = "3.0.0-beta.2"
|
actix-tls = "3.0.0-beta.2"
|
||||||
|
|
||||||
|
ahash = "0.7"
|
||||||
base64 = "0.13"
|
base64 = "0.13"
|
||||||
bitflags = "1.2"
|
bitflags = "1.2"
|
||||||
bytes = "1"
|
bytes = "1"
|
||||||
bytestring = "1"
|
bytestring = "1"
|
||||||
cookie = { version = "0.14.1", features = ["percent-encode"] }
|
cfg-if = "1"
|
||||||
|
cookie = { version = "0.14.1", features = ["percent-encode"], optional = true }
|
||||||
derive_more = "0.99.5"
|
derive_more = "0.99.5"
|
||||||
encoding_rs = "0.8"
|
encoding_rs = "0.8"
|
||||||
futures-channel = { version = "0.3.7", default-features = false, features = ["alloc"] }
|
futures-channel = { version = "0.3.7", default-features = false, features = ["alloc"] }
|
||||||
futures-core = { version = "0.3.7", default-features = false, features = ["alloc"] }
|
futures-core = { version = "0.3.7", default-features = false, features = ["alloc"] }
|
||||||
futures-util = { version = "0.3.7", default-features = false, features = ["alloc", "sink"] }
|
futures-util = { version = "0.3.7", default-features = false, features = ["alloc", "sink"] }
|
||||||
ahash = "0.7"
|
|
||||||
h2 = "0.3.0"
|
h2 = "0.3.0"
|
||||||
http = "0.2.2"
|
http = "0.2.2"
|
||||||
httparse = "1.3"
|
httparse = "1.3"
|
||||||
indexmap = "1.3"
|
indexmap = "1.3"
|
||||||
itoa = "0.4"
|
itoa = "0.4"
|
||||||
lazy_static = "1.4"
|
|
||||||
language-tags = "0.2"
|
language-tags = "0.2"
|
||||||
|
lazy_static = "1.4"
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
mime = "0.3"
|
mime = "0.3"
|
||||||
percent-encoding = "2.1"
|
percent-encoding = "2.1"
|
||||||
@ -72,10 +77,10 @@ rand = "0.8"
|
|||||||
regex = "1.3"
|
regex = "1.3"
|
||||||
serde = "1.0"
|
serde = "1.0"
|
||||||
serde_json = "1.0"
|
serde_json = "1.0"
|
||||||
sha-1 = "0.9"
|
|
||||||
smallvec = "1.6"
|
|
||||||
slab = "0.4"
|
|
||||||
serde_urlencoded = "0.7"
|
serde_urlencoded = "0.7"
|
||||||
|
sha-1 = "0.9"
|
||||||
|
slab = "0.4"
|
||||||
|
smallvec = "1.6"
|
||||||
time = { version = "0.2.23", default-features = false, features = ["std"] }
|
time = { version = "0.2.23", default-features = false, features = ["std"] }
|
||||||
|
|
||||||
# compression
|
# compression
|
||||||
|
@ -19,10 +19,12 @@ use serde_json::error::Error as JsonError;
|
|||||||
use serde_urlencoded::ser::Error as FormError;
|
use serde_urlencoded::ser::Error as FormError;
|
||||||
|
|
||||||
use crate::body::Body;
|
use crate::body::Body;
|
||||||
pub use crate::cookie::ParseError as CookieParseError;
|
|
||||||
use crate::helpers::Writer;
|
use crate::helpers::Writer;
|
||||||
use crate::response::{Response, ResponseBuilder};
|
use crate::response::{Response, ResponseBuilder};
|
||||||
|
|
||||||
|
#[cfg(feature = "cookies")]
|
||||||
|
pub use crate::cookie::ParseError as CookieParseError;
|
||||||
|
|
||||||
/// A specialized [`std::result::Result`]
|
/// A specialized [`std::result::Result`]
|
||||||
/// for actix web operations
|
/// for actix web operations
|
||||||
///
|
///
|
||||||
@ -397,6 +399,7 @@ impl ResponseError for PayloadError {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Return `BadRequest` for `cookie::ParseError`
|
/// Return `BadRequest` for `cookie::ParseError`
|
||||||
|
#[cfg(feature = "cookies")]
|
||||||
impl ResponseError for crate::cookie::ParseError {
|
impl ResponseError for crate::cookie::ParseError {
|
||||||
fn status_code(&self) -> StatusCode {
|
fn status_code(&self) -> StatusCode {
|
||||||
StatusCode::BAD_REQUEST
|
StatusCode::BAD_REQUEST
|
||||||
|
@ -549,7 +549,6 @@ mod tests {
|
|||||||
);
|
);
|
||||||
let data =
|
let data =
|
||||||
String::from_utf8(Vec::from(bytes.split().freeze().as_ref())).unwrap();
|
String::from_utf8(Vec::from(bytes.split().freeze().as_ref())).unwrap();
|
||||||
eprintln!("{}", &data);
|
|
||||||
|
|
||||||
assert!(data.contains("Content-Length: 0\r\n"));
|
assert!(data.contains("Content-Length: 0\r\n"));
|
||||||
assert!(data.contains("Connection: close\r\n"));
|
assert!(data.contains("Connection: close\r\n"));
|
||||||
|
@ -5,12 +5,14 @@ use encoding_rs::{Encoding, UTF_8};
|
|||||||
use http::header;
|
use http::header;
|
||||||
use mime::Mime;
|
use mime::Mime;
|
||||||
|
|
||||||
use crate::cookie::Cookie;
|
use crate::error::{ContentTypeError, ParseError};
|
||||||
use crate::error::{ContentTypeError, CookieParseError, ParseError};
|
|
||||||
use crate::extensions::Extensions;
|
use crate::extensions::Extensions;
|
||||||
use crate::header::{Header, HeaderMap};
|
use crate::header::{Header, HeaderMap};
|
||||||
use crate::payload::Payload;
|
use crate::payload::Payload;
|
||||||
|
#[cfg(feature = "cookies")]
|
||||||
|
use crate::{cookie::Cookie, error::CookieParseError};
|
||||||
|
|
||||||
|
#[cfg(feature = "cookies")]
|
||||||
struct Cookies(Vec<Cookie<'static>>);
|
struct Cookies(Vec<Cookie<'static>>);
|
||||||
|
|
||||||
/// Trait that implements general purpose operations on HTTP messages.
|
/// Trait that implements general purpose operations on HTTP messages.
|
||||||
@ -104,7 +106,7 @@ pub trait HttpMessage: Sized {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Load request cookies.
|
/// Load request cookies.
|
||||||
#[inline]
|
#[cfg(feature = "cookies")]
|
||||||
fn cookies(&self) -> Result<Ref<'_, Vec<Cookie<'static>>>, CookieParseError> {
|
fn cookies(&self) -> Result<Ref<'_, Vec<Cookie<'static>>>, CookieParseError> {
|
||||||
if self.extensions().get::<Cookies>().is_none() {
|
if self.extensions().get::<Cookies>().is_none() {
|
||||||
let mut cookies = Vec::new();
|
let mut cookies = Vec::new();
|
||||||
@ -119,12 +121,14 @@ pub trait HttpMessage: Sized {
|
|||||||
}
|
}
|
||||||
self.extensions_mut().insert(Cookies(cookies));
|
self.extensions_mut().insert(Cookies(cookies));
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(Ref::map(self.extensions(), |ext| {
|
Ok(Ref::map(self.extensions(), |ext| {
|
||||||
&ext.get::<Cookies>().unwrap().0
|
&ext.get::<Cookies>().unwrap().0
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return request cookie.
|
/// Return request cookie.
|
||||||
|
#[cfg(feature = "cookies")]
|
||||||
fn cookie(&self, name: &str) -> Option<Cookie<'static>> {
|
fn cookie(&self, name: &str) -> Option<Cookie<'static>> {
|
||||||
if let Ok(cookies) = self.cookies() {
|
if let Ok(cookies) = self.cookies() {
|
||||||
for cookie in cookies.iter() {
|
for cookie in cookies.iter() {
|
||||||
|
@ -1,4 +1,19 @@
|
|||||||
//! HTTP primitives for the Actix ecosystem.
|
//! HTTP primitives for the Actix ecosystem.
|
||||||
|
//!
|
||||||
|
//! ## Crate Features
|
||||||
|
//! | Feature | Functionality |
|
||||||
|
//! | ---------------- | ----------------------------------------------------- |
|
||||||
|
//! | `openssl` | TLS support via [OpenSSL]. |
|
||||||
|
//! | `rustls` | TLS support via [rustls]. |
|
||||||
|
//! | `compress` | Payload compression support. (Deflate, Gzip & Brotli) |
|
||||||
|
//! | `cookies` | Support for cookies backed by the [cookie] crate. |
|
||||||
|
//! | `secure-cookies` | Adds for secure cookies. Enables `cookies` feature. |
|
||||||
|
//! | `trust-dns` | Use [trust-dns] as the client DNS resolver. |
|
||||||
|
//!
|
||||||
|
//! [OpenSSL]: https://crates.io/crates/openssl
|
||||||
|
//! [rustls]: https://crates.io/crates/rustls
|
||||||
|
//! [cookie]: https://crates.io/crates/cookie
|
||||||
|
//! [trust-dns]: https://crates.io/crates/trust-dns
|
||||||
|
|
||||||
#![deny(rust_2018_idioms, nonstandard_style)]
|
#![deny(rust_2018_idioms, nonstandard_style)]
|
||||||
#![allow(
|
#![allow(
|
||||||
@ -34,13 +49,15 @@ mod response;
|
|||||||
mod service;
|
mod service;
|
||||||
mod time_parser;
|
mod time_parser;
|
||||||
|
|
||||||
pub use cookie;
|
|
||||||
pub mod error;
|
pub mod error;
|
||||||
pub mod h1;
|
pub mod h1;
|
||||||
pub mod h2;
|
pub mod h2;
|
||||||
pub mod test;
|
pub mod test;
|
||||||
pub mod ws;
|
pub mod ws;
|
||||||
|
|
||||||
|
#[cfg(feature = "cookies")]
|
||||||
|
pub use cookie;
|
||||||
|
|
||||||
pub use self::builder::HttpServiceBuilder;
|
pub use self::builder::HttpServiceBuilder;
|
||||||
pub use self::config::{KeepAlive, ServiceConfig};
|
pub use self::config::{KeepAlive, ServiceConfig};
|
||||||
pub use self::error::{Error, ResponseError, Result};
|
pub use self::error::{Error, ResponseError, Result};
|
||||||
@ -61,6 +78,7 @@ pub mod http {
|
|||||||
pub use http::{uri, Error, Uri};
|
pub use http::{uri, Error, Uri};
|
||||||
pub use http::{Method, StatusCode, Version};
|
pub use http::{Method, StatusCode, Version};
|
||||||
|
|
||||||
|
#[cfg(feature = "cookies")]
|
||||||
pub use crate::cookie::{Cookie, CookieBuilder};
|
pub use crate::cookie::{Cookie, CookieBuilder};
|
||||||
pub use crate::header::HeaderMap;
|
pub use crate::header::HeaderMap;
|
||||||
|
|
||||||
|
@ -16,13 +16,17 @@ use futures_core::Stream;
|
|||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
|
|
||||||
use crate::body::{Body, BodyStream, MessageBody, ResponseBody};
|
use crate::body::{Body, BodyStream, MessageBody, ResponseBody};
|
||||||
use crate::cookie::{Cookie, CookieJar};
|
|
||||||
use crate::error::Error;
|
use crate::error::Error;
|
||||||
use crate::extensions::Extensions;
|
use crate::extensions::Extensions;
|
||||||
use crate::header::{IntoHeaderPair, IntoHeaderValue};
|
use crate::header::{IntoHeaderPair, IntoHeaderValue};
|
||||||
use crate::http::header::{self, HeaderName, HeaderValue};
|
use crate::http::header::{self, HeaderName};
|
||||||
use crate::http::{Error as HttpError, HeaderMap, StatusCode};
|
use crate::http::{Error as HttpError, HeaderMap, StatusCode};
|
||||||
use crate::message::{BoxedResponseHead, ConnectionType, ResponseHead};
|
use crate::message::{BoxedResponseHead, ConnectionType, ResponseHead};
|
||||||
|
#[cfg(feature = "cookies")]
|
||||||
|
use crate::{
|
||||||
|
cookie::{Cookie, CookieJar},
|
||||||
|
http::header::HeaderValue,
|
||||||
|
};
|
||||||
|
|
||||||
/// An HTTP Response
|
/// An HTTP Response
|
||||||
pub struct Response<B = Body> {
|
pub struct Response<B = Body> {
|
||||||
@ -133,6 +137,7 @@ impl<B> Response<B> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Get an iterator for the cookies set by this response
|
/// Get an iterator for the cookies set by this response
|
||||||
|
#[cfg(feature = "cookies")]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn cookies(&self) -> CookieIter<'_> {
|
pub fn cookies(&self) -> CookieIter<'_> {
|
||||||
CookieIter {
|
CookieIter {
|
||||||
@ -141,6 +146,7 @@ impl<B> Response<B> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Add a cookie to this response
|
/// Add a cookie to this response
|
||||||
|
#[cfg(feature = "cookies")]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn add_cookie(&mut self, cookie: &Cookie<'_>) -> Result<(), HttpError> {
|
pub fn add_cookie(&mut self, cookie: &Cookie<'_>) -> Result<(), HttpError> {
|
||||||
let h = &mut self.head.headers;
|
let h = &mut self.head.headers;
|
||||||
@ -153,6 +159,7 @@ impl<B> Response<B> {
|
|||||||
|
|
||||||
/// Remove all cookies with the given name from this response. Returns
|
/// Remove all cookies with the given name from this response. Returns
|
||||||
/// the number of cookies removed.
|
/// the number of cookies removed.
|
||||||
|
#[cfg(feature = "cookies")]
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn del_cookie(&mut self, name: &str) -> usize {
|
pub fn del_cookie(&mut self, name: &str) -> usize {
|
||||||
let h = &mut self.head.headers;
|
let h = &mut self.head.headers;
|
||||||
@ -298,10 +305,12 @@ impl Future for Response {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "cookies")]
|
||||||
pub struct CookieIter<'a> {
|
pub struct CookieIter<'a> {
|
||||||
iter: header::GetAll<'a>,
|
iter: header::GetAll<'a>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "cookies")]
|
||||||
impl<'a> Iterator for CookieIter<'a> {
|
impl<'a> Iterator for CookieIter<'a> {
|
||||||
type Item = Cookie<'a>;
|
type Item = Cookie<'a>;
|
||||||
|
|
||||||
@ -316,13 +325,13 @@ impl<'a> Iterator for CookieIter<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An HTTP response builder
|
/// An HTTP response builder.
|
||||||
///
|
///
|
||||||
/// This type can be used to construct an instance of `Response` through a
|
/// This type can be used to construct an instance of `Response` through a builder-like pattern.
|
||||||
/// builder-like pattern.
|
|
||||||
pub struct ResponseBuilder {
|
pub struct ResponseBuilder {
|
||||||
head: Option<BoxedResponseHead>,
|
head: Option<BoxedResponseHead>,
|
||||||
err: Option<HttpError>,
|
err: Option<HttpError>,
|
||||||
|
#[cfg(feature = "cookies")]
|
||||||
cookies: Option<CookieJar>,
|
cookies: Option<CookieJar>,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -333,6 +342,7 @@ impl ResponseBuilder {
|
|||||||
ResponseBuilder {
|
ResponseBuilder {
|
||||||
head: Some(BoxedResponseHead::new(status)),
|
head: Some(BoxedResponseHead::new(status)),
|
||||||
err: None,
|
err: None,
|
||||||
|
#[cfg(feature = "cookies")]
|
||||||
cookies: None,
|
cookies: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -531,6 +541,7 @@ impl ResponseBuilder {
|
|||||||
/// .finish()
|
/// .finish()
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
#[cfg(feature = "cookies")]
|
||||||
pub fn cookie<'c>(&mut self, cookie: Cookie<'c>) -> &mut Self {
|
pub fn cookie<'c>(&mut self, cookie: Cookie<'c>) -> &mut Self {
|
||||||
if self.cookies.is_none() {
|
if self.cookies.is_none() {
|
||||||
let mut jar = CookieJar::new();
|
let mut jar = CookieJar::new();
|
||||||
@ -557,6 +568,7 @@ impl ResponseBuilder {
|
|||||||
/// builder.finish()
|
/// builder.finish()
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
#[cfg(feature = "cookies")]
|
||||||
pub fn del_cookie<'a>(&mut self, cookie: &Cookie<'a>) -> &mut Self {
|
pub fn del_cookie<'a>(&mut self, cookie: &Cookie<'a>) -> &mut Self {
|
||||||
if self.cookies.is_none() {
|
if self.cookies.is_none() {
|
||||||
self.cookies = Some(CookieJar::new())
|
self.cookies = Some(CookieJar::new())
|
||||||
@ -624,8 +636,11 @@ impl ResponseBuilder {
|
|||||||
return Response::from(Error::from(e)).into_body();
|
return Response::from(Error::from(e)).into_body();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// allow unused mut when cookies feature is disabled
|
||||||
|
#[allow(unused_mut)]
|
||||||
let mut response = self.head.take().expect("cannot reuse response builder");
|
let mut response = self.head.take().expect("cannot reuse response builder");
|
||||||
|
|
||||||
|
#[cfg(feature = "cookies")]
|
||||||
if let Some(ref jar) = self.cookies {
|
if let Some(ref jar) = self.cookies {
|
||||||
for cookie in jar.delta() {
|
for cookie in jar.delta() {
|
||||||
match HeaderValue::from_str(&cookie.to_string()) {
|
match HeaderValue::from_str(&cookie.to_string()) {
|
||||||
@ -693,6 +708,7 @@ impl ResponseBuilder {
|
|||||||
ResponseBuilder {
|
ResponseBuilder {
|
||||||
head: self.head.take(),
|
head: self.head.take(),
|
||||||
err: self.err.take(),
|
err: self.err.take(),
|
||||||
|
#[cfg(feature = "cookies")]
|
||||||
cookies: self.cookies.take(),
|
cookies: self.cookies.take(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -712,21 +728,28 @@ fn parts<'a>(
|
|||||||
/// Convert `Response` to a `ResponseBuilder`. Body get dropped.
|
/// Convert `Response` to a `ResponseBuilder`. Body get dropped.
|
||||||
impl<B> From<Response<B>> for ResponseBuilder {
|
impl<B> From<Response<B>> for ResponseBuilder {
|
||||||
fn from(res: Response<B>) -> ResponseBuilder {
|
fn from(res: Response<B>) -> ResponseBuilder {
|
||||||
// If this response has cookies, load them into a jar
|
#[cfg(feature = "cookies")]
|
||||||
let mut jar: Option<CookieJar> = None;
|
let jar = {
|
||||||
for c in res.cookies() {
|
// If this response has cookies, load them into a jar
|
||||||
if let Some(ref mut j) = jar {
|
let mut jar: Option<CookieJar> = None;
|
||||||
j.add_original(c.into_owned());
|
|
||||||
} else {
|
for c in res.cookies() {
|
||||||
let mut j = CookieJar::new();
|
if let Some(ref mut j) = jar {
|
||||||
j.add_original(c.into_owned());
|
j.add_original(c.into_owned());
|
||||||
jar = Some(j);
|
} else {
|
||||||
|
let mut j = CookieJar::new();
|
||||||
|
j.add_original(c.into_owned());
|
||||||
|
jar = Some(j);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
jar
|
||||||
|
};
|
||||||
|
|
||||||
ResponseBuilder {
|
ResponseBuilder {
|
||||||
head: Some(res.head),
|
head: Some(res.head),
|
||||||
err: None,
|
err: None,
|
||||||
|
#[cfg(feature = "cookies")]
|
||||||
cookies: jar,
|
cookies: jar,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -735,22 +758,6 @@ impl<B> From<Response<B>> for ResponseBuilder {
|
|||||||
/// Convert `ResponseHead` to a `ResponseBuilder`
|
/// Convert `ResponseHead` to a `ResponseBuilder`
|
||||||
impl<'a> From<&'a ResponseHead> for ResponseBuilder {
|
impl<'a> From<&'a ResponseHead> for ResponseBuilder {
|
||||||
fn from(head: &'a ResponseHead) -> ResponseBuilder {
|
fn from(head: &'a ResponseHead) -> ResponseBuilder {
|
||||||
// If this response has cookies, load them into a jar
|
|
||||||
let mut jar: Option<CookieJar> = None;
|
|
||||||
|
|
||||||
let cookies = CookieIter {
|
|
||||||
iter: head.headers.get_all(header::SET_COOKIE),
|
|
||||||
};
|
|
||||||
for c in cookies {
|
|
||||||
if let Some(ref mut j) = jar {
|
|
||||||
j.add_original(c.into_owned());
|
|
||||||
} else {
|
|
||||||
let mut j = CookieJar::new();
|
|
||||||
j.add_original(c.into_owned());
|
|
||||||
jar = Some(j);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut msg = BoxedResponseHead::new(head.status);
|
let mut msg = BoxedResponseHead::new(head.status);
|
||||||
msg.version = head.version;
|
msg.version = head.version;
|
||||||
msg.reason = head.reason;
|
msg.reason = head.reason;
|
||||||
@ -761,9 +768,32 @@ impl<'a> From<&'a ResponseHead> for ResponseBuilder {
|
|||||||
|
|
||||||
msg.no_chunking(!head.chunked());
|
msg.no_chunking(!head.chunked());
|
||||||
|
|
||||||
|
#[cfg(feature = "cookies")]
|
||||||
|
let jar = {
|
||||||
|
// If this response has cookies, load them into a jar
|
||||||
|
let mut jar: Option<CookieJar> = None;
|
||||||
|
|
||||||
|
let cookies = CookieIter {
|
||||||
|
iter: head.headers.get_all(header::SET_COOKIE),
|
||||||
|
};
|
||||||
|
|
||||||
|
for c in cookies {
|
||||||
|
if let Some(ref mut j) = jar {
|
||||||
|
j.add_original(c.into_owned());
|
||||||
|
} else {
|
||||||
|
let mut j = CookieJar::new();
|
||||||
|
j.add_original(c.into_owned());
|
||||||
|
jar = Some(j);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
jar
|
||||||
|
};
|
||||||
|
|
||||||
ResponseBuilder {
|
ResponseBuilder {
|
||||||
head: Some(msg),
|
head: Some(msg),
|
||||||
err: None,
|
err: None,
|
||||||
|
#[cfg(feature = "cookies")]
|
||||||
cookies: jar,
|
cookies: jar,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,13 +11,14 @@ use std::{
|
|||||||
|
|
||||||
use actix_codec::{AsyncRead, AsyncWrite, ReadBuf};
|
use actix_codec::{AsyncRead, AsyncWrite, ReadBuf};
|
||||||
use bytes::{Bytes, BytesMut};
|
use bytes::{Bytes, BytesMut};
|
||||||
use http::{
|
use http::{Method, Uri, Version};
|
||||||
header::{self, HeaderValue},
|
|
||||||
Method, Uri, Version,
|
|
||||||
};
|
|
||||||
|
|
||||||
|
#[cfg(feature = "cookies")]
|
||||||
use crate::{
|
use crate::{
|
||||||
cookie::{Cookie, CookieJar},
|
cookie::{Cookie, CookieJar},
|
||||||
|
header::{self, HeaderValue},
|
||||||
|
};
|
||||||
|
use crate::{
|
||||||
header::{HeaderMap, IntoHeaderPair},
|
header::{HeaderMap, IntoHeaderPair},
|
||||||
payload::Payload,
|
payload::Payload,
|
||||||
Request,
|
Request,
|
||||||
@ -53,6 +54,7 @@ struct Inner {
|
|||||||
method: Method,
|
method: Method,
|
||||||
uri: Uri,
|
uri: Uri,
|
||||||
headers: HeaderMap,
|
headers: HeaderMap,
|
||||||
|
#[cfg(feature = "cookies")]
|
||||||
cookies: CookieJar,
|
cookies: CookieJar,
|
||||||
payload: Option<Payload>,
|
payload: Option<Payload>,
|
||||||
}
|
}
|
||||||
@ -64,6 +66,7 @@ impl Default for TestRequest {
|
|||||||
uri: Uri::from_str("/").unwrap(),
|
uri: Uri::from_str("/").unwrap(),
|
||||||
version: Version::HTTP_11,
|
version: Version::HTTP_11,
|
||||||
headers: HeaderMap::new(),
|
headers: HeaderMap::new(),
|
||||||
|
#[cfg(feature = "cookies")]
|
||||||
cookies: CookieJar::new(),
|
cookies: CookieJar::new(),
|
||||||
payload: None,
|
payload: None,
|
||||||
}))
|
}))
|
||||||
@ -132,6 +135,7 @@ impl TestRequest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Set cookie for this request.
|
/// Set cookie for this request.
|
||||||
|
#[cfg(feature = "cookies")]
|
||||||
pub fn cookie<'a>(&mut self, cookie: Cookie<'a>) -> &mut Self {
|
pub fn cookie<'a>(&mut self, cookie: Cookie<'a>) -> &mut Self {
|
||||||
parts(&mut self.0).cookies.add(cookie.into_owned());
|
parts(&mut self.0).cookies.add(cookie.into_owned());
|
||||||
self
|
self
|
||||||
@ -165,17 +169,20 @@ impl TestRequest {
|
|||||||
head.version = inner.version;
|
head.version = inner.version;
|
||||||
head.headers = inner.headers;
|
head.headers = inner.headers;
|
||||||
|
|
||||||
let cookie: String = inner
|
#[cfg(feature = "cookies")]
|
||||||
.cookies
|
{
|
||||||
.delta()
|
let cookie: String = inner
|
||||||
// ensure only name=value is written to cookie header
|
.cookies
|
||||||
.map(|c| Cookie::new(c.name(), c.value()).encoded().to_string())
|
.delta()
|
||||||
.collect::<Vec<_>>()
|
// ensure only name=value is written to cookie header
|
||||||
.join("; ");
|
.map(|c| Cookie::new(c.name(), c.value()).encoded().to_string())
|
||||||
|
.collect::<Vec<_>>()
|
||||||
|
.join("; ");
|
||||||
|
|
||||||
if !cookie.is_empty() {
|
if !cookie.is_empty() {
|
||||||
head.headers
|
head.headers
|
||||||
.insert(header::COOKIE, HeaderValue::from_str(&cookie).unwrap());
|
.insert(header::COOKIE, HeaderValue::from_str(&cookie).unwrap());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
req
|
req
|
||||||
|
@ -1,6 +1,10 @@
|
|||||||
# Changes
|
# Changes
|
||||||
|
|
||||||
## Unreleased - 2021-xx-xx
|
## Unreleased - 2021-xx-xx
|
||||||
|
### Changed
|
||||||
|
* Feature `cookies` is now optional and enabled by default. [#1981]
|
||||||
|
|
||||||
|
[#1981]: https://github.com/actix/actix-web/pull/1981
|
||||||
|
|
||||||
|
|
||||||
## 3.0.0-beta.2 - 2021-02-10
|
## 3.0.0-beta.2 - 2021-02-10
|
||||||
|
@ -22,10 +22,11 @@ name = "awc"
|
|||||||
path = "src/lib.rs"
|
path = "src/lib.rs"
|
||||||
|
|
||||||
[package.metadata.docs.rs]
|
[package.metadata.docs.rs]
|
||||||
features = ["openssl", "rustls", "compress"]
|
# features that docs.rs will build with
|
||||||
|
features = ["openssl", "rustls", "compress", "cookies"]
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["compress"]
|
default = ["compress", "cookies"]
|
||||||
|
|
||||||
# openssl
|
# openssl
|
||||||
openssl = ["tls-openssl", "actix-http/openssl"]
|
openssl = ["tls-openssl", "actix-http/openssl"]
|
||||||
@ -36,6 +37,9 @@ rustls = ["tls-rustls", "actix-http/rustls"]
|
|||||||
# content-encoding support
|
# content-encoding support
|
||||||
compress = ["actix-http/compress"]
|
compress = ["actix-http/compress"]
|
||||||
|
|
||||||
|
# cookie parsing and cookie jar
|
||||||
|
cookies = ["actix-http/cookies"]
|
||||||
|
|
||||||
# trust-dns as dns resolver
|
# trust-dns as dns resolver
|
||||||
trust-dns = ["actix-http/trust-dns"]
|
trust-dns = ["actix-http/trust-dns"]
|
||||||
|
|
||||||
|
@ -97,7 +97,9 @@ use std::convert::TryFrom;
|
|||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
pub use actix_http::{client::Connector, cookie, http};
|
#[cfg(feature = "cookies")]
|
||||||
|
pub use actix_http::cookie;
|
||||||
|
pub use actix_http::{client::Connector, http};
|
||||||
|
|
||||||
use actix_http::http::{Error as HttpError, HeaderMap, Method, Uri};
|
use actix_http::http::{Error as HttpError, HeaderMap, Method, Uri};
|
||||||
use actix_http::RequestHead;
|
use actix_http::RequestHead;
|
||||||
|
@ -8,6 +8,7 @@ use futures_core::Stream;
|
|||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
|
|
||||||
use actix_http::body::Body;
|
use actix_http::body::Body;
|
||||||
|
#[cfg(feature = "cookies")]
|
||||||
use actix_http::cookie::{Cookie, CookieJar};
|
use actix_http::cookie::{Cookie, CookieJar};
|
||||||
use actix_http::http::header::{self, IntoHeaderPair};
|
use actix_http::http::header::{self, IntoHeaderPair};
|
||||||
use actix_http::http::{
|
use actix_http::http::{
|
||||||
@ -54,10 +55,12 @@ pub struct ClientRequest {
|
|||||||
pub(crate) head: RequestHead,
|
pub(crate) head: RequestHead,
|
||||||
err: Option<HttpError>,
|
err: Option<HttpError>,
|
||||||
addr: Option<net::SocketAddr>,
|
addr: Option<net::SocketAddr>,
|
||||||
cookies: Option<CookieJar>,
|
|
||||||
response_decompress: bool,
|
response_decompress: bool,
|
||||||
timeout: Option<Duration>,
|
timeout: Option<Duration>,
|
||||||
config: Rc<ClientConfig>,
|
config: Rc<ClientConfig>,
|
||||||
|
|
||||||
|
#[cfg(feature = "cookies")]
|
||||||
|
cookies: Option<CookieJar>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ClientRequest {
|
impl ClientRequest {
|
||||||
@ -72,6 +75,7 @@ impl ClientRequest {
|
|||||||
head: RequestHead::default(),
|
head: RequestHead::default(),
|
||||||
err: None,
|
err: None,
|
||||||
addr: None,
|
addr: None,
|
||||||
|
#[cfg(feature = "cookies")]
|
||||||
cookies: None,
|
cookies: None,
|
||||||
timeout: None,
|
timeout: None,
|
||||||
response_decompress: true,
|
response_decompress: true,
|
||||||
@ -290,6 +294,7 @@ impl ClientRequest {
|
|||||||
/// println!("Response: {:?}", resp);
|
/// println!("Response: {:?}", resp);
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
#[cfg(feature = "cookies")]
|
||||||
pub fn cookie(mut self, cookie: Cookie<'_>) -> Self {
|
pub fn cookie(mut self, cookie: Cookie<'_>) -> Self {
|
||||||
if self.cookies.is_none() {
|
if self.cookies.is_none() {
|
||||||
let mut jar = CookieJar::new();
|
let mut jar = CookieJar::new();
|
||||||
@ -472,7 +477,8 @@ impl ClientRequest {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn prep_for_sending(mut self) -> Result<Self, PrepForSendingError> {
|
// allow unused mut when cookies feature is disabled
|
||||||
|
fn prep_for_sending(#[allow(unused_mut)] mut self) -> Result<Self, PrepForSendingError> {
|
||||||
if let Some(e) = self.err {
|
if let Some(e) = self.err {
|
||||||
return Err(e.into());
|
return Err(e.into());
|
||||||
}
|
}
|
||||||
@ -493,6 +499,7 @@ impl ClientRequest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// set cookies
|
// set cookies
|
||||||
|
#[cfg(feature = "cookies")]
|
||||||
if let Some(ref mut jar) = self.cookies {
|
if let Some(ref mut jar) = self.cookies {
|
||||||
let cookie: String = jar
|
let cookie: String = jar
|
||||||
.delta()
|
.delta()
|
||||||
|
@ -1,20 +1,25 @@
|
|||||||
use std::cell::{Ref, RefMut};
|
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::future::Future;
|
use std::future::Future;
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
use std::pin::Pin;
|
use std::pin::Pin;
|
||||||
use std::task::{Context, Poll};
|
use std::task::{Context, Poll};
|
||||||
|
use std::{
|
||||||
|
cell::{Ref, RefMut},
|
||||||
|
mem,
|
||||||
|
};
|
||||||
|
|
||||||
use bytes::{Bytes, BytesMut};
|
use bytes::{Bytes, BytesMut};
|
||||||
use futures_core::{ready, Stream};
|
use futures_core::{ready, Stream};
|
||||||
|
|
||||||
use actix_http::cookie::Cookie;
|
use actix_http::error::PayloadError;
|
||||||
use actix_http::error::{CookieParseError, PayloadError};
|
use actix_http::http::header;
|
||||||
use actix_http::http::header::{CONTENT_LENGTH, SET_COOKIE};
|
|
||||||
use actix_http::http::{HeaderMap, StatusCode, Version};
|
use actix_http::http::{HeaderMap, StatusCode, Version};
|
||||||
use actix_http::{Extensions, HttpMessage, Payload, PayloadStream, ResponseHead};
|
use actix_http::{Extensions, HttpMessage, Payload, PayloadStream, ResponseHead};
|
||||||
use serde::de::DeserializeOwned;
|
use serde::de::DeserializeOwned;
|
||||||
|
|
||||||
|
#[cfg(feature = "cookies")]
|
||||||
|
use actix_http::{cookie::Cookie, error::CookieParseError};
|
||||||
|
|
||||||
use crate::error::JsonPayloadError;
|
use crate::error::JsonPayloadError;
|
||||||
|
|
||||||
/// Client Response
|
/// Client Response
|
||||||
@ -39,17 +44,17 @@ impl<S> HttpMessage for ClientResponse<S> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn take_payload(&mut self) -> Payload<S> {
|
fn take_payload(&mut self) -> Payload<S> {
|
||||||
std::mem::replace(&mut self.payload, Payload::None)
|
mem::replace(&mut self.payload, Payload::None)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Load request cookies.
|
/// Load request cookies.
|
||||||
#[inline]
|
#[cfg(feature = "cookies")]
|
||||||
fn cookies(&self) -> Result<Ref<'_, Vec<Cookie<'static>>>, CookieParseError> {
|
fn cookies(&self) -> Result<Ref<'_, Vec<Cookie<'static>>>, CookieParseError> {
|
||||||
struct Cookies(Vec<Cookie<'static>>);
|
struct Cookies(Vec<Cookie<'static>>);
|
||||||
|
|
||||||
if self.extensions().get::<Cookies>().is_none() {
|
if self.extensions().get::<Cookies>().is_none() {
|
||||||
let mut cookies = Vec::new();
|
let mut cookies = Vec::new();
|
||||||
for hdr in self.headers().get_all(&SET_COOKIE) {
|
for hdr in self.headers().get_all(&header::SET_COOKIE) {
|
||||||
let s = std::str::from_utf8(hdr.as_bytes()).map_err(CookieParseError::from)?;
|
let s = std::str::from_utf8(hdr.as_bytes()).map_err(CookieParseError::from)?;
|
||||||
cookies.push(Cookie::parse_encoded(s)?.into_owned());
|
cookies.push(Cookie::parse_encoded(s)?.into_owned());
|
||||||
}
|
}
|
||||||
@ -161,7 +166,7 @@ where
|
|||||||
/// Create `MessageBody` for request.
|
/// Create `MessageBody` for request.
|
||||||
pub fn new(res: &mut ClientResponse<S>) -> MessageBody<S> {
|
pub fn new(res: &mut ClientResponse<S>) -> MessageBody<S> {
|
||||||
let mut len = None;
|
let mut len = None;
|
||||||
if let Some(l) = res.headers().get(&CONTENT_LENGTH) {
|
if let Some(l) = res.headers().get(&header::CONTENT_LENGTH) {
|
||||||
if let Ok(s) = l.to_str() {
|
if let Ok(s) = l.to_str() {
|
||||||
if let Ok(l) = s.parse::<usize>() {
|
if let Ok(l) = s.parse::<usize>() {
|
||||||
len = Some(l)
|
len = Some(l)
|
||||||
@ -256,7 +261,7 @@ where
|
|||||||
}
|
}
|
||||||
|
|
||||||
let mut len = None;
|
let mut len = None;
|
||||||
if let Some(l) = req.headers().get(&CONTENT_LENGTH) {
|
if let Some(l) = req.headers().get(&header::CONTENT_LENGTH) {
|
||||||
if let Ok(s) = l.to_str() {
|
if let Ok(s) = l.to_str() {
|
||||||
if let Ok(l) = s.parse::<usize>() {
|
if let Ok(l) = s.parse::<usize>() {
|
||||||
len = Some(l)
|
len = Some(l)
|
||||||
|
@ -1,9 +1,13 @@
|
|||||||
//! Test helpers for actix http client to use during testing.
|
//! Test helpers for actix http client to use during testing.
|
||||||
use std::convert::TryFrom;
|
use std::convert::TryFrom;
|
||||||
|
|
||||||
use actix_http::cookie::{Cookie, CookieJar};
|
use actix_http::http::header::{Header, IntoHeaderValue};
|
||||||
use actix_http::http::header::{self, Header, HeaderValue, IntoHeaderValue};
|
|
||||||
use actix_http::http::{Error as HttpError, HeaderName, StatusCode, Version};
|
use actix_http::http::{Error as HttpError, HeaderName, StatusCode, Version};
|
||||||
|
#[cfg(feature = "cookies")]
|
||||||
|
use actix_http::{
|
||||||
|
cookie::{Cookie, CookieJar},
|
||||||
|
http::header::{self, HeaderValue},
|
||||||
|
};
|
||||||
use actix_http::{h1, Payload, ResponseHead};
|
use actix_http::{h1, Payload, ResponseHead};
|
||||||
use bytes::Bytes;
|
use bytes::Bytes;
|
||||||
|
|
||||||
@ -12,6 +16,7 @@ use crate::ClientResponse;
|
|||||||
/// Test `ClientResponse` builder
|
/// Test `ClientResponse` builder
|
||||||
pub struct TestResponse {
|
pub struct TestResponse {
|
||||||
head: ResponseHead,
|
head: ResponseHead,
|
||||||
|
#[cfg(feature = "cookies")]
|
||||||
cookies: CookieJar,
|
cookies: CookieJar,
|
||||||
payload: Option<Payload>,
|
payload: Option<Payload>,
|
||||||
}
|
}
|
||||||
@ -20,6 +25,7 @@ impl Default for TestResponse {
|
|||||||
fn default() -> TestResponse {
|
fn default() -> TestResponse {
|
||||||
TestResponse {
|
TestResponse {
|
||||||
head: ResponseHead::new(StatusCode::OK),
|
head: ResponseHead::new(StatusCode::OK),
|
||||||
|
#[cfg(feature = "cookies")]
|
||||||
cookies: CookieJar::new(),
|
cookies: CookieJar::new(),
|
||||||
payload: None,
|
payload: None,
|
||||||
}
|
}
|
||||||
@ -69,6 +75,7 @@ impl TestResponse {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Set cookie for this response
|
/// Set cookie for this response
|
||||||
|
#[cfg(feature = "cookies")]
|
||||||
pub fn cookie(mut self, cookie: Cookie<'_>) -> Self {
|
pub fn cookie(mut self, cookie: Cookie<'_>) -> Self {
|
||||||
self.cookies.add(cookie.into_owned());
|
self.cookies.add(cookie.into_owned());
|
||||||
self
|
self
|
||||||
@ -84,8 +91,11 @@ impl TestResponse {
|
|||||||
|
|
||||||
/// Complete response creation and generate `ClientResponse` instance
|
/// Complete response creation and generate `ClientResponse` instance
|
||||||
pub fn finish(self) -> ClientResponse {
|
pub fn finish(self) -> ClientResponse {
|
||||||
|
// allow unused mut when cookies feature is disabled
|
||||||
|
#[allow(unused_mut)]
|
||||||
let mut head = self.head;
|
let mut head = self.head;
|
||||||
|
|
||||||
|
#[cfg(feature = "cookies")]
|
||||||
for cookie in self.cookies.delta() {
|
for cookie in self.cookies.delta() {
|
||||||
head.headers.insert(
|
head.headers.insert(
|
||||||
header::SET_COOKIE,
|
header::SET_COOKIE,
|
||||||
|
@ -32,6 +32,7 @@ use std::rc::Rc;
|
|||||||
use std::{fmt, str};
|
use std::{fmt, str};
|
||||||
|
|
||||||
use actix_codec::Framed;
|
use actix_codec::Framed;
|
||||||
|
#[cfg(feature = "cookies")]
|
||||||
use actix_http::cookie::{Cookie, CookieJar};
|
use actix_http::cookie::{Cookie, CookieJar};
|
||||||
use actix_http::{ws, Payload, RequestHead};
|
use actix_http::{ws, Payload, RequestHead};
|
||||||
use actix_rt::time::timeout;
|
use actix_rt::time::timeout;
|
||||||
@ -54,8 +55,10 @@ pub struct WebsocketsRequest {
|
|||||||
addr: Option<SocketAddr>,
|
addr: Option<SocketAddr>,
|
||||||
max_size: usize,
|
max_size: usize,
|
||||||
server_mode: bool,
|
server_mode: bool,
|
||||||
cookies: Option<CookieJar>,
|
|
||||||
config: Rc<ClientConfig>,
|
config: Rc<ClientConfig>,
|
||||||
|
|
||||||
|
#[cfg(feature = "cookies")]
|
||||||
|
cookies: Option<CookieJar>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WebsocketsRequest {
|
impl WebsocketsRequest {
|
||||||
@ -89,6 +92,7 @@ impl WebsocketsRequest {
|
|||||||
protocols: None,
|
protocols: None,
|
||||||
max_size: 65_536,
|
max_size: 65_536,
|
||||||
server_mode: false,
|
server_mode: false,
|
||||||
|
#[cfg(feature = "cookies")]
|
||||||
cookies: None,
|
cookies: None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -117,6 +121,7 @@ impl WebsocketsRequest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Set a cookie
|
/// Set a cookie
|
||||||
|
#[cfg(feature = "cookies")]
|
||||||
pub fn cookie(mut self, cookie: Cookie<'_>) -> Self {
|
pub fn cookie(mut self, cookie: Cookie<'_>) -> Self {
|
||||||
if self.cookies.is_none() {
|
if self.cookies.is_none() {
|
||||||
let mut jar = CookieJar::new();
|
let mut jar = CookieJar::new();
|
||||||
@ -270,6 +275,7 @@ impl WebsocketsRequest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// set cookies
|
// set cookies
|
||||||
|
#[cfg(feature = "cookies")]
|
||||||
if let Some(ref mut jar) = self.cookies {
|
if let Some(ref mut jar) = self.cookies {
|
||||||
let cookie: String = jar
|
let cookie: String = jar
|
||||||
.delta()
|
.delta()
|
||||||
|
@ -13,9 +13,11 @@ pub enum UrlGenerationError {
|
|||||||
/// Resource not found
|
/// Resource not found
|
||||||
#[display(fmt = "Resource not found")]
|
#[display(fmt = "Resource not found")]
|
||||||
ResourceNotFound,
|
ResourceNotFound,
|
||||||
|
|
||||||
/// Not all path pattern covered
|
/// Not all path pattern covered
|
||||||
#[display(fmt = "Not all path pattern covered")]
|
#[display(fmt = "Not all path pattern covered")]
|
||||||
NotEnoughElements,
|
NotEnoughElements,
|
||||||
|
|
||||||
/// URL parse error
|
/// URL parse error
|
||||||
#[display(fmt = "{}", _0)]
|
#[display(fmt = "{}", _0)]
|
||||||
ParseError(UrlParseError),
|
ParseError(UrlParseError),
|
||||||
|
@ -61,6 +61,7 @@
|
|||||||
//! ## Crate Features
|
//! ## Crate Features
|
||||||
//!
|
//!
|
||||||
//! * `compress` - content encoding compression support (enabled by default)
|
//! * `compress` - content encoding compression support (enabled by default)
|
||||||
|
//! * `cookies` - cookies support (enabled by default)
|
||||||
//! * `openssl` - HTTPS support via `openssl` crate, supports `HTTP/2`
|
//! * `openssl` - HTTPS support via `openssl` crate, supports `HTTP/2`
|
||||||
//! * `rustls` - HTTPS support via `rustls` crate, supports `HTTP/2`
|
//! * `rustls` - HTTPS support via `rustls` crate, supports `HTTP/2`
|
||||||
//! * `secure-cookies` - secure cookies support
|
//! * `secure-cookies` - secure cookies support
|
||||||
|
@ -806,15 +806,15 @@ async fn test_server_cookies() {
|
|||||||
}))
|
}))
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let req = srv.get("/");
|
||||||
|
let res = req.send().await.unwrap();
|
||||||
|
assert!(res.status().is_success());
|
||||||
|
|
||||||
let first_cookie = http::CookieBuilder::new("first", "first_value")
|
let first_cookie = http::CookieBuilder::new("first", "first_value")
|
||||||
.http_only(true)
|
.http_only(true)
|
||||||
.finish();
|
.finish();
|
||||||
let second_cookie = http::Cookie::new("second", "second_value");
|
let second_cookie = http::Cookie::new("second", "second_value");
|
||||||
|
|
||||||
let req = srv.get("/");
|
|
||||||
let res = req.send().await.unwrap();
|
|
||||||
assert!(res.status().is_success());
|
|
||||||
|
|
||||||
let cookies = res.cookies().expect("To have cookies");
|
let cookies = res.cookies().expect("To have cookies");
|
||||||
assert_eq!(cookies.len(), 2);
|
assert_eq!(cookies.len(), 2);
|
||||||
if cookies[0] == first_cookie {
|
if cookies[0] == first_cookie {
|
||||||
|
Loading…
Reference in New Issue
Block a user