diff --git a/CHANGES.md b/CHANGES.md index 00608df76..12caa2df9 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -15,10 +15,12 @@ ### Removed * Public field of `web::Path` has been made private. [#1894] * Public field of `web::Query` has been made private. [#1894] +* `TestRequest::with_header`; use `TestRequest::default().insert_header()`. [#1869] [#1891]: https://github.com/actix/actix-web/pull/1891 [#1893]: https://github.com/actix/actix-web/pull/1893 [#1894]: https://github.com/actix/actix-web/pull/1894 +[#1869]: https://github.com/actix/actix-web/pull/1869 ## 4.0.0-beta.1 - 2021-01-07 diff --git a/actix-http/CHANGES.md b/actix-http/CHANGES.md index 2105e25e3..cdfe277fb 100644 --- a/actix-http/CHANGES.md +++ b/actix-http/CHANGES.md @@ -1,11 +1,26 @@ # Changes ## Unreleased - 2021-xx-xx -### Changed -* `Response::content_type` now takes an `impl IntoHeaderValue` to support `mime` types. [#1894] -* `Response::set` and `Response::header` methods; use the respective `Response::set_header` and - `Response::append_header` methods. [#1869] +### Added +* `IntoHeaderPair` trait that allows using types and non-typed headers in the same methods. [#1869] +* `ResponseBuilder::insert_header` method which allows using typed headers. [#1869] +* `ResponseBuilder::append_header` method which allows using typed headers. [#1869] +* `TestRequest::insert_header` method which allows using typed headers. [#1869] +### Changed +* `ResponseBuilder::content_type` now takes an `impl IntoHeaderValue` to support using typed + `mime` types. [#1894] +* Renamed `IntoHeaderValue::{try_into => try_into_value}` to avoid ambiguity with std + `TryInto` trait. [#1894] + +### Removed +* `ResponseBuilder::set`; use `ResponseBuilder::insert_header`. [#1869] +* `ResponseBuilder::set_header`; use `ResponseBuilder::insert_header`. [#1869] +* `ResponseBuilder::header`; use `ResponseBuilder::append_header`. [#1869] +* `TestRequest::with_hdr`; use `TestRequest::default().insert_header()`. [#1869] +* `TestRequest::with_header`; use `TestRequest::default().insert_header()`. [#1869] + +[#1869]: https://github.com/actix/actix-web/pull/1869 [#1894]: https://github.com/actix/actix-web/pull/1894 @@ -35,12 +50,8 @@ [#1813]: https://github.com/actix/actix-web/pull/1813 [#1857]: https://github.com/actix/actix-web/pull/1857 [#1864]: https://github.com/actix/actix-web/pull/1864 -<<<<<<< HEAD [#1878]: https://github.com/actix/actix-web/pull/1878 -======= -[#1869]: https://github.com/actix/actix-web/pull/1869 ->>>>>>> 587000a2... add IntoHeaderPair trait ## 2.2.0 - 2020-11-25 ### Added diff --git a/actix-http/src/header/common/accept.rs b/actix-http/src/header/common/accept.rs index da26b0261..98ad240e1 100644 --- a/actix-http/src/header/common/accept.rs +++ b/actix-http/src/header/common/accept.rs @@ -132,7 +132,7 @@ header! { #[test] fn test_fuzzing1() { use crate::test::TestRequest; - let req = TestRequest::with_header(crate::header::ACCEPT, "chunk#;e").finish(); + let req = TestRequest::default().insert_header(crate::header::ACCEPT, "chunk#;e").finish(); let header = Accept::parse(&req); assert!(header.is_ok()); } diff --git a/actix-http/src/header/common/cache_control.rs b/actix-http/src/header/common/cache_control.rs index b081355d4..c57d4a2a7 100644 --- a/actix-http/src/header/common/cache_control.rs +++ b/actix-http/src/header/common/cache_control.rs @@ -196,7 +196,7 @@ mod tests { #[test] fn test_parse_multiple_headers() { - let req = TestRequest::with_header(header::CACHE_CONTROL, "no-cache, private") + let req = TestRequest::default().insert_header(header::CACHE_CONTROL, "no-cache, private") .finish(); let cache = Header::parse(&req); assert_eq!( @@ -211,7 +211,7 @@ mod tests { #[test] fn test_parse_argument() { let req = - TestRequest::with_header(header::CACHE_CONTROL, "max-age=100, private") + TestRequest::default().insert_header(header::CACHE_CONTROL, "max-age=100, private") .finish(); let cache = Header::parse(&req); assert_eq!( @@ -226,7 +226,7 @@ mod tests { #[test] fn test_parse_quote_form() { let req = - TestRequest::with_header(header::CACHE_CONTROL, "max-age=\"200\"").finish(); + TestRequest::default().insert_header(header::CACHE_CONTROL, "max-age=\"200\"").finish(); let cache = Header::parse(&req); assert_eq!( cache.ok(), @@ -237,7 +237,7 @@ mod tests { #[test] fn test_parse_extension() { let req = - TestRequest::with_header(header::CACHE_CONTROL, "foo, bar=baz").finish(); + TestRequest::default().insert_header(header::CACHE_CONTROL, "foo, bar=baz").finish(); let cache = Header::parse(&req); assert_eq!( cache.ok(), @@ -250,7 +250,7 @@ mod tests { #[test] fn test_parse_bad_syntax() { - let req = TestRequest::with_header(header::CACHE_CONTROL, "foo=").finish(); + let req = TestRequest::default().insert_header(header::CACHE_CONTROL, "foo=").finish(); let cache: Result = Header::parse(&req); assert_eq!(cache.ok(), None) } diff --git a/actix-http/src/header/common/if_none_match.rs b/actix-http/src/header/common/if_none_match.rs index 7f6ccb137..adc904561 100644 --- a/actix-http/src/header/common/if_none_match.rs +++ b/actix-http/src/header/common/if_none_match.rs @@ -73,12 +73,12 @@ mod tests { fn test_if_none_match() { let mut if_none_match: Result; - let req = TestRequest::with_header(IF_NONE_MATCH, "*").finish(); + let req = TestRequest::default().insert_header(IF_NONE_MATCH, "*").finish(); if_none_match = Header::parse(&req); assert_eq!(if_none_match.ok(), Some(IfNoneMatch::Any)); let req = - TestRequest::with_header(IF_NONE_MATCH, &b"\"foobar\", W/\"weak-etag\""[..]) + TestRequest::default().insert_header(IF_NONE_MATCH, &b"\"foobar\", W/\"weak-etag\""[..]) .finish(); if_none_match = Header::parse(&req); diff --git a/actix-http/src/header/into_pair.rs b/actix-http/src/header/into_pair.rs index 9dcff688d..d0d6e7324 100644 --- a/actix-http/src/header/into_pair.rs +++ b/actix-http/src/header/into_pair.rs @@ -1,6 +1,5 @@ -use std::convert::{Infallible, TryFrom}; +use std::convert::TryFrom; -use either::Either; use http::{ header::{HeaderName, InvalidHeaderName, InvalidHeaderValue}, Error as HttpError, HeaderValue, @@ -10,39 +9,11 @@ use super::{Header, IntoHeaderValue}; /// Transforms structures into header K/V pairs for inserting into `HeaderMap`s. pub trait IntoHeaderPair: Sized { - type Error; + type Error: Into; fn try_into_header_pair(self) -> Result<(HeaderName, HeaderValue), Self::Error>; } -impl IntoHeaderPair for (HeaderName, HeaderValue) { - type Error = Infallible; - - fn try_into_header_pair(self) -> Result<(HeaderName, HeaderValue), Self::Error> { - Ok(self) - } -} - -impl IntoHeaderPair for (HeaderName, &str) { - type Error = InvalidHeaderValue; - - fn try_into_header_pair(self) -> Result<(HeaderName, HeaderValue), Self::Error> { - let (name, value) = self; - let value = HeaderValue::try_from(value)?; - Ok((name, value)) - } -} - -impl IntoHeaderPair for (&str, HeaderValue) { - type Error = InvalidHeaderName; - - fn try_into_header_pair(self) -> Result<(HeaderName, HeaderValue), Self::Error> { - let (name, value) = self; - let name = HeaderName::try_from(name)?; - Ok((name, value)) - } -} - #[derive(Debug)] pub enum InvalidHeaderPart { Name(InvalidHeaderName), @@ -58,52 +29,86 @@ impl From for HttpError { } } -impl IntoHeaderPair for (&str, &str) { +impl IntoHeaderPair for (HeaderName, V) +where + V: IntoHeaderValue, + V::Error: Into, +{ + type Error = InvalidHeaderPart; + + fn try_into_header_pair(self) -> Result<(HeaderName, HeaderValue), Self::Error> { + let (name, value) = self; + let value = value + .try_into_value() + .map_err(|err| InvalidHeaderPart::Value(err.into()))?; + Ok((name, value)) + } +} + +impl IntoHeaderPair for (&HeaderName, V) +where + V: IntoHeaderValue, + V::Error: Into, +{ + type Error = InvalidHeaderPart; + + fn try_into_header_pair(self) -> Result<(HeaderName, HeaderValue), Self::Error> { + let (name, value) = self; + let value = value + .try_into_value() + .map_err(|err| InvalidHeaderPart::Value(err.into()))?; + Ok((name.clone(), value)) + } +} + +impl IntoHeaderPair for (&[u8], V) +where + V: IntoHeaderValue, + V::Error: Into, +{ type Error = InvalidHeaderPart; fn try_into_header_pair(self) -> Result<(HeaderName, HeaderValue), Self::Error> { let (name, value) = self; let name = HeaderName::try_from(name).map_err(InvalidHeaderPart::Name)?; - let value = HeaderValue::try_from(value).map_err(InvalidHeaderPart::Value)?; + let value = value + .try_into_value() + .map_err(|err| InvalidHeaderPart::Value(err.into()))?; Ok((name, value)) } } -impl IntoHeaderPair for (HeaderName, String) { - type Error = InvalidHeaderValue; - - fn try_into_header_pair(self) -> Result<(HeaderName, HeaderValue), Self::Error> { - let (name, value) = self; - let value = HeaderValue::try_from(&value)?; - Ok((name, value)) - } -} - -impl IntoHeaderPair for (String, HeaderValue) { - type Error = InvalidHeaderName; - - fn try_into_header_pair(self) -> Result<(HeaderName, HeaderValue), Self::Error> { - let (name, value) = self; - let name = HeaderName::try_from(&name)?; - Ok((name, value)) - } -} - -impl IntoHeaderPair for (String, String) { - type Error = Either; - - fn try_into_header_pair(self) -> Result<(HeaderName, HeaderValue), Self::Error> { - let (name, value) = self; - let name = HeaderName::try_from(&name).map_err(Either::Left)?; - let value = HeaderValue::try_from(&value).map_err(Either::Right)?; - Ok((name, value)) - } -} - -impl IntoHeaderPair for T +impl IntoHeaderPair for (&str, V) where - T: Header, + V: IntoHeaderValue, + V::Error: Into, { + type Error = InvalidHeaderPart; + + fn try_into_header_pair(self) -> Result<(HeaderName, HeaderValue), Self::Error> { + let (name, value) = self; + let name = HeaderName::try_from(name).map_err(InvalidHeaderPart::Name)?; + let value = value + .try_into_value() + .map_err(|err| InvalidHeaderPart::Value(err.into()))?; + Ok((name, value)) + } +} + +impl IntoHeaderPair for (String, V) +where + V: IntoHeaderValue, + V::Error: Into, +{ + type Error = InvalidHeaderPart; + + fn try_into_header_pair(self) -> Result<(HeaderName, HeaderValue), Self::Error> { + let (name, value) = self; + (name.as_str(), value).try_into_header_pair() + } +} + +impl IntoHeaderPair for T { type Error = ::Error; fn try_into_header_pair(self) -> Result<(HeaderName, HeaderValue), Self::Error> { diff --git a/actix-http/src/header/into_value.rs b/actix-http/src/header/into_value.rs index 2e8b75b00..4b1e6cbbd 100644 --- a/actix-http/src/header/into_value.rs +++ b/actix-http/src/header/into_value.rs @@ -9,7 +9,7 @@ pub trait IntoHeaderValue: Sized { /// The type returned in the event of a conversion error. type Error: Into; - /// Try to convert value to a Header pair value. + /// Try to convert value to a HeaderValue. fn try_into_value(self) -> Result; } @@ -22,7 +22,16 @@ impl IntoHeaderValue for HeaderValue { } } -impl<'a> IntoHeaderValue for &'a str { +impl IntoHeaderValue for &HeaderValue { + type Error = InvalidHeaderValue; + + #[inline] + fn try_into_value(self) -> Result { + Ok(self.clone()) + } +} + +impl IntoHeaderValue for &str { type Error = InvalidHeaderValue; #[inline] @@ -31,7 +40,7 @@ impl<'a> IntoHeaderValue for &'a str { } } -impl<'a> IntoHeaderValue for &'a [u8] { +impl IntoHeaderValue for &[u8] { type Error = InvalidHeaderValue; #[inline] @@ -72,8 +81,16 @@ impl IntoHeaderValue for usize { #[inline] fn try_into_value(self) -> Result { - let s = format!("{}", self); - HeaderValue::try_from(s) + HeaderValue::try_from(self.to_string()) + } +} + +impl IntoHeaderValue for i64 { + type Error = InvalidHeaderValue; + + #[inline] + fn try_into_value(self) -> Result { + HeaderValue::try_from(self.to_string()) } } @@ -82,8 +99,25 @@ impl IntoHeaderValue for u64 { #[inline] fn try_into_value(self) -> Result { - let s = format!("{}", self); - HeaderValue::try_from(s) + HeaderValue::try_from(self.to_string()) + } +} + +impl IntoHeaderValue for i32 { + type Error = InvalidHeaderValue; + + #[inline] + fn try_into_value(self) -> Result { + HeaderValue::try_from(self.to_string()) + } +} + +impl IntoHeaderValue for u32 { + type Error = InvalidHeaderValue; + + #[inline] + fn try_into_value(self) -> Result { + HeaderValue::try_from(self.to_string()) } } diff --git a/actix-http/src/header/map.rs b/actix-http/src/header/map.rs index 107bed0fa..8f20f3e6f 100644 --- a/actix-http/src/header/map.rs +++ b/actix-http/src/header/map.rs @@ -285,6 +285,7 @@ impl<'a> AsName for &'a String { } } +/// Iterator for all values in a `HeaderMap` with the same name. pub struct GetAll<'a> { idx: usize, item: Option<&'a Value>, diff --git a/actix-http/src/header/mod.rs b/actix-http/src/header/mod.rs index 6ee104894..e4e15cd91 100644 --- a/actix-http/src/header/mod.rs +++ b/actix-http/src/header/mod.rs @@ -1,4 +1,5 @@ -//! Various HTTP headers. +//! Typed HTTP headers, pre-defined `HeaderName`s, traits for parsing/conversion and other +//! header utility methods. use std::fmt; @@ -68,7 +69,7 @@ impl fmt::Write for Writer { } } -/// Convert http::HeaderMap to a HeaderMap +/// Convert `http::HeaderMap` to our `HeaderMap`. impl From for HeaderMap { fn from(map: http::HeaderMap) -> HeaderMap { let mut new_map = HeaderMap::with_capacity(map.capacity()); @@ -80,7 +81,7 @@ impl From for HeaderMap { } // This encode set is used for HTTP header values and is defined at -// https://tools.ietf.org/html/rfc5987#section-3.2 +// https://tools.ietf.org/html/rfc5987#section-3.2. pub(crate) const HTTP_VALUE: &AsciiSet = &CONTROLS .add(b' ') .add(b'"') diff --git a/actix-http/src/httpmessage.rs b/actix-http/src/httpmessage.rs index 80c4c4d41..923c63fa9 100644 --- a/actix-http/src/httpmessage.rs +++ b/actix-http/src/httpmessage.rs @@ -173,11 +173,13 @@ mod tests { #[test] fn test_content_type() { - let req = TestRequest::with_header("content-type", "text/plain").finish(); + let req = TestRequest::default() + .insert_header("content-type", "text/plain") + .finish(); assert_eq!(req.content_type(), "text/plain"); - let req = - TestRequest::with_header("content-type", "application/json; charset=utf=8") - .finish(); + let req = TestRequest::default() + .insert_header("content-type", "application/json; charset=utf=8") + .finish(); assert_eq!(req.content_type(), "application/json"); let req = TestRequest::default().finish(); assert_eq!(req.content_type(), ""); @@ -185,13 +187,15 @@ mod tests { #[test] fn test_mime_type() { - let req = TestRequest::with_header("content-type", "application/json").finish(); + let req = TestRequest::default() + .insert_header("content-type", "application/json") + .finish(); assert_eq!(req.mime_type().unwrap(), Some(mime::APPLICATION_JSON)); let req = TestRequest::default().finish(); assert_eq!(req.mime_type().unwrap(), None); - let req = - TestRequest::with_header("content-type", "application/json; charset=utf-8") - .finish(); + let req = TestRequest::default() + .insert_header("content-type", "application/json; charset=utf-8") + .finish(); let mt = req.mime_type().unwrap().unwrap(); assert_eq!(mt.get_param(mime::CHARSET), Some(mime::UTF_8)); assert_eq!(mt.type_(), mime::APPLICATION); @@ -200,11 +204,9 @@ mod tests { #[test] fn test_mime_type_error() { - let req = TestRequest::with_header( - "content-type", - "applicationadfadsfasdflknadsfklnadsfjson", - ) - .finish(); + let req = TestRequest::default() + .insert_header("content-type", "applicationadfadsfasdflknadsfklnadsfjson") + .finish(); assert_eq!(Err(ContentTypeError::ParseError), req.mime_type()); } @@ -213,27 +215,27 @@ mod tests { let req = TestRequest::default().finish(); assert_eq!(UTF_8.name(), req.encoding().unwrap().name()); - let req = TestRequest::with_header("content-type", "application/json").finish(); + let req = TestRequest::default() + .insert_header("content-type", "application/json") + .finish(); assert_eq!(UTF_8.name(), req.encoding().unwrap().name()); - let req = TestRequest::with_header( - "content-type", - "application/json; charset=ISO-8859-2", - ) - .finish(); + let req = TestRequest::default() + .insert_header("content-type", "application/json; charset=ISO-8859-2") + .finish(); assert_eq!(ISO_8859_2, req.encoding().unwrap()); } #[test] fn test_encoding_error() { - let req = TestRequest::with_header("content-type", "applicatjson").finish(); + let req = TestRequest::default() + .insert_header("content-type", "applicatjson") + .finish(); assert_eq!(Some(ContentTypeError::ParseError), req.encoding().err()); - let req = TestRequest::with_header( - "content-type", - "application/json; charset=kkkttktk", - ) - .finish(); + let req = TestRequest::default() + .insert_header("content-type", "application/json; charset=kkkttktk") + .finish(); assert_eq!( Some(ContentTypeError::UnknownEncoding), req.encoding().err() @@ -245,8 +247,9 @@ mod tests { let req = TestRequest::default().finish(); assert!(!req.chunked().unwrap()); - let req = - TestRequest::with_header(header::TRANSFER_ENCODING, "chunked").finish(); + let req = TestRequest::default() + .insert_header(header::TRANSFER_ENCODING, "chunked") + .finish(); assert!(req.chunked().unwrap()); let req = TestRequest::default() diff --git a/actix-http/src/response.rs b/actix-http/src/response.rs index cc5a11e08..3f43c4d98 100644 --- a/actix-http/src/response.rs +++ b/actix-http/src/response.rs @@ -2,7 +2,6 @@ use std::{ cell::{Ref, RefMut}, - convert::TryFrom, fmt, future::Future, pin::Pin, @@ -18,8 +17,8 @@ use crate::body::{Body, BodyStream, MessageBody, ResponseBody}; use crate::cookie::{Cookie, CookieJar}; use crate::error::Error; use crate::extensions::Extensions; -use crate::header::{Header, IntoHeaderPair, IntoHeaderValue}; -use crate::http::header::{self, HeaderName, HeaderValue}; +use crate::header::{IntoHeaderPair, IntoHeaderValue}; +use crate::http::header::{self, HeaderValue}; use crate::http::{Error as HttpError, HeaderMap, StatusCode}; use crate::message::{BoxedResponseHead, ConnectionType, ResponseHead}; @@ -345,80 +344,18 @@ impl ResponseBuilder { self } - /// Set a header. + /// Insert a header, replacing any that were set with an equivalent field name. /// /// ```rust - /// use actix_http::{http, Request, Response, Result}; - /// - /// fn index(req: Request) -> Result { - /// Ok(Response::Ok() - /// .set(http::header::IfModifiedSince( - /// "Sun, 07 Nov 1994 08:48:37 GMT".parse()?, - /// )) - /// .finish()) - /// } - /// ``` - #[doc(hidden)] - pub fn set(&mut self, hdr: H) -> &mut Self { - if let Some(parts) = parts(&mut self.head, &self.err) { - match hdr.try_into_value() { - Ok(value) => { - parts.headers.append(H::name(), value); - } - Err(e) => self.err = Some(e.into()), - } - } - self - } - - /// Append a header to existing headers. - /// - /// ```rust - /// use actix_http::{http, Request, Response}; - /// - /// fn index(req: Request) -> Response { - /// Response::Ok() - /// .header("X-TEST", "value") - /// .header(http::header::CONTENT_TYPE, "application/json") - /// .finish() - /// } - /// ``` - pub fn header(&mut self, key: K, value: V) -> &mut Self - where - HeaderName: TryFrom, - >::Error: Into, - V: IntoHeaderValue, - { - if let Some(parts) = parts(&mut self.head, &self.err) { - match HeaderName::try_from(key) { - Ok(key) => match value.try_into_value() { - Ok(value) => { - parts.headers.append(key, value); - } - Err(e) => self.err = Some(e.into()), - }, - Err(e) => self.err = Some(e.into()), - }; - } - self - } - - /// Insert a header, replacing any that existed with an equivalent field name. - /// - /// ```rust - /// use actix_http::{http, Request, Response}; - /// - /// fn index(req: Request) -> Response { - /// Response::Ok() - /// .set_header(("X-TEST", "value")) - /// .set_header(ContentType(mime::APPLICATION_JSON)) - /// .finish() - /// } + /// # use actix_http::Response; + /// Response::Ok() + /// .set_header(("X-TEST", "value")) + /// .set_header(ContentType(mime::APPLICATION_JSON)) + /// .finish() /// ``` pub fn insert_header(&mut self, header: H) -> &mut Self where H: IntoHeaderPair, - H::Error: Into, { if let Some(parts) = parts(&mut self.head, &self.err) { match header.try_into_header_pair() { @@ -430,22 +367,18 @@ impl ResponseBuilder { self } - /// Append a header, keeping any that existed with an equivalent field name. + /// Append a header, keeping any that were set with an equivalent field name. /// /// ```rust - /// use actix_http::{http, Request, Response}; - /// - /// fn index(req: Request) -> Response { - /// Response::Ok() - /// .append_header(("X-TEST", "value")) - /// .append_header(ContentType(mime::APPLICATION_JSON)) - /// .finish() - /// } + /// # use actix_http::Response; + /// Response::Ok() + /// .append_header(("X-TEST", "value")) + /// .append_header(ContentType(mime::APPLICATION_JSON)) + /// .finish() /// ``` pub fn append_header(&mut self, header: H) -> &mut Self where H: IntoHeaderPair, - H::Error: Into, { if let Some(parts) = parts(&mut self.head, &self.err) { match header.try_into_header_pair() { @@ -504,7 +437,7 @@ impl ResponseBuilder { /// Disable chunked transfer encoding for HTTP/1.1 streaming responses. #[inline] pub fn no_chunking(&mut self, len: u64) -> &mut Self { - self.header(header::CONTENT_LENGTH, len); + self.insert_header((header::CONTENT_LENGTH, len)); if let Some(parts) = parts(&mut self.head, &self.err) { parts.no_chunking(true); @@ -519,7 +452,7 @@ impl ResponseBuilder { V: IntoHeaderValue, { if let Some(parts) = parts(&mut self.head, &self.err) { - match value.try_into() { + match value.try_into_value() { Ok(value) => { parts.headers.insert(header::CONTENT_TYPE, value); } @@ -689,8 +622,9 @@ impl ResponseBuilder { } else { true }; + if !contains { - self.header(header::CONTENT_TYPE, "application/json"); + self.insert_header(header::ContentType(mime::APPLICATION_JSON)); } self.body(Body::from(body)) diff --git a/actix-http/src/test.rs b/actix-http/src/test.rs index 0b99ec41e..4f6b88c09 100644 --- a/actix-http/src/test.rs +++ b/actix-http/src/test.rs @@ -13,7 +13,7 @@ use actix_codec::{AsyncRead, AsyncWrite, ReadBuf}; use bytes::{Bytes, BytesMut}; use http::{ header::{self, HeaderValue}, - Error as HttpError, Method, Uri, Version, + Method, Uri, Version, }; use crate::{ @@ -38,7 +38,7 @@ use crate::{ /// } /// } /// -/// let resp = TestRequest::with_header("content-type", "text/plain") +/// let resp = TestRequest::default().insert_header("content-type", "text/plain") /// .run(&index) /// .unwrap(); /// assert_eq!(resp.status(), StatusCode::OK); @@ -76,15 +76,6 @@ impl TestRequest { TestRequest::default().uri(path).take() } - /// Create a default TestRequest and then set a header. - pub fn with_header(header: H) -> TestRequest - where - H: IntoHeaderPair, - H::Error: Into, - { - TestRequest::default().header(header).take() - } - /// Set HTTP version of this request. pub fn version(&mut self, ver: Version) -> &mut Self { parts(&mut self.0).version = ver; @@ -97,17 +88,35 @@ impl TestRequest { self } - /// Set HTTP Uri of this request. + /// Set URI of this request. + /// + /// # Panics + /// If provided URI is invalid. pub fn uri(&mut self, path: &str) -> &mut Self { parts(&mut self.0).uri = Uri::from_str(path).unwrap(); self } - /// Set a header. - pub fn header(&mut self, header: H) -> &mut Self + /// Insert a header, replacing any that were set with an equivalent field name. + pub fn insert_header(&mut self, header: H) -> &mut Self + where + H: IntoHeaderPair, + { + match header.try_into_header_pair() { + Ok((key, value)) => { + parts(&mut self.0).headers.insert(key, value); + return self; + } + Err(err) => { + panic!("Error inserting test header: {}.", err.into()); + } + } + } + + /// Append a header, keeping any that were set with an equivalent field name. + pub fn append_header(&mut self, header: H) -> &mut Self where H: IntoHeaderPair, - H::Error: Into, { match header.try_into_header_pair() { Ok((key, value)) => { @@ -115,7 +124,7 @@ impl TestRequest { return self; } Err(err) => { - panic!("Error setting test header: {}.", err.into()); + panic!("Error inserting test header: {}.", err.into()); } } } diff --git a/actix-http/src/ws/mod.rs b/actix-http/src/ws/mod.rs index a2b093ce4..9f660ae68 100644 --- a/actix-http/src/ws/mod.rs +++ b/actix-http/src/ws/mod.rs @@ -101,7 +101,7 @@ impl ResponseError for HandshakeError { fn error_response(&self) -> Response { match self { HandshakeError::GetMethodRequired => Response::MethodNotAllowed() - .header(header::ALLOW, "GET") + .insert_header((header::ALLOW, "GET")) .finish(), HandshakeError::NoWebsocketUpgrade => Response::BadRequest() @@ -198,8 +198,8 @@ pub fn handshake_response(req: &RequestHead) -> ResponseBuilder { Response::build(StatusCode::SWITCHING_PROTOCOLS) .upgrade("websocket") - .header(header::TRANSFER_ENCODING, "chunked") - .header(header::SEC_WEBSOCKET_ACCEPT, key.as_str()) + .insert_header((header::TRANSFER_ENCODING, "chunked")) + .insert_header((header::SEC_WEBSOCKET_ACCEPT, key)) .take() } diff --git a/awc/CHANGES.md b/awc/CHANGES.md index 89b6121f3..c5c1185be 100644 --- a/awc/CHANGES.md +++ b/awc/CHANGES.md @@ -1,6 +1,17 @@ # Changes ## Unreleased - 2021-xx-xx +### Added +* `ClientRequest::insert_header` method which allows using typed headers. [#1869] +* `ClientRequest::append_header` method which allows using typed headers. [#1869] + +### Removed +* `ClientRequest::set`; use `ClientRequest::insert_header`. [#1869] +* `ClientRequest::set_header`; use `ClientRequest::insert_header`. [#1869] +* `ClientRequest::set_header_if_none`; use `ClientRequest::insert_header_if_none`. [#1869] +* `ClientRequest::header`; use `ClientRequest::append_header`. [#1869] + +[#1869]: https://github.com/actix/actix-web/pull/1869 ## 3.0.0-beta.1 - 2021-01-07 diff --git a/awc/src/lib.rs b/awc/src/lib.rs index aad6ec38b..3328756bf 100644 --- a/awc/src/lib.rs +++ b/awc/src/lib.rs @@ -182,8 +182,8 @@ impl Client { { let mut req = ClientRequest::new(method, url, self.0.clone()); - for (key, value) in self.0.headers.iter() { - req = req.set_header_if_none(key.clone(), value.clone()); + for header in self.0.headers.iter() { + req = req.insert_header_if_none(header); } req } @@ -198,8 +198,8 @@ impl Client { >::Error: Into, { let mut req = self.request(head.method.clone(), url); - for (key, value) in head.headers.iter() { - req = req.set_header_if_none(key.clone(), value.clone()); + for header in head.headers.iter() { + req = req.insert_header_if_none(header); } req } diff --git a/awc/src/request.rs b/awc/src/request.rs index 4d2c0bdad..52841efc7 100644 --- a/awc/src/request.rs +++ b/awc/src/request.rs @@ -9,10 +9,10 @@ use serde::Serialize; use actix_http::body::Body; use actix_http::cookie::{Cookie, CookieJar}; -use actix_http::http::header::{self, Header, IntoHeaderValue}; +use actix_http::http::header::{self, IntoHeaderPair}; use actix_http::http::{ - uri, ConnectionType, Error as HttpError, HeaderMap, HeaderName, HeaderValue, Method, - Uri, Version, + uri, ConnectionType, Error as HttpError, HeaderMap, HeaderValue, Method, Uri, + Version, }; use actix_http::{Error, RequestHead}; @@ -143,45 +143,49 @@ impl ClientRequest { &self.head.peer_addr } - #[inline] /// Returns request's headers. + #[inline] pub fn headers(&self) -> &HeaderMap { &self.head.headers } - #[inline] /// Returns request's mutable headers. + #[inline] pub fn headers_mut(&mut self) -> &mut HeaderMap { &mut self.head.headers } - /// Set a header. - /// - /// ```rust - /// fn main() { - /// # actix_rt::System::new("test").block_on(futures_util::future::lazy(|_| { - /// let req = awc::Client::new() - /// .get("http://www.rust-lang.org") - /// .set(awc::http::header::Date::now()) - /// .set(awc::http::header::ContentType(mime::TEXT_HTML)); - /// # Ok::<_, ()>(()) - /// # })); - /// } - /// ``` - pub fn set(mut self, hdr: H) -> Self { - match hdr.try_into_value() { - Ok(value) => { - self.head.headers.insert(H::name(), value); - } + /// Insert a header, replacing any that were set with an equivalent field name. + pub fn insert_header(mut self, header: H) -> Self + where + H: IntoHeaderPair, + { + match header.try_into_header_pair() { + Ok((key, value)) => self.head.headers.insert(key, value), Err(e) => self.err = Some(e.into()), - } + }; + self } - /// Append a header. - /// - /// Header gets appended to existing header. - /// To override header use `set_header()` method. + /// Insert a header only if it is not yet set. + pub fn insert_header_if_none(mut self, header: H) -> Self + where + H: IntoHeaderPair, + { + match header.try_into_header_pair() { + Ok((key, value)) => { + if !self.head.headers.contains_key(&key) { + self.head.headers.insert(key, value); + } + } + Err(e) => self.err = Some(e.into()), + }; + + self + } + + /// Append a header, keeping any that were set with an equivalent field name. /// /// ```rust /// use awc::{http, Client}; @@ -196,57 +200,15 @@ impl ClientRequest { /// # }); /// } /// ``` - pub fn header(mut self, key: K, value: V) -> Self + pub fn append_header(mut self, header: H) -> Self where - HeaderName: TryFrom, - >::Error: Into, - V: IntoHeaderValue, + H: IntoHeaderPair, { - match HeaderName::try_from(key) { - Ok(key) => match value.try_into_value() { - Ok(value) => self.head.headers.append(key, value), - Err(e) => self.err = Some(e.into()), - }, + match header.try_into_header_pair() { + Ok((key, value)) => self.head.headers.append(key, value), Err(e) => self.err = Some(e.into()), - } - self - } + }; - /// Insert a header, replaces existing header. - pub fn set_header(mut self, key: K, value: V) -> Self - where - HeaderName: TryFrom, - >::Error: Into, - V: IntoHeaderValue, - { - match HeaderName::try_from(key) { - Ok(key) => match value.try_into_value() { - Ok(value) => self.head.headers.insert(key, value), - Err(e) => self.err = Some(e.into()), - }, - Err(e) => self.err = Some(e.into()), - } - self - } - - /// Insert a header only if it is not yet set. - pub fn set_header_if_none(mut self, key: K, value: V) -> Self - where - HeaderName: TryFrom, - >::Error: Into, - V: IntoHeaderValue, - { - match HeaderName::try_from(key) { - Ok(key) => { - if !self.head.headers.contains_key(&key) { - match value.try_into_value() { - Ok(value) => self.head.headers.insert(key, value), - Err(e) => self.err = Some(e.into()), - } - } - } - Err(e) => self.err = Some(e.into()), - } self } @@ -282,7 +244,7 @@ impl ClientRequest { /// Set content length #[inline] pub fn content_length(self, len: u64) -> Self { - self.header(header::CONTENT_LENGTH, len) + self.append_header((header::CONTENT_LENGTH, len)) } /// Set HTTP basic authorization header @@ -294,10 +256,10 @@ impl ClientRequest { Some(password) => format!("{}:{}", username, password), None => format!("{}:", username), }; - self.header( + self.append_header(( header::AUTHORIZATION, format!("Basic {}", base64::encode(&auth)), - ) + )) } /// Set HTTP bearer authentication header @@ -305,7 +267,7 @@ impl ClientRequest { where T: fmt::Display, { - self.header(header::AUTHORIZATION, format!("Bearer {}", token)) + self.append_header((header::AUTHORIZATION, format!("Bearer {}", token))) } /// Set a cookie @@ -557,12 +519,15 @@ impl ClientRequest { .unwrap_or(true); if https { - slf = slf.set_header_if_none(header::ACCEPT_ENCODING, HTTPS_ENCODING) + slf = + slf.insert_header_if_none((header::ACCEPT_ENCODING, HTTPS_ENCODING)) } else { #[cfg(any(feature = "flate2-zlib", feature = "flate2-rust"))] { - slf = - slf.set_header_if_none(header::ACCEPT_ENCODING, "gzip, deflate") + slf = slf.insert_header_if_none(( + header::ACCEPT_ENCODING, + "gzip, deflate", + )) } }; } @@ -595,7 +560,7 @@ mod tests { #[actix_rt::test] async fn test_debug() { - let request = Client::new().get("/").header("x-test", "111"); + let request = Client::new().get("/").append_header("x-test", "111"); let repr = format!("{:?}", request); assert!(repr.contains("ClientRequest")); assert!(repr.contains("x-test")); @@ -608,16 +573,16 @@ mod tests { .version(Version::HTTP_2) .set(header::Date(SystemTime::now().into())) .content_type("plain/text") - .header(header::SERVER, "awc"); + .append_header(header::SERVER, "awc"); let req = if let Some(val) = Some("server") { - req.header(header::USER_AGENT, val) + req.append_header(header::USER_AGENT, val) } else { req }; let req = if let Some(_val) = Option::<&str>::None { - req.header(header::ALLOW, "1") + req.append_header(header::ALLOW, "1") } else { req }; @@ -660,7 +625,7 @@ mod tests { .header(header::CONTENT_TYPE, "111") .finish() .get("/") - .set_header(header::CONTENT_TYPE, "222"); + .insert_header(header::CONTENT_TYPE, "222"); assert_eq!( req.head diff --git a/awc/tests/test_client.rs b/awc/tests/test_client.rs index 6cae77a49..3133132ec 100644 --- a/awc/tests/test_client.rs +++ b/awc/tests/test_client.rs @@ -52,7 +52,7 @@ async fn test_simple() { .service(web::resource("/").route(web::to(|| HttpResponse::Ok().body(STR)))) }); - let request = srv.get("/").header("x-test", "111").send(); + let request = srv.get("/").append_header("x-test", "111").send(); let mut response = request.await.unwrap(); assert!(response.status().is_success()); @@ -82,7 +82,7 @@ async fn test_json() { let request = srv .get("/") - .header("x-test", "111") + .append_header("x-test", "111") .send_json(&"TEST".to_string()); let response = request.await.unwrap(); assert!(response.status().is_success()); @@ -99,7 +99,7 @@ async fn test_form() { let mut data = HashMap::new(); let _ = data.insert("key".to_string(), "TEST".to_string()); - let request = srv.get("/").header("x-test", "111").send_form(&data); + let request = srv.get("/").append_header("x-test", "111").send_form(&data); let response = request.await.unwrap(); assert!(response.status().is_success()); } diff --git a/examples/client.rs b/examples/client.rs index 15cf24fa8..4040c2025 100644 --- a/examples/client.rs +++ b/examples/client.rs @@ -10,7 +10,7 @@ async fn main() -> Result<(), Error> { // Create request builder, configure request and send let mut response = client .get("https://www.rust-lang.org/") - .header("User-Agent", "Actix-web") + .append_header("User-Agent", "Actix-web") .send() .await?; diff --git a/src/extract.rs b/src/extract.rs index 4081188ef..7a677bca4 100644 --- a/src/extract.rs +++ b/src/extract.rs @@ -347,25 +347,21 @@ mod tests { #[actix_rt::test] async fn test_option() { - let (req, mut pl) = TestRequest::with_header( - header::CONTENT_TYPE, - "application/x-www-form-urlencoded", - ) - .data(FormConfig::default().limit(4096)) - .to_http_parts(); + let (req, mut pl) = TestRequest::default() + .insert_header((header::CONTENT_TYPE, "application/x-www-form-urlencoded")) + .data(FormConfig::default().limit(4096)) + .to_http_parts(); let r = Option::>::from_request(&req, &mut pl) .await .unwrap(); assert_eq!(r, None); - let (req, mut pl) = TestRequest::with_header( - header::CONTENT_TYPE, - "application/x-www-form-urlencoded", - ) - .header(header::CONTENT_LENGTH, "9") - .set_payload(Bytes::from_static(b"hello=world")) - .to_http_parts(); + let (req, mut pl) = TestRequest::default() + .insert_header((header::CONTENT_TYPE, "application/x-www-form-urlencoded")) + .insert_header((header::CONTENT_LENGTH, "9")) + .set_payload(Bytes::from_static(b"hello=world")) + .to_http_parts(); let r = Option::>::from_request(&req, &mut pl) .await @@ -377,13 +373,11 @@ mod tests { })) ); - let (req, mut pl) = TestRequest::with_header( - header::CONTENT_TYPE, - "application/x-www-form-urlencoded", - ) - .header(header::CONTENT_LENGTH, "9") - .set_payload(Bytes::from_static(b"bye=world")) - .to_http_parts(); + let (req, mut pl) = TestRequest::default() + .insert_header((header::CONTENT_TYPE, "application/x-www-form-urlencoded")) + .insert_header((header::CONTENT_LENGTH, "9")) + .set_payload(Bytes::from_static(b"bye=world")) + .to_http_parts(); let r = Option::>::from_request(&req, &mut pl) .await @@ -393,13 +387,11 @@ mod tests { #[actix_rt::test] async fn test_result() { - let (req, mut pl) = TestRequest::with_header( - header::CONTENT_TYPE, - "application/x-www-form-urlencoded", - ) - .header(header::CONTENT_LENGTH, "11") - .set_payload(Bytes::from_static(b"hello=world")) - .to_http_parts(); + let (req, mut pl) = TestRequest::default() + .insert_header((header::CONTENT_TYPE, "application/x-www-form-urlencoded")) + .insert_header((header::CONTENT_LENGTH, "11")) + .set_payload(Bytes::from_static(b"hello=world")) + .to_http_parts(); let r = Result::, Error>::from_request(&req, &mut pl) .await @@ -412,13 +404,11 @@ mod tests { }) ); - let (req, mut pl) = TestRequest::with_header( - header::CONTENT_TYPE, - "application/x-www-form-urlencoded", - ) - .header(header::CONTENT_LENGTH, "9") - .set_payload(Bytes::from_static(b"bye=world")) - .to_http_parts(); + let (req, mut pl) = TestRequest::default() + .insert_header((header::CONTENT_TYPE, "application/x-www-form-urlencoded")) + .insert_header((header::CONTENT_LENGTH, 9)) + .set_payload(Bytes::from_static(b"bye=world")) + .to_http_parts(); let r = Result::, Error>::from_request(&req, &mut pl) .await diff --git a/src/guard.rs b/src/guard.rs index 25284236a..ba0cbea85 100644 --- a/src/guard.rs +++ b/src/guard.rs @@ -330,7 +330,8 @@ mod tests { #[test] fn test_header() { - let req = TestRequest::with_header(header::TRANSFER_ENCODING, "chunked") + let req = TestRequest::default() + .insert_header((header::TRANSFER_ENCODING, "chunked")) .to_http_request(); let pred = Header("transfer-encoding", "chunked"); @@ -346,10 +347,10 @@ mod tests { #[test] fn test_host() { let req = TestRequest::default() - .header( + .insert_header(( header::HOST, header::HeaderValue::from_static("www.rust-lang.org"), - ) + )) .to_http_request(); let pred = Host("www.rust-lang.org"); @@ -374,10 +375,10 @@ mod tests { #[test] fn test_host_scheme() { let req = TestRequest::default() - .header( + .insert_header(( header::HOST, header::HeaderValue::from_static("https://www.rust-lang.org"), - ) + )) .to_http_request(); let pred = Host("www.rust-lang.org").scheme("https"); diff --git a/src/info.rs b/src/info.rs index 75ebf67eb..c9ddf6ec4 100644 --- a/src/info.rs +++ b/src/info.rs @@ -200,10 +200,10 @@ mod tests { assert_eq!(info.host(), "localhost:8080"); let req = TestRequest::default() - .header( + .insert_header(( header::FORWARDED, "for=192.0.2.60; proto=https; by=203.0.113.43; host=rust-lang.org", - ) + )) .to_http_request(); let info = req.connection_info(); @@ -212,7 +212,7 @@ mod tests { assert_eq!(info.realip_remote_addr(), Some("192.0.2.60")); let req = TestRequest::default() - .header(header::HOST, "rust-lang.org") + .insert_header((header::HOST, "rust-lang.org")) .to_http_request(); let info = req.connection_info(); @@ -221,20 +221,20 @@ mod tests { assert_eq!(info.realip_remote_addr(), None); let req = TestRequest::default() - .header(X_FORWARDED_FOR, "192.0.2.60") + .insert_header((X_FORWARDED_FOR, "192.0.2.60")) .to_http_request(); let info = req.connection_info(); assert_eq!(info.realip_remote_addr(), Some("192.0.2.60")); let req = TestRequest::default() - .header(X_FORWARDED_HOST, "192.0.2.60") + .insert_header((X_FORWARDED_HOST, "192.0.2.60")) .to_http_request(); let info = req.connection_info(); assert_eq!(info.host(), "192.0.2.60"); assert_eq!(info.realip_remote_addr(), None); let req = TestRequest::default() - .header(X_FORWARDED_PROTO, "https") + .insert_header((X_FORWARDED_PROTO, "https")) .to_http_request(); let info = req.connection_info(); assert_eq!(info.scheme(), "https"); diff --git a/src/middleware/default_headers.rs b/src/middleware/default_headers.rs index 6f027124f..5d55fd830 100644 --- a/src/middleware/default_headers.rs +++ b/src/middleware/default_headers.rs @@ -212,8 +212,11 @@ mod tests { let req = TestRequest::default().to_srv_request(); let srv = |req: ServiceRequest| { - ok(req - .into_response(HttpResponse::Ok().header(CONTENT_TYPE, "0002").finish())) + ok(req.into_response( + HttpResponse::Ok() + .insert_header((CONTENT_TYPE, "0002")) + .finish(), + )) }; let mut mw = DefaultHeaders::new() .header(CONTENT_TYPE, "0001") diff --git a/src/middleware/logger.rs b/src/middleware/logger.rs index 276265a58..66bd7e464 100644 --- a/src/middleware/logger.rs +++ b/src/middleware/logger.rs @@ -603,7 +603,7 @@ mod tests { let srv = |req: ServiceRequest| { ok(req.into_response( HttpResponse::build(StatusCode::OK) - .header("X-Test", "ttt") + .insert_header(("X-Test", "ttt")) .finish(), )) }; @@ -611,11 +611,12 @@ mod tests { let mut srv = logger.new_transform(srv.into_service()).await.unwrap(); - let req = TestRequest::with_header( - header::USER_AGENT, - header::HeaderValue::from_static("ACTIX-WEB"), - ) - .to_srv_request(); + let req = TestRequest::default() + .insert_header(( + header::USER_AGENT, + header::HeaderValue::from_static("ACTIX-WEB"), + )) + .to_srv_request(); let _res = srv.call(req).await; } @@ -624,7 +625,7 @@ mod tests { let srv = |req: ServiceRequest| { ok(req.into_response( HttpResponse::build(StatusCode::OK) - .header("X-Test", "ttt") + .insert_header(("X-Test", "ttt")) .finish(), )) }; @@ -633,23 +634,25 @@ mod tests { let mut srv = logger.new_transform(srv.into_service()).await.unwrap(); - let req = TestRequest::with_header( - header::USER_AGENT, - header::HeaderValue::from_static("ACTIX-WEB"), - ) - .to_srv_request(); + let req = TestRequest::default() + .insert_header(( + header::USER_AGENT, + header::HeaderValue::from_static("ACTIX-WEB"), + )) + .to_srv_request(); let _res = srv.call(req).await.unwrap(); } #[actix_rt::test] async fn test_url_path() { let mut format = Format::new("%T %U"); - let req = TestRequest::with_header( - header::USER_AGENT, - header::HeaderValue::from_static("ACTIX-WEB"), - ) - .uri("/test/route/yeah") - .to_srv_request(); + let req = TestRequest::default() + .insert_header(( + header::USER_AGENT, + header::HeaderValue::from_static("ACTIX-WEB"), + )) + .uri("/test/route/yeah") + .to_srv_request(); let now = OffsetDateTime::now_utc(); for unit in &mut format.0 { @@ -676,12 +679,13 @@ mod tests { async fn test_default_format() { let mut format = Format::default(); - let req = TestRequest::with_header( - header::USER_AGENT, - header::HeaderValue::from_static("ACTIX-WEB"), - ) - .peer_addr("127.0.0.1:8081".parse().unwrap()) - .to_srv_request(); + let req = TestRequest::default() + .insert_header(( + header::USER_AGENT, + header::HeaderValue::from_static("ACTIX-WEB"), + )) + .peer_addr("127.0.0.1:8081".parse().unwrap()) + .to_srv_request(); let now = OffsetDateTime::now_utc(); for unit in &mut format.0 { @@ -736,13 +740,14 @@ mod tests { async fn test_remote_addr_format() { let mut format = Format::new("%{r}a"); - let req = TestRequest::with_header( - header::FORWARDED, - header::HeaderValue::from_static( - "for=192.0.2.60;proto=http;by=203.0.113.43", - ), - ) - .to_srv_request(); + let req = TestRequest::default() + .insert_header(( + header::FORWARDED, + header::HeaderValue::from_static( + "for=192.0.2.60;proto=http;by=203.0.113.43", + ), + )) + .to_srv_request(); let now = OffsetDateTime::now_utc(); for unit in &mut format.0 { diff --git a/src/request.rs b/src/request.rs index c0e26006c..53dac3932 100644 --- a/src/request.rs +++ b/src/request.rs @@ -423,8 +423,9 @@ mod tests { #[test] fn test_debug() { - let req = - TestRequest::with_header("content-type", "text/plain").to_http_request(); + let req = TestRequest::default() + .insert_header(("content-type", "text/plain")) + .to_http_request(); let dbg = format!("{:?}", req); assert!(dbg.contains("HttpRequest")); } @@ -438,8 +439,8 @@ mod tests { #[test] fn test_request_cookies() { let req = TestRequest::default() - .header(header::COOKIE, "cookie1=value1") - .header(header::COOKIE, "cookie2=value2") + .insert_header((header::COOKIE, "cookie1=value1")) + .insert_header((header::COOKIE, "cookie2=value2")) .to_http_request(); { let cookies = req.cookies().unwrap(); @@ -476,7 +477,8 @@ mod tests { assert!(rmap.has_resource("/user/test.html")); assert!(!rmap.has_resource("/test/unknown")); - let req = TestRequest::with_header(header::HOST, "www.rust-lang.org") + let req = TestRequest::default() + .insert_header((header::HOST, "www.rust-lang.org")) .rmap(rmap) .to_http_request(); @@ -506,7 +508,7 @@ mod tests { assert!(rmap.has_resource("/index.html")); let req = TestRequest::with_uri("/test") - .header(header::HOST, "www.rust-lang.org") + .insert_header((header::HOST, "www.rust-lang.org")) .rmap(rmap) .to_http_request(); let url = req.url_for_static("index"); @@ -557,7 +559,7 @@ mod tests { let mut srv = init_service(App::new().service(web::resource("/").to( |req: HttpRequest| { HttpResponse::Ok() - .set_header("pool_cap", req.app_state().pool().cap) + .insert_header(("pool_cap", req.app_state().pool().cap)) .finish() }, ))) diff --git a/src/responder.rs b/src/responder.rs index d1d0c28df..d5771d520 100644 --- a/src/responder.rs +++ b/src/responder.rs @@ -1,30 +1,11 @@ -use std::convert::TryFrom; - -use actix_http::error::InternalError; -use actix_http::http::{ - header::IntoHeaderPair, Error as HttpError, HeaderMap, HeaderName, StatusCode, -}; -use actix_http::ResponseBuilder; -use bytes::{Bytes, BytesMut}; -use std::{ - fmt, - future::Future, - marker::PhantomData, - pin::Pin, - task::{Context, Poll}, -}; +use std::fmt; use actix_http::{ error::InternalError, http::{header::IntoHeaderPair, Error as HttpError, HeaderMap, StatusCode}, - Error, Response, ResponseBuilder, + ResponseBuilder, }; use bytes::{Bytes, BytesMut}; -use futures_util::{ - future::{err, ok, Either as EitherFuture, Ready}, - ready, -}; -use pin_project::pin_project; use crate::{Error, HttpRequest, HttpResponse}; @@ -73,7 +54,6 @@ pub trait Responder { where Self: Sized, H: IntoHeaderPair, - H::Error: Into, { CustomResponder::new(self).with_header(header) } @@ -219,12 +199,12 @@ impl CustomResponder { /// fn index(req: HttpRequest) -> impl Responder { /// web::Json(MyObj { name: "Name".to_string() }) /// .with_header(("x-version", "1.2.3")) + /// .with_header(("x-version", "1.2.3")) /// } /// ``` pub fn with_header(mut self, header: H) -> Self where H: IntoHeaderPair, - H::Error: Into, { if self.headers.is_none() { self.headers = Some(HeaderMap::new()); @@ -423,8 +403,7 @@ pub(crate) mod tests { let res = "test" .to_string() .with_header(("content-type", "json")) - .respond_to(&req) - .unwrap(); + .respond_to(&req); assert_eq!(res.status(), StatusCode::OK); assert_eq!(res.body().bin_ref(), b"test"); @@ -443,9 +422,8 @@ pub(crate) mod tests { let req = TestRequest::default().to_http_request(); let res = ("test".to_string(), StatusCode::OK) - .with_header(CONTENT_TYPE, mime::APPLICATION_JSON) - .respond_to(&req) - .unwrap(); + .with_header((CONTENT_TYPE, mime::APPLICATION_JSON)) + .respond_to(&req); assert_eq!(res.status(), StatusCode::OK); assert_eq!(res.body().bin_ref(), b"test"); assert_eq!( diff --git a/src/service.rs b/src/service.rs index 668b7d1b4..d4fa4acca 100644 --- a/src/service.rs +++ b/src/service.rs @@ -588,14 +588,14 @@ mod tests { fn test_fmt_debug() { let req = TestRequest::get() .uri("/index.html?test=1") - .header("x-test", "111") + .insert_header(("x-test", "111")) .to_srv_request(); let s = format!("{:?}", req); assert!(s.contains("ServiceRequest")); assert!(s.contains("test=1")); assert!(s.contains("x-test")); - let res = HttpResponse::Ok().header("x-test", "111").finish(); + let res = HttpResponse::Ok().insert_header(("x-test", "111")).finish(); let res = TestRequest::post() .uri("/index.html?test=1") .to_srv_response(res); diff --git a/src/test.rs b/src/test.rs index 64bfe35cf..1a65d56a2 100644 --- a/src/test.rs +++ b/src/test.rs @@ -7,7 +7,7 @@ use std::{fmt, net, thread, time}; use actix_codec::{AsyncRead, AsyncWrite, Framed}; use actix_http::http::header::{ContentType, IntoHeaderPair}; -use actix_http::http::{Error as HttpError, Method, StatusCode, Uri, Version}; +use actix_http::http::{Method, StatusCode, Uri, Version}; use actix_http::test::TestRequest as HttpTestRequest; use actix_http::{cookie::Cookie, ws, Extensions, HttpService, Request}; use actix_router::{Path, ResourceDef, Url}; @@ -349,7 +349,7 @@ where /// /// #[test] /// fn test_index() { -/// let req = test::TestRequest::with_header("content-type", "text/plain") +/// let req = test::TestRequest::default().insert_header("content-type", "text/plain") /// .to_http_request(); /// /// let resp = index(req).await.unwrap(); @@ -389,15 +389,6 @@ impl TestRequest { TestRequest::default().uri(path) } - /// Create TestRequest and set header - pub fn with_header(header: H) -> TestRequest - where - H: IntoHeaderPair, - H::Error: Into, - { - TestRequest::default().header(header) - } - /// Create TestRequest and set method to `Method::GET` pub fn get() -> TestRequest { TestRequest::default().method(Method::GET) @@ -441,17 +432,25 @@ impl TestRequest { self } - /// Set a header - pub fn header(mut self, header: H) -> Self + /// Insert a header, replacing any that were set with an equivalent field name. + pub fn insert_header(mut self, header: H) -> Self where H: IntoHeaderPair, - H::Error: Into, { - self.req.header(header); + self.req.insert_header(header); self } - /// Set cookie for this request + /// Append a header, keeping any that were set with an equivalent field name. + pub fn append_header(mut self, header: H) -> Self + where + H: IntoHeaderPair, + { + self.req.insert_header(header); + self + } + + /// Set cookie for this request. pub fn cookie(mut self, cookie: Cookie<'_>) -> Self { self.req.cookie(cookie); self @@ -481,7 +480,7 @@ impl TestRequest { let bytes = serde_urlencoded::to_string(data) .expect("Failed to serialize test data as a urlencoded form"); self.req.set_payload(bytes); - self.req.header(ContentType::form_url_encoded()); + self.req.insert_header(ContentType::form_url_encoded()); self } @@ -491,7 +490,7 @@ impl TestRequest { let bytes = serde_json::to_string(data).expect("Failed to serialize test data to json"); self.req.set_payload(bytes); - self.req.header(ContentType::json()); + self.req.insert_header(ContentType::json()); self } @@ -1016,9 +1015,10 @@ mod tests { #[actix_rt::test] async fn test_basics() { - let req = TestRequest::with_hdr(header::ContentType::json()) + let req = TestRequest::default() .version(Version::HTTP_2) - .set(header::Date(SystemTime::now().into())) + .insert_header(header::ContentType::json()) + .insert_header(header::Date(SystemTime::now().into())) .param("test", "123") .data(10u32) .app_data(20u64) @@ -1055,7 +1055,7 @@ mod tests { let put_req = TestRequest::put() .uri("/index.html") - .header(header::CONTENT_TYPE, "application/json") + .insert_header((header::CONTENT_TYPE, "application/json")) .to_request(); let result = read_response(&mut app, put_req).await; @@ -1063,7 +1063,7 @@ mod tests { let patch_req = TestRequest::patch() .uri("/index.html") - .header(header::CONTENT_TYPE, "application/json") + .insert_header((header::CONTENT_TYPE, "application/json")) .to_request(); let result = read_response(&mut app, patch_req).await; @@ -1086,7 +1086,7 @@ mod tests { let req = TestRequest::post() .uri("/index.html") - .header(header::CONTENT_TYPE, "application/json") + .insert_header((header::CONTENT_TYPE, "application/json")) .to_request(); let result = read_response(&mut app, req).await; @@ -1131,7 +1131,7 @@ mod tests { let req = TestRequest::post() .uri("/people") - .header(header::CONTENT_TYPE, "application/json") + .insert_header((header::CONTENT_TYPE, "application/json")) .set_payload(payload) .to_request(); @@ -1152,7 +1152,7 @@ mod tests { let resp = TestRequest::post() .uri("/people") - .header(header::CONTENT_TYPE, "application/json") + .insert_header((header::CONTENT_TYPE, "application/json")) .set_payload(payload) .send_request(&mut app) .await; diff --git a/src/types/form.rs b/src/types/form.rs index 71680b19a..96e09ee1c 100644 --- a/src/types/form.rs +++ b/src/types/form.rs @@ -381,11 +381,11 @@ mod tests { #[actix_rt::test] async fn test_form() { - let (req, mut pl) = - TestRequest::with_header(CONTENT_TYPE, "application/x-www-form-urlencoded") - .header(CONTENT_LENGTH, "11") - .set_payload(Bytes::from_static(b"hello=world&counter=123")) - .to_http_parts(); + let (req, mut pl) = TestRequest::default() + .insert_header((CONTENT_TYPE, "application/x-www-form-urlencoded")) + .insert_header((CONTENT_LENGTH, 11)) + .set_payload(Bytes::from_static(b"hello=world&counter=123")) + .to_http_parts(); let Form(s) = Form::::from_request(&req, &mut pl).await.unwrap(); assert_eq!( @@ -414,25 +414,26 @@ mod tests { #[actix_rt::test] async fn test_urlencoded_error() { - let (req, mut pl) = - TestRequest::with_header(CONTENT_TYPE, "application/x-www-form-urlencoded") - .header(CONTENT_LENGTH, "xxxx") - .to_http_parts(); + let (req, mut pl) = TestRequest::default() + .insert_header((CONTENT_TYPE, "application/x-www-form-urlencoded")) + .insert_header((CONTENT_LENGTH, "xxxx")) + .to_http_parts(); let info = UrlEncoded::::new(&req, &mut pl).await; assert!(eq(info.err().unwrap(), UrlencodedError::UnknownLength)); - let (req, mut pl) = - TestRequest::with_header(CONTENT_TYPE, "application/x-www-form-urlencoded") - .header(CONTENT_LENGTH, "1000000") - .to_http_parts(); + let (req, mut pl) = TestRequest::default() + .insert_header((CONTENT_TYPE, "application/x-www-form-urlencoded")) + .insert_header((CONTENT_LENGTH, "1000000")) + .to_http_parts(); let info = UrlEncoded::::new(&req, &mut pl).await; assert!(eq( info.err().unwrap(), UrlencodedError::Overflow { size: 0, limit: 0 } )); - let (req, mut pl) = TestRequest::with_header(CONTENT_TYPE, "text/plain") - .header(CONTENT_LENGTH, "10") + let (req, mut pl) = TestRequest::default() + .insert_header((CONTENT_TYPE, "text/plain")) + .insert_header((CONTENT_LENGTH, 10)) .to_http_parts(); let info = UrlEncoded::::new(&req, &mut pl).await; assert!(eq(info.err().unwrap(), UrlencodedError::ContentType)); @@ -440,11 +441,11 @@ mod tests { #[actix_rt::test] async fn test_urlencoded() { - let (req, mut pl) = - TestRequest::with_header(CONTENT_TYPE, "application/x-www-form-urlencoded") - .header(CONTENT_LENGTH, "11") - .set_payload(Bytes::from_static(b"hello=world&counter=123")) - .to_http_parts(); + let (req, mut pl) = TestRequest::default() + .insert_header((CONTENT_TYPE, "application/x-www-form-urlencoded")) + .insert_header((CONTENT_LENGTH, 11)) + .set_payload(Bytes::from_static(b"hello=world&counter=123")) + .to_http_parts(); let info = UrlEncoded::::new(&req, &mut pl).await.unwrap(); assert_eq!( @@ -455,13 +456,14 @@ mod tests { } ); - let (req, mut pl) = TestRequest::with_header( - CONTENT_TYPE, - "application/x-www-form-urlencoded; charset=utf-8", - ) - .header(CONTENT_LENGTH, "11") - .set_payload(Bytes::from_static(b"hello=world&counter=123")) - .to_http_parts(); + let (req, mut pl) = TestRequest::default() + .insert_header(( + CONTENT_TYPE, + "application/x-www-form-urlencoded; charset=utf-8", + )) + .insert_header((CONTENT_LENGTH, 11)) + .set_payload(Bytes::from_static(b"hello=world&counter=123")) + .to_http_parts(); let info = UrlEncoded::::new(&req, &mut pl).await.unwrap(); assert_eq!( @@ -497,8 +499,8 @@ mod tests { let ctype = HeaderValue::from_static("application/x-www-form-urlencoded"); let (req, mut pl) = TestRequest::default() - .header(CONTENT_TYPE, ctype) - .header(CONTENT_LENGTH, HeaderValue::from_static("20")) + .insert_header((CONTENT_TYPE, ctype)) + .insert_header((CONTENT_LENGTH, HeaderValue::from_static("20"))) .set_payload(Bytes::from_static(b"hello=test&counter=4")) .app_data(web::Data::new(FormConfig::default().limit(10))) .to_http_parts(); diff --git a/src/types/json.rs b/src/types/json.rs index edfb775f3..7b94f66f6 100644 --- a/src/types/json.rs +++ b/src/types/json.rs @@ -427,7 +427,7 @@ mod tests { use crate::{ error::InternalError, http::{ - header::{self, HeaderValue, CONTENT_LENGTH, CONTENT_TYPE}, + header::{self, CONTENT_LENGTH, CONTENT_TYPE}, StatusCode, }, test::{load_stream, TestRequest}, @@ -469,14 +469,14 @@ mod tests { #[actix_rt::test] async fn test_custom_error_responder() { let (req, mut pl) = TestRequest::default() - .header( + .insert_header(( header::CONTENT_TYPE, header::HeaderValue::from_static("application/json"), - ) - .header( + )) + .insert_header(( header::CONTENT_LENGTH, header::HeaderValue::from_static("16"), - ) + )) .set_payload(Bytes::from_static(b"{\"name\": \"test\"}")) .app_data(JsonConfig::default().limit(10).error_handler(|err, _| { let msg = MyObject { @@ -500,14 +500,14 @@ mod tests { #[actix_rt::test] async fn test_extract() { let (req, mut pl) = TestRequest::default() - .header( + .insert_header(( header::CONTENT_TYPE, header::HeaderValue::from_static("application/json"), - ) - .header( + )) + .insert_header(( header::CONTENT_LENGTH, header::HeaderValue::from_static("16"), - ) + )) .set_payload(Bytes::from_static(b"{\"name\": \"test\"}")) .to_http_parts(); @@ -521,14 +521,14 @@ mod tests { ); let (req, mut pl) = TestRequest::default() - .header( + .insert_header(( header::CONTENT_TYPE, header::HeaderValue::from_static("application/json"), - ) - .header( + )) + .insert_header(( header::CONTENT_LENGTH, header::HeaderValue::from_static("16"), - ) + )) .set_payload(Bytes::from_static(b"{\"name\": \"test\"}")) .app_data(JsonConfig::default().limit(10)) .to_http_parts(); @@ -538,14 +538,14 @@ mod tests { .contains("Json payload size is bigger than allowed")); let (req, mut pl) = TestRequest::default() - .header( + .insert_header(( header::CONTENT_TYPE, header::HeaderValue::from_static("application/json"), - ) - .header( + )) + .insert_header(( header::CONTENT_LENGTH, header::HeaderValue::from_static("16"), - ) + )) .set_payload(Bytes::from_static(b"{\"name\": \"test\"}")) .app_data( JsonConfig::default() @@ -564,23 +564,23 @@ mod tests { assert!(json_eq(json.err().unwrap(), JsonPayloadError::ContentType)); let (req, mut pl) = TestRequest::default() - .header( + .insert_header(( header::CONTENT_TYPE, header::HeaderValue::from_static("application/text"), - ) + )) .to_http_parts(); let json = JsonBody::::new(&req, &mut pl, None).await; assert!(json_eq(json.err().unwrap(), JsonPayloadError::ContentType)); let (req, mut pl) = TestRequest::default() - .header( + .insert_header(( header::CONTENT_TYPE, header::HeaderValue::from_static("application/json"), - ) - .header( + )) + .insert_header(( header::CONTENT_LENGTH, header::HeaderValue::from_static("10000"), - ) + )) .to_http_parts(); let json = JsonBody::::new(&req, &mut pl, None) @@ -589,14 +589,14 @@ mod tests { assert!(json_eq(json.err().unwrap(), JsonPayloadError::Overflow)); let (req, mut pl) = TestRequest::default() - .header( + .insert_header(( header::CONTENT_TYPE, header::HeaderValue::from_static("application/json"), - ) - .header( + )) + .insert_header(( header::CONTENT_LENGTH, header::HeaderValue::from_static("16"), - ) + )) .set_payload(Bytes::from_static(b"{\"name\": \"test\"}")) .to_http_parts(); @@ -611,17 +611,18 @@ mod tests { #[actix_rt::test] async fn test_with_json_and_bad_content_type() { - let (req, mut pl) = TestRequest::with_header( - header::CONTENT_TYPE, - header::HeaderValue::from_static("text/plain"), - ) - .header( - header::CONTENT_LENGTH, - header::HeaderValue::from_static("16"), - ) - .set_payload(Bytes::from_static(b"{\"name\": \"test\"}")) - .app_data(JsonConfig::default().limit(4096)) - .to_http_parts(); + let (req, mut pl) = TestRequest::default() + .insert_header(( + header::CONTENT_TYPE, + header::HeaderValue::from_static("text/plain"), + )) + .insert_header(( + header::CONTENT_LENGTH, + header::HeaderValue::from_static("16"), + )) + .set_payload(Bytes::from_static(b"{\"name\": \"test\"}")) + .app_data(JsonConfig::default().limit(4096)) + .to_http_parts(); let s = Json::::from_request(&req, &mut pl).await; assert!(s.is_err()) @@ -629,19 +630,20 @@ mod tests { #[actix_rt::test] async fn test_with_json_and_good_custom_content_type() { - let (req, mut pl) = TestRequest::with_header( - header::CONTENT_TYPE, - header::HeaderValue::from_static("text/plain"), - ) - .header( - header::CONTENT_LENGTH, - header::HeaderValue::from_static("16"), - ) - .set_payload(Bytes::from_static(b"{\"name\": \"test\"}")) - .app_data(JsonConfig::default().content_type(|mime: mime::Mime| { - mime.type_() == mime::TEXT && mime.subtype() == mime::PLAIN - })) - .to_http_parts(); + let (req, mut pl) = TestRequest::default() + .insert_header(( + header::CONTENT_TYPE, + header::HeaderValue::from_static("text/plain"), + )) + .insert_header(( + header::CONTENT_LENGTH, + header::HeaderValue::from_static("16"), + )) + .set_payload(Bytes::from_static(b"{\"name\": \"test\"}")) + .app_data(JsonConfig::default().content_type(|mime: mime::Mime| { + mime.type_() == mime::TEXT && mime.subtype() == mime::PLAIN + })) + .to_http_parts(); let s = Json::::from_request(&req, &mut pl).await; assert!(s.is_ok()) @@ -649,19 +651,20 @@ mod tests { #[actix_rt::test] async fn test_with_json_and_bad_custom_content_type() { - let (req, mut pl) = TestRequest::with_header( - header::CONTENT_TYPE, - header::HeaderValue::from_static("text/html"), - ) - .header( - header::CONTENT_LENGTH, - header::HeaderValue::from_static("16"), - ) - .set_payload(Bytes::from_static(b"{\"name\": \"test\"}")) - .app_data(JsonConfig::default().content_type(|mime: mime::Mime| { - mime.type_() == mime::TEXT && mime.subtype() == mime::PLAIN - })) - .to_http_parts(); + let (req, mut pl) = TestRequest::default() + .insert_header(( + header::CONTENT_TYPE, + header::HeaderValue::from_static("text/html"), + )) + .insert_header(( + header::CONTENT_LENGTH, + header::HeaderValue::from_static("16"), + )) + .set_payload(Bytes::from_static(b"{\"name\": \"test\"}")) + .app_data(JsonConfig::default().content_type(|mime: mime::Mime| { + mime.type_() == mime::TEXT && mime.subtype() == mime::PLAIN + })) + .to_http_parts(); let s = Json::::from_request(&req, &mut pl).await; assert!(s.is_err()) @@ -670,8 +673,8 @@ mod tests { #[actix_rt::test] async fn test_with_config_in_data_wrapper() { let (req, mut pl) = TestRequest::default() - .header(CONTENT_TYPE, HeaderValue::from_static("application/json")) - .header(CONTENT_LENGTH, HeaderValue::from_static("16")) + .insert_header((CONTENT_TYPE, mime::APPLICATION_JSON)) + .insert_header((CONTENT_LENGTH, 16)) .set_payload(Bytes::from_static(b"{\"name\": \"test\"}")) .app_data(web::Data::new(JsonConfig::default().limit(10))) .to_http_parts(); diff --git a/src/types/payload.rs b/src/types/payload.rs index 22528031c..bee1b695a 100644 --- a/src/types/payload.rs +++ b/src/types/payload.rs @@ -364,14 +364,13 @@ mod tests { let cfg = PayloadConfig::default().mimetype(mime::APPLICATION_JSON); assert!(cfg.check_mimetype(&req).is_err()); - let req = TestRequest::with_header( - header::CONTENT_TYPE, - "application/x-www-form-urlencoded", - ) - .to_http_request(); + let req = TestRequest::default() + .insert_header((header::CONTENT_TYPE, "application/x-www-form-urlencoded")) + .to_http_request(); assert!(cfg.check_mimetype(&req).is_err()); - let req = TestRequest::with_header(header::CONTENT_TYPE, "application/json") + let req = TestRequest::default() + .insert_header((header::CONTENT_TYPE, "application/json")) .to_http_request(); assert!(cfg.check_mimetype(&req).is_ok()); } @@ -432,25 +431,25 @@ mod tests { assert_eq!(resp.status(), StatusCode::BAD_REQUEST); let req = TestRequest::with_uri("/bytes-app-data") - .header(header::CONTENT_TYPE, mime::APPLICATION_JSON) + .insert_header(header::ContentType(mime::APPLICATION_JSON)) .to_request(); let resp = call_service(&mut srv, req).await; assert_eq!(resp.status(), StatusCode::OK); let req = TestRequest::with_uri("/bytes-data") - .header(header::CONTENT_TYPE, mime::APPLICATION_JSON) + .insert_header(header::ContentType(mime::APPLICATION_JSON)) .to_request(); let resp = call_service(&mut srv, req).await; assert_eq!(resp.status(), StatusCode::OK); let req = TestRequest::with_uri("/string-app-data") - .header(header::CONTENT_TYPE, mime::APPLICATION_JSON) + .insert_header(header::ContentType(mime::APPLICATION_JSON)) .to_request(); let resp = call_service(&mut srv, req).await; assert_eq!(resp.status(), StatusCode::OK); let req = TestRequest::with_uri("/string-data") - .header(header::CONTENT_TYPE, mime::APPLICATION_JSON) + .insert_header(header::ContentType(mime::APPLICATION_JSON)) .to_request(); let resp = call_service(&mut srv, req).await; assert_eq!(resp.status(), StatusCode::OK); @@ -458,7 +457,8 @@ mod tests { #[actix_rt::test] async fn test_bytes() { - let (req, mut pl) = TestRequest::with_header(header::CONTENT_LENGTH, "11") + let (req, mut pl) = TestRequest::default() + .insert_header((header::CONTENT_LENGTH, "11")) .set_payload(Bytes::from_static(b"hello=world")) .to_http_parts(); @@ -468,7 +468,8 @@ mod tests { #[actix_rt::test] async fn test_string() { - let (req, mut pl) = TestRequest::with_header(header::CONTENT_LENGTH, "11") + let (req, mut pl) = TestRequest::default() + .insert_header((header::CONTENT_LENGTH, "11")) .set_payload(Bytes::from_static(b"hello=world")) .to_http_parts(); @@ -478,7 +479,8 @@ mod tests { #[actix_rt::test] async fn test_message_body() { - let (req, mut pl) = TestRequest::with_header(header::CONTENT_LENGTH, "xxxx") + let (req, mut pl) = TestRequest::default() + .insert_header((header::CONTENT_LENGTH, "xxxx")) .to_srv_request() .into_parts(); let res = HttpMessageBody::new(&req, &mut pl).await; @@ -487,7 +489,8 @@ mod tests { _ => unreachable!("error"), } - let (req, mut pl) = TestRequest::with_header(header::CONTENT_LENGTH, "1000000") + let (req, mut pl) = TestRequest::default() + .insert_header((header::CONTENT_LENGTH, "1000000")) .to_srv_request() .into_parts(); let res = HttpMessageBody::new(&req, &mut pl).await; diff --git a/tests/test_server.rs b/tests/test_server.rs index 43ee1230d..6d679005d 100644 --- a/tests/test_server.rs +++ b/tests/test_server.rs @@ -108,7 +108,7 @@ async fn test_body_gzip() { let mut response = srv .get("/") .no_decompress() - .header(ACCEPT_ENCODING, "gzip") + .append_header((ACCEPT_ENCODING, "gzip")) .send() .await .unwrap(); @@ -137,7 +137,7 @@ async fn test_body_gzip2() { let mut response = srv .get("/") .no_decompress() - .header(ACCEPT_ENCODING, "gzip") + .append_header((ACCEPT_ENCODING, "gzip")) .send() .await .unwrap(); @@ -178,7 +178,7 @@ async fn test_body_encoding_override() { let mut response = srv .get("/") .no_decompress() - .header(ACCEPT_ENCODING, "deflate") + .append_header((ACCEPT_ENCODING, "deflate")) .send() .await .unwrap(); @@ -197,7 +197,7 @@ async fn test_body_encoding_override() { let mut response = srv .request(actix_web::http::Method::GET, srv.url("/raw")) .no_decompress() - .header(ACCEPT_ENCODING, "deflate") + .append_header((ACCEPT_ENCODING, "deflate")) .send() .await .unwrap(); @@ -231,7 +231,7 @@ async fn test_body_gzip_large() { let mut response = srv .get("/") .no_decompress() - .header(ACCEPT_ENCODING, "gzip") + .append_header((ACCEPT_ENCODING, "gzip")) .send() .await .unwrap(); @@ -269,7 +269,7 @@ async fn test_body_gzip_large_random() { let mut response = srv .get("/") .no_decompress() - .header(ACCEPT_ENCODING, "gzip") + .append_header((ACCEPT_ENCODING, "gzip")) .send() .await .unwrap(); @@ -300,7 +300,7 @@ async fn test_body_chunked_implicit() { let mut response = srv .get("/") .no_decompress() - .header(ACCEPT_ENCODING, "gzip") + .append_header((ACCEPT_ENCODING, "gzip")) .send() .await .unwrap(); @@ -333,7 +333,7 @@ async fn test_body_br_streaming() { let mut response = srv .get("/") - .header(ACCEPT_ENCODING, "br") + .append_header((ACCEPT_ENCODING, "br")) .no_decompress() .send() .await @@ -406,7 +406,7 @@ async fn test_body_deflate() { // client request let mut response = srv .get("/") - .header(ACCEPT_ENCODING, "deflate") + .append_header((ACCEPT_ENCODING, "deflate")) .no_decompress() .send() .await @@ -433,7 +433,7 @@ async fn test_body_brotli() { // client request let mut response = srv .get("/") - .header(ACCEPT_ENCODING, "br") + .append_header((ACCEPT_ENCODING, "br")) .no_decompress() .send() .await @@ -466,7 +466,7 @@ async fn test_encoding() { let request = srv .post("/") - .header(CONTENT_ENCODING, "gzip") + .insert_header((CONTENT_ENCODING, "gzip")) .send_body(enc.clone()); let mut response = request.await.unwrap(); assert!(response.status().is_success()); @@ -492,7 +492,7 @@ async fn test_gzip_encoding() { let request = srv .post("/") - .header(CONTENT_ENCODING, "gzip") + .append_header((CONTENT_ENCODING, "gzip")) .send_body(enc.clone()); let mut response = request.await.unwrap(); assert!(response.status().is_success()); @@ -519,7 +519,7 @@ async fn test_gzip_encoding_large() { let request = srv .post("/") - .header(CONTENT_ENCODING, "gzip") + .append_header((CONTENT_ENCODING, "gzip")) .send_body(enc.clone()); let mut response = request.await.unwrap(); assert!(response.status().is_success()); @@ -551,7 +551,7 @@ async fn test_reading_gzip_encoding_large_random() { let request = srv .post("/") - .header(CONTENT_ENCODING, "gzip") + .append_header((CONTENT_ENCODING, "gzip")) .send_body(enc.clone()); let mut response = request.await.unwrap(); assert!(response.status().is_success()); @@ -578,7 +578,7 @@ async fn test_reading_deflate_encoding() { // client request let request = srv .post("/") - .header(CONTENT_ENCODING, "deflate") + .append_header((CONTENT_ENCODING, "deflate")) .send_body(enc.clone()); let mut response = request.await.unwrap(); assert!(response.status().is_success()); @@ -605,7 +605,7 @@ async fn test_reading_deflate_encoding_large() { // client request let request = srv .post("/") - .header(CONTENT_ENCODING, "deflate") + .append_header((CONTENT_ENCODING, "deflate")) .send_body(enc.clone()); let mut response = request.await.unwrap(); assert!(response.status().is_success()); @@ -637,7 +637,7 @@ async fn test_reading_deflate_encoding_large_random() { // client request let request = srv .post("/") - .header(CONTENT_ENCODING, "deflate") + .append_header((CONTENT_ENCODING, "deflate")) .send_body(enc.clone()); let mut response = request.await.unwrap(); assert!(response.status().is_success()); @@ -664,7 +664,7 @@ async fn test_brotli_encoding() { // client request let request = srv .post("/") - .header(CONTENT_ENCODING, "br") + .append_header((CONTENT_ENCODING, "br")) .send_body(enc.clone()); let mut response = request.await.unwrap(); assert!(response.status().is_success()); @@ -699,7 +699,7 @@ async fn test_brotli_encoding_large() { // client request let request = srv .post("/") - .header(CONTENT_ENCODING, "br") + .append_header((CONTENT_ENCODING, "br")) .send_body(enc.clone()); let mut response = request.await.unwrap(); assert!(response.status().is_success()); @@ -739,7 +739,7 @@ async fn test_brotli_encoding_large_openssl() { // client request let mut response = srv .post("/") - .header(actix_web::http::header::CONTENT_ENCODING, "br") + .append_header((actix_web::http::header::CONTENT_ENCODING, "br")) .send_body(enc) .await .unwrap();