mirror of
https://github.com/fafhrd91/actix-web
synced 2025-01-18 05:41:50 +01:00
cookie is optional
This commit is contained in:
parent
00b7dc7887
commit
c5c7b244be
@ -31,8 +31,8 @@ before_cache: |
|
||||
|
||||
script:
|
||||
- cargo clean
|
||||
- cargo build --features="ssl"
|
||||
- cargo test --features="ssl"
|
||||
- cargo build --all-features
|
||||
- cargo test --all-features
|
||||
|
||||
# Upload docs
|
||||
after_success:
|
||||
|
24
Cargo.toml
24
Cargo.toml
@ -7,20 +7,20 @@ readme = "README.md"
|
||||
keywords = ["http", "web", "framework", "async", "futures"]
|
||||
homepage = "https://actix.rs"
|
||||
repository = "https://github.com/actix/actix-http.git"
|
||||
documentation = "https://actix.rs/api/actix-http/stable/actix_http/"
|
||||
documentation = "https://docs.rs/actix-http/"
|
||||
categories = ["network-programming", "asynchronous",
|
||||
"web-programming::http-server",
|
||||
"web-programming::websocket"]
|
||||
license = "Apache-2.0"
|
||||
license = "MIT/Apache-2.0"
|
||||
exclude = [".gitignore", ".travis.yml", ".cargo/config", "appveyor.yml"]
|
||||
edition = "2018"
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
features = ["session"]
|
||||
features = ["ssl", "fail", "cookie"]
|
||||
|
||||
[badges]
|
||||
travis-ci = { repository = "actix/actix-http", branch = "master" }
|
||||
appveyor = { repository = "fafhrd91/actix-http-b1qsn" }
|
||||
# appveyor = { repository = "fafhrd91/actix-http-b1qsn" }
|
||||
codecov = { repository = "actix/actix-http", branch = "master", service = "github" }
|
||||
|
||||
[lib]
|
||||
@ -28,13 +28,15 @@ name = "actix_http"
|
||||
path = "src/lib.rs"
|
||||
|
||||
[features]
|
||||
default = ["fail"]
|
||||
default = []
|
||||
|
||||
# openssl
|
||||
ssl = ["openssl", "actix-connect/ssl"]
|
||||
|
||||
# failure integration. it is on by default, it will be off in future versions
|
||||
# actix itself does not use failure anymore
|
||||
# cookies integration
|
||||
cookies = ["cookie"]
|
||||
|
||||
# failure integration. actix does not use failure anymore
|
||||
fail = ["failure"]
|
||||
|
||||
[dependencies]
|
||||
@ -49,7 +51,6 @@ backtrace = "0.3"
|
||||
bitflags = "1.0"
|
||||
bytes = "0.4"
|
||||
byteorder = "1.2"
|
||||
cookie = { version="0.11", features=["percent-encode"] }
|
||||
derive_more = "0.14"
|
||||
encoding = "0.2"
|
||||
futures = "0.1"
|
||||
@ -76,11 +77,10 @@ tokio-timer = "0.2"
|
||||
tokio-current-thread = "0.1"
|
||||
trust-dns-resolver = { version="0.11.0-alpha.2", default-features = false }
|
||||
|
||||
# openssl
|
||||
openssl = { version="0.10", optional = true }
|
||||
|
||||
# failure is optional
|
||||
# optional deps
|
||||
cookie = { version="0.11", features=["percent-encode"], optional = true }
|
||||
failure = { version = "0.1.5", optional = true }
|
||||
openssl = { version="0.10", optional = true }
|
||||
|
||||
[dev-dependencies]
|
||||
actix-rt = "0.2.0"
|
||||
|
@ -1,13 +1,12 @@
|
||||
use std::fmt;
|
||||
use std::fmt::Write as FmtWrite;
|
||||
use std::io::Write;
|
||||
|
||||
use actix_service::Service;
|
||||
use bytes::{BufMut, Bytes, BytesMut};
|
||||
#[cfg(feature = "cookies")]
|
||||
use cookie::{Cookie, CookieJar};
|
||||
use futures::future::{err, Either};
|
||||
use futures::{Future, Stream};
|
||||
use percent_encoding::{percent_encode, USERINFO_ENCODE_SET};
|
||||
use serde::Serialize;
|
||||
use serde_json;
|
||||
|
||||
@ -58,6 +57,7 @@ impl ClientRequest<()> {
|
||||
ClientRequestBuilder {
|
||||
head: Some(RequestHead::default()),
|
||||
err: None,
|
||||
#[cfg(feature = "cookies")]
|
||||
cookies: None,
|
||||
default_headers: true,
|
||||
}
|
||||
@ -235,6 +235,7 @@ where
|
||||
pub struct ClientRequestBuilder {
|
||||
head: Option<RequestHead>,
|
||||
err: Option<HttpError>,
|
||||
#[cfg(feature = "cookies")]
|
||||
cookies: Option<CookieJar>,
|
||||
default_headers: bool,
|
||||
}
|
||||
@ -441,6 +442,7 @@ impl ClientRequestBuilder {
|
||||
self.header(header::CONTENT_LENGTH, wrt.get_mut().take().freeze())
|
||||
}
|
||||
|
||||
#[cfg(feature = "cookies")]
|
||||
/// Set a cookie
|
||||
///
|
||||
/// ```rust
|
||||
@ -560,20 +562,28 @@ impl ClientRequestBuilder {
|
||||
);
|
||||
}
|
||||
|
||||
#[allow(unused_mut)]
|
||||
let mut head = self.head.take().expect("cannot reuse request builder");
|
||||
|
||||
// set cookies
|
||||
if let Some(ref mut jar) = self.cookies {
|
||||
let mut cookie = String::new();
|
||||
for c in jar.delta() {
|
||||
let name = percent_encode(c.name().as_bytes(), USERINFO_ENCODE_SET);
|
||||
let value = percent_encode(c.value().as_bytes(), USERINFO_ENCODE_SET);
|
||||
let _ = write!(&mut cookie, "; {}={}", name, value);
|
||||
#[cfg(feature = "cookies")]
|
||||
{
|
||||
use percent_encoding::{percent_encode, USERINFO_ENCODE_SET};
|
||||
use std::fmt::Write;
|
||||
|
||||
// set cookies
|
||||
if let Some(ref mut jar) = self.cookies {
|
||||
let mut cookie = String::new();
|
||||
for c in jar.delta() {
|
||||
let name = percent_encode(c.name().as_bytes(), USERINFO_ENCODE_SET);
|
||||
let value =
|
||||
percent_encode(c.value().as_bytes(), USERINFO_ENCODE_SET);
|
||||
let _ = write!(&mut cookie, "; {}={}", name, value);
|
||||
}
|
||||
head.headers.insert(
|
||||
header::COOKIE,
|
||||
HeaderValue::from_str(&cookie.as_str()[2..]).unwrap(),
|
||||
);
|
||||
}
|
||||
head.headers.insert(
|
||||
header::COOKIE,
|
||||
HeaderValue::from_str(&cookie.as_str()[2..]).unwrap(),
|
||||
);
|
||||
}
|
||||
Ok(ClientRequest { head, body })
|
||||
}
|
||||
@ -646,6 +656,7 @@ impl ClientRequestBuilder {
|
||||
ClientRequestBuilder {
|
||||
head: self.head.take(),
|
||||
err: self.err.take(),
|
||||
#[cfg(feature = "cookies")]
|
||||
cookies: self.cookies.take(),
|
||||
default_headers: self.default_headers,
|
||||
}
|
||||
|
17
src/error.rs
17
src/error.rs
@ -8,6 +8,7 @@ use std::{fmt, io, result};
|
||||
// use actix::MailboxError;
|
||||
use actix_utils::timeout::TimeoutError;
|
||||
use backtrace::Backtrace;
|
||||
#[cfg(feature = "cookies")]
|
||||
use cookie;
|
||||
use derive_more::{Display, From};
|
||||
use futures::Canceled;
|
||||
@ -19,7 +20,8 @@ use serde_json::error::Error as JsonError;
|
||||
use serde_urlencoded::ser::Error as FormError;
|
||||
use tokio_timer::Error as TimerError;
|
||||
|
||||
// re-exports
|
||||
// re-export for convinience
|
||||
#[cfg(feature = "cookies")]
|
||||
pub use cookie::ParseError as CookieParseError;
|
||||
|
||||
use crate::body::Body;
|
||||
@ -322,6 +324,7 @@ impl ResponseError for PayloadError {
|
||||
}
|
||||
|
||||
/// Return `BadRequest` for `cookie::ParseError`
|
||||
#[cfg(feature = "cookies")]
|
||||
impl ResponseError for cookie::ParseError {
|
||||
fn error_response(&self) -> Response {
|
||||
Response::new(StatusCode::BAD_REQUEST)
|
||||
@ -889,7 +892,6 @@ mod failure_integration {
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use cookie::ParseError as CookieParseError;
|
||||
use http::{Error as HttpError, StatusCode};
|
||||
use httparse;
|
||||
use std::error::Error as StdError;
|
||||
@ -900,14 +902,19 @@ mod tests {
|
||||
let resp: Response = ParseError::Incomplete.error_response();
|
||||
assert_eq!(resp.status(), StatusCode::BAD_REQUEST);
|
||||
|
||||
let resp: Response = CookieParseError::EmptyName.error_response();
|
||||
assert_eq!(resp.status(), StatusCode::BAD_REQUEST);
|
||||
|
||||
let err: HttpError = StatusCode::from_u16(10000).err().unwrap().into();
|
||||
let resp: Response = err.error_response();
|
||||
assert_eq!(resp.status(), StatusCode::INTERNAL_SERVER_ERROR);
|
||||
}
|
||||
|
||||
#[cfg(feature = "cookies")]
|
||||
#[test]
|
||||
fn test_cookie_parse() {
|
||||
use cookie::ParseError as CookieParseError;
|
||||
let resp: Response = CookieParseError::EmptyName.error_response();
|
||||
assert_eq!(resp.status(), StatusCode::BAD_REQUEST);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_as_response() {
|
||||
let orig = io::Error::new(io::ErrorKind::Other, "other");
|
||||
|
@ -613,13 +613,12 @@ mod tests {
|
||||
let mut sys = actix_rt::System::new("test");
|
||||
let _ = sys.block_on(lazy(|| {
|
||||
let buf = Buffer::new("GET /test HTTP/1\r\n\r\n");
|
||||
let readbuf = BytesMut::new();
|
||||
|
||||
let mut h1 = Dispatcher::new(
|
||||
buf,
|
||||
ServiceConfig::default(),
|
||||
CloneableService::new(
|
||||
(|req| ok::<_, Error>(Response::Ok().finish())).into_service(),
|
||||
(|_| ok::<_, Error>(Response::Ok().finish())).into_service(),
|
||||
),
|
||||
);
|
||||
assert!(h1.poll().is_ok());
|
||||
|
@ -1,18 +1,23 @@
|
||||
use std::cell::{Ref, RefMut};
|
||||
use std::str;
|
||||
|
||||
use cookie::Cookie;
|
||||
use encoding::all::UTF_8;
|
||||
use encoding::label::encoding_from_whatwg_label;
|
||||
use encoding::EncodingRef;
|
||||
use http::{header, HeaderMap};
|
||||
use mime::Mime;
|
||||
|
||||
use crate::error::{ContentTypeError, CookieParseError, ParseError};
|
||||
use crate::error::{ContentTypeError, ParseError};
|
||||
use crate::extensions::Extensions;
|
||||
use crate::header::Header;
|
||||
use crate::payload::Payload;
|
||||
|
||||
#[cfg(feature = "cookies")]
|
||||
use crate::error::CookieParseError;
|
||||
#[cfg(feature = "cookies")]
|
||||
use cookie::Cookie;
|
||||
|
||||
#[cfg(feature = "cookies")]
|
||||
struct Cookies(Vec<Cookie<'static>>);
|
||||
|
||||
/// Trait that implements general purpose operations on http messages
|
||||
@ -105,6 +110,7 @@ pub trait HttpMessage: Sized {
|
||||
|
||||
/// Load request cookies.
|
||||
#[inline]
|
||||
#[cfg(feature = "cookies")]
|
||||
fn cookies(&self) -> Result<Ref<Vec<Cookie<'static>>>, CookieParseError> {
|
||||
if self.extensions().get::<Cookies>().is_none() {
|
||||
let mut cookies = Vec::new();
|
||||
@ -125,6 +131,7 @@ pub trait HttpMessage: Sized {
|
||||
}
|
||||
|
||||
/// Return request cookie.
|
||||
#[cfg(feature = "cookies")]
|
||||
fn cookie(&self, name: &str) -> Option<Cookie<'static>> {
|
||||
if let Ok(cookies) = self.cookies() {
|
||||
for cookie in cookies.iter() {
|
||||
|
@ -113,6 +113,7 @@ pub mod http {
|
||||
#[doc(hidden)]
|
||||
pub use http::uri::PathAndQuery;
|
||||
|
||||
#[cfg(feature = "cookies")]
|
||||
pub use cookie::{Cookie, CookieBuilder};
|
||||
|
||||
/// Various http headers
|
||||
|
@ -3,6 +3,7 @@ use std::io::Write;
|
||||
use std::{fmt, str};
|
||||
|
||||
use bytes::{BufMut, Bytes, BytesMut};
|
||||
#[cfg(feature = "cookies")]
|
||||
use cookie::{Cookie, CookieJar};
|
||||
use futures::future::{ok, FutureResult, IntoFuture};
|
||||
use futures::Stream;
|
||||
@ -128,6 +129,7 @@ impl<B> Response<B> {
|
||||
|
||||
/// Get an iterator for the cookies set by this response
|
||||
#[inline]
|
||||
#[cfg(feature = "cookies")]
|
||||
pub fn cookies(&self) -> CookieIter {
|
||||
CookieIter {
|
||||
iter: self.head.headers.get_all(header::SET_COOKIE).iter(),
|
||||
@ -136,6 +138,7 @@ impl<B> Response<B> {
|
||||
|
||||
/// Add a cookie to this response
|
||||
#[inline]
|
||||
#[cfg(feature = "cookies")]
|
||||
pub fn add_cookie(&mut self, cookie: &Cookie) -> Result<(), HttpError> {
|
||||
let h = &mut self.head.headers;
|
||||
HeaderValue::from_str(&cookie.to_string())
|
||||
@ -148,6 +151,7 @@ impl<B> Response<B> {
|
||||
/// Remove all cookies with the given name from this response. Returns
|
||||
/// the number of cookies removed.
|
||||
#[inline]
|
||||
#[cfg(feature = "cookies")]
|
||||
pub fn del_cookie(&mut self, name: &str) -> usize {
|
||||
let h = &mut self.head.headers;
|
||||
let vals: Vec<HeaderValue> = h
|
||||
@ -267,10 +271,12 @@ impl IntoFuture for Response {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "cookies")]
|
||||
pub struct CookieIter<'a> {
|
||||
iter: header::ValueIter<'a, HeaderValue>,
|
||||
}
|
||||
|
||||
#[cfg(feature = "cookies")]
|
||||
impl<'a> Iterator for CookieIter<'a> {
|
||||
type Item = Cookie<'a>;
|
||||
|
||||
@ -292,6 +298,7 @@ impl<'a> Iterator for CookieIter<'a> {
|
||||
pub struct ResponseBuilder {
|
||||
head: Option<Message<ResponseHead>>,
|
||||
err: Option<HttpError>,
|
||||
#[cfg(feature = "cookies")]
|
||||
cookies: Option<CookieJar>,
|
||||
}
|
||||
|
||||
@ -304,6 +311,7 @@ impl ResponseBuilder {
|
||||
ResponseBuilder {
|
||||
head: Some(head),
|
||||
err: None,
|
||||
#[cfg(feature = "cookies")]
|
||||
cookies: None,
|
||||
}
|
||||
}
|
||||
@ -503,6 +511,7 @@ impl ResponseBuilder {
|
||||
/// .finish()
|
||||
/// }
|
||||
/// ```
|
||||
#[cfg(feature = "cookies")]
|
||||
pub fn cookie<'c>(&mut self, cookie: Cookie<'c>) -> &mut Self {
|
||||
if self.cookies.is_none() {
|
||||
let mut jar = CookieJar::new();
|
||||
@ -530,6 +539,7 @@ impl ResponseBuilder {
|
||||
/// builder.finish()
|
||||
/// }
|
||||
/// ```
|
||||
#[cfg(feature = "cookies")]
|
||||
pub fn del_cookie<'a>(&mut self, cookie: &Cookie<'a>) -> &mut Self {
|
||||
{
|
||||
if self.cookies.is_none() {
|
||||
@ -582,15 +592,20 @@ impl ResponseBuilder {
|
||||
return Response::from(Error::from(e)).into_body();
|
||||
}
|
||||
|
||||
#[allow(unused_mut)]
|
||||
let mut response = self.head.take().expect("cannot reuse response builder");
|
||||
if let Some(ref jar) = self.cookies {
|
||||
for cookie in jar.delta() {
|
||||
match HeaderValue::from_str(&cookie.to_string()) {
|
||||
Ok(val) => {
|
||||
let _ = response.headers.append(header::SET_COOKIE, val);
|
||||
}
|
||||
Err(e) => return Response::from(Error::from(e)).into_body(),
|
||||
};
|
||||
|
||||
#[cfg(feature = "cookies")]
|
||||
{
|
||||
if let Some(ref jar) = self.cookies {
|
||||
for cookie in jar.delta() {
|
||||
match HeaderValue::from_str(&cookie.to_string()) {
|
||||
Ok(val) => {
|
||||
let _ = response.headers.append(header::SET_COOKIE, val);
|
||||
}
|
||||
Err(e) => return Response::from(Error::from(e)).into_body(),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -654,6 +669,7 @@ impl ResponseBuilder {
|
||||
ResponseBuilder {
|
||||
head: self.head.take(),
|
||||
err: self.err.take(),
|
||||
#[cfg(feature = "cookies")]
|
||||
cookies: self.cookies.take(),
|
||||
}
|
||||
}
|
||||
@ -674,7 +690,9 @@ fn parts<'a>(
|
||||
impl<B> From<Response<B>> for 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;
|
||||
#[cfg(feature = "cookies")]
|
||||
for c in res.cookies() {
|
||||
if let Some(ref mut j) = jar {
|
||||
j.add_original(c.into_owned());
|
||||
@ -688,6 +706,7 @@ impl<B> From<Response<B>> for ResponseBuilder {
|
||||
ResponseBuilder {
|
||||
head: Some(res.head),
|
||||
err: None,
|
||||
#[cfg(feature = "cookies")]
|
||||
cookies: jar,
|
||||
}
|
||||
}
|
||||
@ -697,17 +716,22 @@ impl<B> From<Response<B>> for ResponseBuilder {
|
||||
impl<'a> From<&'a ResponseHead> for ResponseBuilder {
|
||||
fn from(head: &'a ResponseHead) -> ResponseBuilder {
|
||||
// If this response has cookies, load them into a jar
|
||||
#[cfg(feature = "cookies")]
|
||||
let mut jar: Option<CookieJar> = None;
|
||||
let cookies = CookieIter {
|
||||
iter: head.headers.get_all(header::SET_COOKIE).iter(),
|
||||
};
|
||||
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);
|
||||
|
||||
#[cfg(feature = "cookies")]
|
||||
{
|
||||
let cookies = CookieIter {
|
||||
iter: head.headers.get_all(header::SET_COOKIE).iter(),
|
||||
};
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -721,6 +745,7 @@ impl<'a> From<&'a ResponseHead> for ResponseBuilder {
|
||||
ResponseBuilder {
|
||||
head: Some(msg),
|
||||
err: None,
|
||||
#[cfg(feature = "cookies")]
|
||||
cookies: jar,
|
||||
}
|
||||
}
|
||||
@ -802,14 +827,9 @@ impl From<BytesMut> for Response {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use time::Duration;
|
||||
|
||||
use super::*;
|
||||
use crate::body::Body;
|
||||
use crate::http;
|
||||
use crate::http::header::{HeaderValue, CONTENT_TYPE, COOKIE};
|
||||
use crate::httpmessage::HttpMessage;
|
||||
use crate::test::TestRequest;
|
||||
|
||||
#[test]
|
||||
fn test_debug() {
|
||||
@ -822,8 +842,11 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "cookies")]
|
||||
fn test_response_cookies() {
|
||||
let req = TestRequest::default()
|
||||
use crate::httpmessage::HttpMessage;
|
||||
|
||||
let req = crate::test::TestRequest::default()
|
||||
.header(COOKIE, "cookie1=value1")
|
||||
.header(COOKIE, "cookie2=value2")
|
||||
.finish();
|
||||
@ -831,11 +854,11 @@ mod tests {
|
||||
|
||||
let resp = Response::Ok()
|
||||
.cookie(
|
||||
http::Cookie::build("name", "value")
|
||||
crate::http::Cookie::build("name", "value")
|
||||
.domain("www.rust-lang.org")
|
||||
.path("/test")
|
||||
.http_only(true)
|
||||
.max_age(Duration::days(1))
|
||||
.max_age(time::Duration::days(1))
|
||||
.finish(),
|
||||
)
|
||||
.del_cookie(&cookies[0])
|
||||
@ -856,16 +879,17 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "cookies")]
|
||||
fn test_update_response_cookies() {
|
||||
let mut r = Response::Ok()
|
||||
.cookie(http::Cookie::new("original", "val100"))
|
||||
.cookie(crate::http::Cookie::new("original", "val100"))
|
||||
.finish();
|
||||
|
||||
r.add_cookie(&http::Cookie::new("cookie2", "val200"))
|
||||
r.add_cookie(&crate::http::Cookie::new("cookie2", "val200"))
|
||||
.unwrap();
|
||||
r.add_cookie(&http::Cookie::new("cookie2", "val250"))
|
||||
r.add_cookie(&crate::http::Cookie::new("cookie2", "val250"))
|
||||
.unwrap();
|
||||
r.add_cookie(&http::Cookie::new("cookie3", "val300"))
|
||||
r.add_cookie(&crate::http::Cookie::new("cookie3", "val300"))
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(r.cookies().count(), 4);
|
||||
@ -1016,11 +1040,14 @@ mod tests {
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "cookies")]
|
||||
fn test_into_builder() {
|
||||
use crate::httpmessage::HttpMessage;
|
||||
|
||||
let mut resp: Response = "test".into();
|
||||
assert_eq!(resp.status(), StatusCode::OK);
|
||||
|
||||
resp.add_cookie(&http::Cookie::new("cookie1", "val100"))
|
||||
resp.add_cookie(&crate::http::Cookie::new("cookie1", "val100"))
|
||||
.unwrap();
|
||||
|
||||
let mut builder: ResponseBuilder = resp.into();
|
||||
|
57
src/test.rs
57
src/test.rs
@ -1,12 +1,11 @@
|
||||
//! Test Various helpers for Actix applications to use during testing.
|
||||
use std::fmt::Write as FmtWrite;
|
||||
use std::str::FromStr;
|
||||
|
||||
use bytes::Bytes;
|
||||
#[cfg(feature = "cookies")]
|
||||
use cookie::{Cookie, CookieJar};
|
||||
use http::header::{self, HeaderName, HeaderValue};
|
||||
use http::header::HeaderName;
|
||||
use http::{HeaderMap, HttpTryFrom, Method, Uri, Version};
|
||||
use percent_encoding::{percent_encode, USERINFO_ENCODE_SET};
|
||||
|
||||
use crate::header::{Header, IntoHeaderValue};
|
||||
use crate::payload::Payload;
|
||||
@ -46,6 +45,7 @@ struct Inner {
|
||||
method: Method,
|
||||
uri: Uri,
|
||||
headers: HeaderMap,
|
||||
#[cfg(feature = "cookies")]
|
||||
cookies: CookieJar,
|
||||
payload: Option<Payload>,
|
||||
}
|
||||
@ -57,6 +57,7 @@ impl Default for TestRequest {
|
||||
uri: Uri::from_str("/").unwrap(),
|
||||
version: Version::HTTP_11,
|
||||
headers: HeaderMap::new(),
|
||||
#[cfg(feature = "cookies")]
|
||||
cookies: CookieJar::new(),
|
||||
payload: None,
|
||||
}))
|
||||
@ -126,6 +127,7 @@ impl TestRequest {
|
||||
}
|
||||
|
||||
/// Set cookie for this request
|
||||
#[cfg(feature = "cookies")]
|
||||
pub fn cookie<'a>(&mut self, cookie: Cookie<'a>) -> &mut Self {
|
||||
parts(&mut self.0).cookies.add(cookie.into_owned());
|
||||
self
|
||||
@ -145,38 +147,39 @@ impl TestRequest {
|
||||
|
||||
/// Complete request creation and generate `Request` instance
|
||||
pub fn finish(&mut self) -> Request {
|
||||
let Inner {
|
||||
method,
|
||||
uri,
|
||||
version,
|
||||
headers,
|
||||
payload,
|
||||
cookies,
|
||||
} = self.0.take().expect("cannot reuse test request builder");;
|
||||
let inner = self.0.take().expect("cannot reuse test request builder");;
|
||||
|
||||
let mut req = if let Some(pl) = payload {
|
||||
let mut req = if let Some(pl) = inner.payload {
|
||||
Request::with_payload(pl)
|
||||
} else {
|
||||
Request::with_payload(crate::h1::Payload::empty().into())
|
||||
};
|
||||
|
||||
let head = req.head_mut();
|
||||
head.uri = uri;
|
||||
head.method = method;
|
||||
head.version = version;
|
||||
head.headers = headers;
|
||||
head.uri = inner.uri;
|
||||
head.method = inner.method;
|
||||
head.version = inner.version;
|
||||
head.headers = inner.headers;
|
||||
|
||||
let mut cookie = String::new();
|
||||
for c in cookies.delta() {
|
||||
let name = percent_encode(c.name().as_bytes(), USERINFO_ENCODE_SET);
|
||||
let value = percent_encode(c.value().as_bytes(), USERINFO_ENCODE_SET);
|
||||
let _ = write!(&mut cookie, "; {}={}", name, value);
|
||||
}
|
||||
if !cookie.is_empty() {
|
||||
head.headers.insert(
|
||||
header::COOKIE,
|
||||
HeaderValue::from_str(&cookie.as_str()[2..]).unwrap(),
|
||||
);
|
||||
#[cfg(feature = "cookies")]
|
||||
{
|
||||
use std::fmt::Write as FmtWrite;
|
||||
|
||||
use http::header::{self, HeaderValue};
|
||||
use percent_encoding::{percent_encode, USERINFO_ENCODE_SET};
|
||||
|
||||
let mut cookie = String::new();
|
||||
for c in inner.cookies.delta() {
|
||||
let name = percent_encode(c.name().as_bytes(), USERINFO_ENCODE_SET);
|
||||
let value = percent_encode(c.value().as_bytes(), USERINFO_ENCODE_SET);
|
||||
let _ = write!(&mut cookie, "; {}={}", name, value);
|
||||
}
|
||||
if !cookie.is_empty() {
|
||||
head.headers.insert(
|
||||
header::COOKIE,
|
||||
HeaderValue::from_str(&cookie.as_str()[2..]).unwrap(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
req
|
||||
|
@ -1,6 +1,7 @@
|
||||
//! Http client request
|
||||
use std::str;
|
||||
|
||||
#[cfg(feature = "cookies")]
|
||||
use cookie::Cookie;
|
||||
use http::header::{HeaderName, HeaderValue};
|
||||
use http::{Error as HttpError, HttpTryFrom};
|
||||
@ -50,6 +51,7 @@ impl Connect {
|
||||
self
|
||||
}
|
||||
|
||||
#[cfg(feature = "cookies")]
|
||||
/// Set cookie for handshake request
|
||||
pub fn cookie(mut self, cookie: Cookie) -> Self {
|
||||
self.request.cookie(cookie);
|
||||
|
Loading…
x
Reference in New Issue
Block a user