mirror of
https://github.com/fafhrd91/actix-web
synced 2024-11-27 17:52:56 +01:00
add HttpResponse::add_removal_cookie
(#2586)
This commit is contained in:
parent
ad159f5219
commit
5ee555462f
@ -1,10 +1,14 @@
|
|||||||
# Changes
|
# Changes
|
||||||
|
|
||||||
## Unreleased - 2021-xx-xx
|
## Unreleased - 2021-xx-xx
|
||||||
|
### Added
|
||||||
|
- `HttpResponse::add_removal_cookie` [#2586]
|
||||||
|
|
||||||
### Removed
|
### Removed
|
||||||
- `HttpRequest::req_data[_mut]()`; request-local data is still available through `.extensions()`. [#2585]
|
- `HttpRequest::req_data[_mut]()`; request-local data is still available through `.extensions()`. [#2585]
|
||||||
|
|
||||||
[#2585]: https://github.com/actix/actix-web/pull/2585
|
[#2585]: https://github.com/actix/actix-web/pull/2585
|
||||||
|
[#2586]: https://github.com/actix/actix-web/pull/2586
|
||||||
|
|
||||||
|
|
||||||
## 4.0.0-beta.20 - 2022-01-14
|
## 4.0.0-beta.20 - 2022-01-14
|
||||||
|
@ -27,7 +27,7 @@ use crate::{error::Error, HttpRequest, HttpResponseBuilder, Responder};
|
|||||||
/// An outgoing response.
|
/// An outgoing response.
|
||||||
pub struct HttpResponse<B = BoxBody> {
|
pub struct HttpResponse<B = BoxBody> {
|
||||||
res: Response<B>,
|
res: Response<B>,
|
||||||
pub(crate) error: Option<Error>,
|
error: Option<Error>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl HttpResponse<BoxBody> {
|
impl HttpResponse<BoxBody> {
|
||||||
@ -116,18 +116,54 @@ impl<B> HttpResponse<B> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Add a cookie to this response
|
/// Add a cookie to this response.
|
||||||
|
///
|
||||||
|
/// # Errors
|
||||||
|
/// Returns an error if the cookie results in a malformed `Set-Cookie` header.
|
||||||
#[cfg(feature = "cookies")]
|
#[cfg(feature = "cookies")]
|
||||||
pub fn add_cookie(&mut self, cookie: &Cookie<'_>) -> Result<(), HttpError> {
|
pub fn add_cookie(&mut self, cookie: &Cookie<'_>) -> Result<(), HttpError> {
|
||||||
HeaderValue::from_str(&cookie.to_string())
|
HeaderValue::from_str(&cookie.to_string())
|
||||||
.map(|c| {
|
.map(|cookie| self.headers_mut().append(header::SET_COOKIE, cookie))
|
||||||
self.headers_mut().append(header::SET_COOKIE, c);
|
.map_err(Into::into)
|
||||||
})
|
|
||||||
.map_err(|e| e.into())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Remove all cookies with the given name from this response. Returns
|
/// Add a "removal" cookie to the response that matches attributes of given cookie.
|
||||||
/// the number of cookies removed.
|
///
|
||||||
|
/// This will cause browsers/clients to remove stored cookies with this name.
|
||||||
|
///
|
||||||
|
/// The `Set-Cookie` header added to the response will have:
|
||||||
|
/// - name matching given cookie;
|
||||||
|
/// - domain matching given cookie;
|
||||||
|
/// - path matching given cookie;
|
||||||
|
/// - an empty value;
|
||||||
|
/// - a max-age of `0`;
|
||||||
|
/// - an expiration date far in the past.
|
||||||
|
///
|
||||||
|
/// If the cookie you're trying to remove has an explicit path or domain set, those attributes
|
||||||
|
/// will need to be included in the cookie passed in here.
|
||||||
|
///
|
||||||
|
/// # Errors
|
||||||
|
/// Returns an error if the given name results in a malformed `Set-Cookie` header.
|
||||||
|
#[cfg(feature = "cookies")]
|
||||||
|
pub fn add_removal_cookie(&mut self, cookie: &Cookie<'_>) -> Result<(), HttpError> {
|
||||||
|
let mut removal_cookie = cookie.to_owned();
|
||||||
|
removal_cookie.make_removal();
|
||||||
|
|
||||||
|
HeaderValue::from_str(&removal_cookie.to_string())
|
||||||
|
.map(|cookie| self.headers_mut().append(header::SET_COOKIE, cookie))
|
||||||
|
.map_err(Into::into)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Remove all cookies with the given name from this response.
|
||||||
|
///
|
||||||
|
/// Returns the number of cookies removed.
|
||||||
|
///
|
||||||
|
/// This method can _not_ cause a browser/client to delete any of its stored cookies. Its only
|
||||||
|
/// purpose is to delete cookies that were added to this response using [`add_cookie`]
|
||||||
|
/// and [`add_removal_cookie`]. Use [`add_removal_cookie`] to send a "removal" cookie.
|
||||||
|
///
|
||||||
|
/// [`add_cookie`]: Self::add_cookie
|
||||||
|
/// [`add_removal_cookie`]: Self::add_removal_cookie
|
||||||
#[cfg(feature = "cookies")]
|
#[cfg(feature = "cookies")]
|
||||||
pub fn del_cookie(&mut self, name: &str) -> usize {
|
pub fn del_cookie(&mut self, name: &str) -> usize {
|
||||||
let headers = self.headers_mut();
|
let headers = self.headers_mut();
|
||||||
@ -140,6 +176,7 @@ impl<B> HttpResponse<B> {
|
|||||||
headers.remove(header::SET_COOKIE);
|
headers.remove(header::SET_COOKIE);
|
||||||
|
|
||||||
let mut count: usize = 0;
|
let mut count: usize = 0;
|
||||||
|
|
||||||
for v in vals {
|
for v in vals {
|
||||||
if let Ok(s) = v.to_str() {
|
if let Ok(s) = v.to_str() {
|
||||||
if let Ok(c) = Cookie::parse_encoded(s) {
|
if let Ok(c) = Cookie::parse_encoded(s) {
|
||||||
@ -370,3 +407,23 @@ mod tests {
|
|||||||
assert!(dbg.contains("HttpResponse"));
|
assert!(dbg.contains("HttpResponse"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
#[cfg(feature = "cookies")]
|
||||||
|
mod cookie_tests {
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn removal_cookies() {
|
||||||
|
let mut res = HttpResponse::Ok().finish();
|
||||||
|
let cookie = Cookie::new("foo", "");
|
||||||
|
res.add_removal_cookie(&cookie).unwrap();
|
||||||
|
let set_cookie_hdr = res.headers().get(header::SET_COOKIE).unwrap();
|
||||||
|
assert_eq!(
|
||||||
|
&set_cookie_hdr.as_bytes()[..25],
|
||||||
|
&b"foo=; Max-Age=0; Expires="[..],
|
||||||
|
"unexpected set-cookie value: {:?}",
|
||||||
|
set_cookie_hdr.to_str()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user