mirror of
https://github.com/fafhrd91/actix-web
synced 2025-01-18 13:51:50 +01:00
add cookies support for response
This commit is contained in:
parent
5c9f813d28
commit
f0531793b4
@ -2,12 +2,13 @@
|
|||||||
use std::{io, mem, str};
|
use std::{io, mem, str};
|
||||||
use std::convert::Into;
|
use std::convert::Into;
|
||||||
|
|
||||||
use cookie;
|
use cookie::CookieJar;
|
||||||
use bytes::Bytes;
|
use bytes::Bytes;
|
||||||
use http::{Method, StatusCode, Version, Uri, HeaderMap, HttpTryFrom, Error};
|
use http::{Method, StatusCode, Version, Uri, HeaderMap, HttpTryFrom, Error};
|
||||||
use http::header::{self, HeaderName, HeaderValue};
|
use http::header::{self, HeaderName, HeaderValue};
|
||||||
|
|
||||||
use Params;
|
use Params;
|
||||||
|
use {Cookie, CookieParseError};
|
||||||
|
|
||||||
#[derive(Copy, Clone, PartialEq, Debug)]
|
#[derive(Copy, Clone, PartialEq, Debug)]
|
||||||
pub enum ConnectionType {
|
pub enum ConnectionType {
|
||||||
@ -24,7 +25,7 @@ pub struct HttpRequest {
|
|||||||
uri: Uri,
|
uri: Uri,
|
||||||
headers: HeaderMap,
|
headers: HeaderMap,
|
||||||
params: Params,
|
params: Params,
|
||||||
cookies: Vec<cookie::Cookie<'static>>,
|
cookies: Vec<Cookie<'static>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl HttpRequest {
|
impl HttpRequest {
|
||||||
@ -81,18 +82,18 @@ impl HttpRequest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Return request cookies.
|
/// Return request cookies.
|
||||||
pub fn cookies(&mut self) -> &Vec<cookie::Cookie<'static>> {
|
pub fn cookies(&mut self) -> &Vec<Cookie<'static>> {
|
||||||
&self.cookies
|
&self.cookies
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Load cookies
|
/// Load cookies
|
||||||
pub fn load_cookies(&mut self) -> Result<&Vec<cookie::Cookie>, cookie::ParseError>
|
pub fn load_cookies(&mut self) -> Result<&Vec<Cookie>, CookieParseError>
|
||||||
{
|
{
|
||||||
if let Some(val) = self.headers.get(header::COOKIE) {
|
if let Some(val) = self.headers.get(header::COOKIE) {
|
||||||
let s = str::from_utf8(val.as_bytes())
|
let s = str::from_utf8(val.as_bytes())
|
||||||
.map_err(cookie::ParseError::from)?;
|
.map_err(CookieParseError::from)?;
|
||||||
for cookie in s.split("; ") {
|
for cookie in s.split("; ") {
|
||||||
self.cookies.push(cookie::Cookie::parse_encoded(cookie)?.into_owned());
|
self.cookies.push(Cookie::parse_encoded(cookie)?.into_owned());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(&self.cookies)
|
Ok(&self.cookies)
|
||||||
@ -344,6 +345,7 @@ struct Parts {
|
|||||||
reason: Option<&'static str>,
|
reason: Option<&'static str>,
|
||||||
chunked: bool,
|
chunked: bool,
|
||||||
connection_type: Option<ConnectionType>,
|
connection_type: Option<ConnectionType>,
|
||||||
|
cookies: CookieJar,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parts {
|
impl Parts {
|
||||||
@ -355,6 +357,7 @@ impl Parts {
|
|||||||
reason: None,
|
reason: None,
|
||||||
chunked: false,
|
chunked: false,
|
||||||
connection_type: None,
|
connection_type: None,
|
||||||
|
cookies: CookieJar::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -470,12 +473,35 @@ impl Builder {
|
|||||||
self
|
self
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
|
/// Set a cookie
|
||||||
|
pub fn cookie<'c>(&mut self, cookie: Cookie<'c>) -> &mut Self {
|
||||||
|
if let Some(parts) = parts(&mut self.parts, &self.err) {
|
||||||
|
parts.cookies.add(cookie.into_owned());
|
||||||
|
}
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Remote cookie, cookie has to be cookie from `HttpRequest::cookies()` method.
|
||||||
|
pub fn del_cookie<'a>(&mut self, cookie: &Cookie<'a>) -> &mut Self {
|
||||||
|
if let Some(parts) = parts(&mut self.parts, &self.err) {
|
||||||
|
let cookie = cookie.clone().into_owned();
|
||||||
|
parts.cookies.add_original(cookie.clone());
|
||||||
|
parts.cookies.remove(cookie);
|
||||||
|
}
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
/// Set a body
|
/// Set a body
|
||||||
pub fn body<B: Into<Body>>(&mut self, body: B) -> Result<HttpResponse, Error> {
|
pub fn body<B: Into<Body>>(&mut self, body: B) -> Result<HttpResponse, Error> {
|
||||||
let parts = self.parts.take().expect("cannot reuse response builder");
|
let mut parts = self.parts.take().expect("cannot reuse response builder");
|
||||||
if let Some(e) = self.err.take() {
|
if let Some(e) = self.err.take() {
|
||||||
return Err(e)
|
return Err(e)
|
||||||
}
|
}
|
||||||
|
for cookie in parts.cookies.delta() {
|
||||||
|
parts.headers.append(
|
||||||
|
header::SET_COOKIE,
|
||||||
|
HeaderValue::from_str(&cookie.to_string())?);
|
||||||
|
}
|
||||||
Ok(HttpResponse {
|
Ok(HttpResponse {
|
||||||
version: parts.version,
|
version: parts.version,
|
||||||
headers: parts.headers,
|
headers: parts.headers,
|
||||||
|
@ -49,4 +49,8 @@ pub use resource::{Reply, Resource};
|
|||||||
pub use route::{Route, RouteFactory, RouteHandler};
|
pub use route::{Route, RouteFactory, RouteHandler};
|
||||||
pub use server::HttpServer;
|
pub use server::HttpServer;
|
||||||
pub use context::HttpContext;
|
pub use context::HttpContext;
|
||||||
|
|
||||||
|
// re-exports
|
||||||
|
pub use cookie::{Cookie, CookieBuilder};
|
||||||
|
pub use cookie::{ParseError as CookieParseError};
|
||||||
pub use route_recognizer::Params;
|
pub use route_recognizer::Params;
|
||||||
|
@ -1,7 +1,9 @@
|
|||||||
extern crate actix_web;
|
extern crate actix_web;
|
||||||
extern crate http;
|
extern crate http;
|
||||||
|
extern crate time;
|
||||||
|
|
||||||
use actix_web::*;
|
use actix_web::*;
|
||||||
|
use time::Duration;
|
||||||
use http::{header, Method, Uri, Version, HeaderMap, HttpTryFrom};
|
use http::{header, Method, Uri, Version, HeaderMap, HttpTryFrom};
|
||||||
|
|
||||||
|
|
||||||
@ -30,3 +32,35 @@ fn test_request_cookies() {
|
|||||||
assert_eq!(cookies[1].name(), "cookie2");
|
assert_eq!(cookies[1].name(), "cookie2");
|
||||||
assert_eq!(cookies[1].value(), "value2");
|
assert_eq!(cookies[1].value(), "value2");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_response_cookies() {
|
||||||
|
let mut headers = HeaderMap::new();
|
||||||
|
headers.insert(header::COOKIE,
|
||||||
|
header::HeaderValue::from_static("cookie1=value1; cookie2=value2"));
|
||||||
|
|
||||||
|
let mut req = HttpRequest::new(
|
||||||
|
Method::GET, Uri::try_from("/").unwrap(), Version::HTTP_11, headers);
|
||||||
|
let cookies = req.load_cookies().unwrap();
|
||||||
|
|
||||||
|
let resp = httpcodes::HTTPOk
|
||||||
|
.builder()
|
||||||
|
.cookie(Cookie::build("name", "value")
|
||||||
|
.domain("www.rust-lang.org")
|
||||||
|
.path("/test")
|
||||||
|
.http_only(true)
|
||||||
|
.max_age(Duration::days(1))
|
||||||
|
.finish())
|
||||||
|
.del_cookie(&cookies[0])
|
||||||
|
.body(Body::Empty);
|
||||||
|
|
||||||
|
assert!(resp.is_ok());
|
||||||
|
let resp = resp.unwrap();
|
||||||
|
|
||||||
|
let mut val: Vec<_> = resp.headers().get_all("Set-Cookie")
|
||||||
|
.iter().map(|v| v.to_str().unwrap().to_owned()).collect();
|
||||||
|
val.sort();
|
||||||
|
assert!(val[0].starts_with("cookie1=; Max-Age=0;"));
|
||||||
|
assert_eq!(
|
||||||
|
val[1],"name=value; HttpOnly; Path=/test; Domain=www.rust-lang.org; Max-Age=86400");
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user