mirror of
https://github.com/fafhrd91/actix-web
synced 2025-01-18 05:41:50 +01:00
fix client cookies parsing
This commit is contained in:
parent
ab597dd98a
commit
5703bd8160
@ -242,7 +242,7 @@ impl ClientRequest {
|
||||
self.header(header::CONTENT_LENGTH, wrt.get_mut().take().freeze())
|
||||
}
|
||||
|
||||
/// Set HTTP basic authorization
|
||||
/// Set HTTP basic authorization header
|
||||
pub fn basic_auth<U, P>(self, username: U, password: Option<P>) -> Self
|
||||
where
|
||||
U: fmt::Display,
|
||||
@ -258,7 +258,7 @@ impl ClientRequest {
|
||||
)
|
||||
}
|
||||
|
||||
/// Set HTTP bearer authentication
|
||||
/// Set HTTP bearer authentication header
|
||||
pub fn bearer_auth<T>(self, token: T) -> Self
|
||||
where
|
||||
T: fmt::Display,
|
||||
|
@ -5,10 +5,15 @@ use bytes::{Bytes, BytesMut};
|
||||
use futures::{Future, Poll, Stream};
|
||||
|
||||
use actix_http::error::PayloadError;
|
||||
use actix_http::http::header::CONTENT_LENGTH;
|
||||
use actix_http::http::header::{CONTENT_LENGTH, SET_COOKIE};
|
||||
use actix_http::http::{HeaderMap, StatusCode, Version};
|
||||
use actix_http::{Extensions, Head, HttpMessage, Payload, PayloadStream, ResponseHead};
|
||||
|
||||
#[cfg(feature = "cookies")]
|
||||
use actix_http::error::CookieParseError;
|
||||
#[cfg(feature = "cookies")]
|
||||
use cookie::Cookie;
|
||||
|
||||
/// Client Response
|
||||
pub struct ClientResponse<S = PayloadStream> {
|
||||
pub(crate) head: ResponseHead,
|
||||
@ -33,6 +38,26 @@ impl<S> HttpMessage for ClientResponse<S> {
|
||||
fn take_payload(&mut self) -> Payload<S> {
|
||||
std::mem::replace(&mut self.payload, Payload::None)
|
||||
}
|
||||
|
||||
/// Load request cookies.
|
||||
#[inline]
|
||||
#[cfg(feature = "cookies")]
|
||||
fn cookies(&self) -> Result<Ref<Vec<Cookie<'static>>>, CookieParseError> {
|
||||
struct Cookies(Vec<Cookie<'static>>);
|
||||
|
||||
if self.extensions().get::<Cookies>().is_none() {
|
||||
let mut cookies = Vec::new();
|
||||
for hdr in self.headers().get_all(SET_COOKIE) {
|
||||
let s = std::str::from_utf8(hdr.as_bytes())
|
||||
.map_err(CookieParseError::from)?;
|
||||
cookies.push(Cookie::parse_encoded(s)?.into_owned());
|
||||
}
|
||||
self.extensions_mut().insert(Cookies(cookies));
|
||||
}
|
||||
Ok(Ref::map(self.extensions(), |ext| {
|
||||
&ext.get::<Cookies>().unwrap().0
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
impl<S> ClientResponse<S> {
|
||||
|
@ -8,7 +8,7 @@ use rand::Rng;
|
||||
|
||||
use actix_http::HttpService;
|
||||
use actix_http_test::TestServer;
|
||||
use actix_web::{http::header, web, App, HttpMessage, HttpRequest, HttpResponse};
|
||||
use actix_web::{http::header, web, App, Error, HttpMessage, HttpRequest, HttpResponse};
|
||||
|
||||
const STR: &str = "Hello World Hello World Hello World Hello World Hello World \
|
||||
Hello World Hello World Hello World Hello World Hello World \
|
||||
@ -352,69 +352,69 @@ fn test_client_brotli_encoding() {
|
||||
// assert_eq!(bytes, Bytes::from_static(STR.as_ref()));
|
||||
// }
|
||||
|
||||
// #[test]
|
||||
// fn test_client_cookie_handling() {
|
||||
// use actix_web::http::Cookie;
|
||||
// fn err() -> Error {
|
||||
// use std::io::{Error as IoError, ErrorKind};
|
||||
// // stub some generic error
|
||||
// Error::from(IoError::from(ErrorKind::NotFound))
|
||||
// }
|
||||
// let cookie1 = Cookie::build("cookie1", "value1").finish();
|
||||
// let cookie2 = Cookie::build("cookie2", "value2")
|
||||
// .domain("www.example.org")
|
||||
// .path("/")
|
||||
// .secure(true)
|
||||
// .http_only(true)
|
||||
// .finish();
|
||||
// // Q: are all these clones really necessary? A: Yes, possibly
|
||||
// let cookie1b = cookie1.clone();
|
||||
// let cookie2b = cookie2.clone();
|
||||
// let mut srv = test::TestServer::new(move |app| {
|
||||
// let cookie1 = cookie1b.clone();
|
||||
// let cookie2 = cookie2b.clone();
|
||||
// app.handler(move |req: &HttpRequest| {
|
||||
// // Check cookies were sent correctly
|
||||
// req.cookie("cookie1")
|
||||
// .ok_or_else(err)
|
||||
// .and_then(|c1| {
|
||||
// if c1.value() == "value1" {
|
||||
// Ok(())
|
||||
// } else {
|
||||
// Err(err())
|
||||
// }
|
||||
// })
|
||||
// .and_then(|()| req.cookie("cookie2").ok_or_else(err))
|
||||
// .and_then(|c2| {
|
||||
// if c2.value() == "value2" {
|
||||
// Ok(())
|
||||
// } else {
|
||||
// Err(err())
|
||||
// }
|
||||
// })
|
||||
// // Send some cookies back
|
||||
// .map(|_| {
|
||||
// HttpResponse::Ok()
|
||||
// .cookie(cookie1.clone())
|
||||
// .cookie(cookie2.clone())
|
||||
// .finish()
|
||||
// })
|
||||
// })
|
||||
// });
|
||||
#[test]
|
||||
fn test_client_cookie_handling() {
|
||||
use actix_web::http::Cookie;
|
||||
fn err() -> Error {
|
||||
use std::io::{Error as IoError, ErrorKind};
|
||||
// stub some generic error
|
||||
Error::from(IoError::from(ErrorKind::NotFound))
|
||||
}
|
||||
let cookie1 = Cookie::build("cookie1", "value1").finish();
|
||||
let cookie2 = Cookie::build("cookie2", "value2")
|
||||
.domain("www.example.org")
|
||||
.path("/")
|
||||
.secure(true)
|
||||
.http_only(true)
|
||||
.finish();
|
||||
// Q: are all these clones really necessary? A: Yes, possibly
|
||||
let cookie1b = cookie1.clone();
|
||||
let cookie2b = cookie2.clone();
|
||||
|
||||
// let request = srv
|
||||
// .get()
|
||||
// .cookie(cookie1.clone())
|
||||
// .cookie(cookie2.clone())
|
||||
// .finish()
|
||||
// .unwrap();
|
||||
// let response = srv.execute(request.send()).unwrap();
|
||||
// assert!(response.status().is_success());
|
||||
// let c1 = response.cookie("cookie1").expect("Missing cookie1");
|
||||
// assert_eq!(c1, cookie1);
|
||||
// let c2 = response.cookie("cookie2").expect("Missing cookie2");
|
||||
// assert_eq!(c2, cookie2);
|
||||
// }
|
||||
let mut srv = TestServer::new(move || {
|
||||
let cookie1 = cookie1b.clone();
|
||||
let cookie2 = cookie2b.clone();
|
||||
|
||||
HttpService::new(App::new().route(
|
||||
"/",
|
||||
web::to(move |req: HttpRequest| {
|
||||
// Check cookies were sent correctly
|
||||
req.cookie("cookie1")
|
||||
.ok_or_else(err)
|
||||
.and_then(|c1| {
|
||||
if c1.value() == "value1" {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(err())
|
||||
}
|
||||
})
|
||||
.and_then(|()| req.cookie("cookie2").ok_or_else(err))
|
||||
.and_then(|c2| {
|
||||
if c2.value() == "value2" {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(err())
|
||||
}
|
||||
})
|
||||
// Send some cookies back
|
||||
.map(|_| {
|
||||
HttpResponse::Ok()
|
||||
.cookie(cookie1.clone())
|
||||
.cookie(cookie2.clone())
|
||||
.finish()
|
||||
})
|
||||
}),
|
||||
))
|
||||
});
|
||||
|
||||
let request = srv.get().cookie(cookie1.clone()).cookie(cookie2.clone());
|
||||
let response = srv.block_on(request.send()).unwrap();
|
||||
assert!(response.status().is_success());
|
||||
let c1 = response.cookie("cookie1").expect("Missing cookie1");
|
||||
assert_eq!(c1, cookie1);
|
||||
let c2 = response.cookie("cookie2").expect("Missing cookie2");
|
||||
assert_eq!(c2, cookie2);
|
||||
}
|
||||
|
||||
// #[test]
|
||||
// fn test_default_headers() {
|
||||
|
Loading…
x
Reference in New Issue
Block a user