Skip to content

Commit

Permalink
add HttpResponse::add_removal_cookie (#2586)
Browse files Browse the repository at this point in the history
  • Loading branch information
robjtede committed Jan 19, 2022
1 parent ad159f5 commit 5ee5554
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 8 deletions.
4 changes: 4 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
# Changes

## Unreleased - 2021-xx-xx
### Added
- `HttpResponse::add_removal_cookie` [#2586]

### Removed
- `HttpRequest::req_data[_mut]()`; request-local data is still available through `.extensions()`. [#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
Expand Down
73 changes: 65 additions & 8 deletions src/response/response.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ use crate::{error::Error, HttpRequest, HttpResponseBuilder, Responder};
/// An outgoing response.
pub struct HttpResponse<B = BoxBody> {
res: Response<B>,
pub(crate) error: Option<Error>,
error: Option<Error>,
}

impl HttpResponse<BoxBody> {
Expand Down Expand Up @@ -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")]
pub fn add_cookie(&mut self, cookie: &Cookie<'_>) -> Result<(), HttpError> {
HeaderValue::from_str(&cookie.to_string())
.map(|c| {
self.headers_mut().append(header::SET_COOKIE, c);
})
.map_err(|e| e.into())
.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.
/// Add a "removal" cookie to the response that matches attributes of given cookie.
///
/// 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")]
pub fn del_cookie(&mut self, name: &str) -> usize {
let headers = self.headers_mut();
Expand All @@ -140,6 +176,7 @@ impl<B> HttpResponse<B> {
headers.remove(header::SET_COOKIE);

let mut count: usize = 0;

for v in vals {
if let Ok(s) = v.to_str() {
if let Ok(c) = Cookie::parse_encoded(s) {
Expand Down Expand Up @@ -370,3 +407,23 @@ mod tests {
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()
);
}
}

0 comments on commit 5ee5554

Please sign in to comment.