aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Fischer <martin@push-f.com>2021-01-26 10:56:58 +0100
committerMartin Fischer <martin@push-f.com>2021-01-26 11:01:52 +0100
commit18b1b875c80a244f6ea29894672db18b90ec4eea (patch)
tree03bd90c620b4f17d59fcbc3a4843d00adf4368bb
parent3fd065757f02ebf1d055912e6809fac15c8bf058 (diff)
fix wrong insertion/appending of headers
-rw-r--r--src/response.rs53
1 files changed, 47 insertions, 6 deletions
diff --git a/src/response.rs b/src/response.rs
index 9c92e4c..78e9a70 100644
--- a/src/response.rs
+++ b/src/response.rs
@@ -1,15 +1,17 @@
//! Provides the [`SputnikBuilder`] trait.
+use std::convert::TryInto;
+
use cookie::Cookie;
-use hyper::{StatusCode, header::{self, HeaderValue}, http};
+use hyper::{StatusCode, header, http};
use time::{Duration, OffsetDateTime};
use hyper::http::response::Builder;
pub trait SputnikBuilder {
- /// Adds a Set-Cookie header.
+ /// Appends a Set-Cookie header.
fn set_cookie(&mut self, cookie: Cookie);
- /// Adds a Set-Cookie header to delete a cookie.
+ /// Appends a Set-Cookie header to delete a cookie.
fn delete_cookie(&mut self, name: &str);
/// Sets the Content-Type.
@@ -23,7 +25,9 @@ pub fn redirect(location: &str, code: StatusCode) -> Builder {
impl SputnikBuilder for Builder {
fn set_cookie(&mut self, cookie: Cookie) {
- self.headers_mut().unwrap().insert(header::SET_COOKIE, HeaderValue::from_str(&cookie.encoded().to_string()).unwrap());
+ if let Some(headers) = self.headers_mut() {
+ headers.append(header::SET_COOKIE, cookie.encoded().to_string().try_into().unwrap());
+ }
}
fn delete_cookie(&mut self, name: &str) {
@@ -33,8 +37,11 @@ impl SputnikBuilder for Builder {
self.set_cookie(cookie);
}
- fn content_type(self, mime: mime::Mime) -> Self {
- self.header(header::CONTENT_TYPE, mime.to_string())
+ fn content_type(mut self, mime: mime::Mime) -> Self {
+ if let Some(headers) = self.headers_mut() {
+ headers.insert(header::CONTENT_TYPE, mime.to_string().try_into().unwrap());
+ }
+ self
}
}
@@ -47,4 +54,38 @@ impl EmptyBuilder<hyper::Body> for Builder {
fn empty(self) -> http::Result<http::response::Response<hyper::Body>> {
self.body(hyper::Body::empty())
}
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ fn test_set_cookie() {
+ let mut builder = Builder::new();
+ builder.set_cookie(Cookie::new("some", "cookie"));
+ builder.set_cookie(Cookie::new("some", "cookie"));
+ let resp = builder.body(hyper::Body::empty()).unwrap();
+ assert_eq!(resp.headers().len(), 2);
+
+ let mut builder = Builder::new()
+ .header("foo", "invalid\r\n");
+ // doesn't panic after invalid header
+ builder.set_cookie(Cookie::new("some", "cookie"));
+ }
+
+ #[test]
+ fn test_content_type() {
+ let resp = Builder::new()
+ .content_type(mime::TEXT_PLAIN)
+ .content_type(mime::TEXT_HTML)
+ .body(hyper::Body::empty()).unwrap();
+ assert_eq!(resp.headers().len(), 1);
+ assert_eq!(resp.headers().get(header::CONTENT_TYPE).unwrap(), "text/html");
+
+ // doesn't panic after invalid header
+ Builder::new()
+ .header("foo", "invalid\r\n")
+ .content_type(mime::TEXT_HTML);
+ }
} \ No newline at end of file