diff --git a/actix-http/src/client/h2proto.rs b/actix-http/src/client/h2proto.rs index 0deb5c014..7292972de 100644 --- a/actix-http/src/client/h2proto.rs +++ b/actix-http/src/client/h2proto.rs @@ -1,4 +1,3 @@ -use std::convert::TryFrom; use std::future::Future; use std::time; @@ -61,10 +60,14 @@ where BodySize::Empty => req .headers_mut() .insert(CONTENT_LENGTH, HeaderValue::from_static("0")), - BodySize::Sized(len) => req.headers_mut().insert( - CONTENT_LENGTH, - HeaderValue::try_from(format!("{}", len)).unwrap(), - ), + BodySize::Sized(len) => { + let mut buf = itoa::Buffer::new(); + + req.headers_mut().insert( + CONTENT_LENGTH, + HeaderValue::from_str(buf.format(len)).unwrap(), + ) + } }; // Extracting extra headers from RequestHeadType. HeaderMap::new() does not allocate. @@ -87,7 +90,10 @@ where // copy headers for (key, value) in headers { match *key { - CONNECTION | TRANSFER_ENCODING => continue, // http2 specific + // TODO: consider skipping other headers according to: + // https://tools.ietf.org/html/rfc7540#section-8.1.2.2 + // omit HTTP/1.x only headers + CONNECTION | TRANSFER_ENCODING => continue, CONTENT_LENGTH if skip_len => continue, // DATE => has_date = true, _ => {} diff --git a/actix-http/src/h1/encoder.rs b/actix-http/src/h1/encoder.rs index 97916e7db..60062d559 100644 --- a/actix-http/src/h1/encoder.rs +++ b/actix-http/src/h1/encoder.rs @@ -633,9 +633,9 @@ mod tests { let mut res: Response<()> = Response::new(StatusCode::SWITCHING_PROTOCOLS).into_body::<()>(); res.headers_mut() - .insert(DATE, HeaderValue::from_static(&"")); + .insert(DATE, HeaderValue::from_static("")); res.headers_mut() - .insert(CONTENT_LENGTH, HeaderValue::from_static(&"0")); + .insert(CONTENT_LENGTH, HeaderValue::from_static("0")); let _ = res.encode_headers( &mut bytes, diff --git a/actix-http/src/h2/dispatcher.rs b/actix-http/src/h2/dispatcher.rs index 5ccd2a9d1..003a7034e 100644 --- a/actix-http/src/h2/dispatcher.rs +++ b/actix-http/src/h2/dispatcher.rs @@ -125,7 +125,7 @@ where let pl = Payload::::H2(pl); let mut req = Request::with_payload(pl); - let head = &mut req.head_mut(); + let head = req.head_mut(); head.uri = parts.uri; head.method = parts.method; head.version = parts.version; @@ -203,16 +203,22 @@ where BodySize::Empty => res .headers_mut() .insert(CONTENT_LENGTH, HeaderValue::from_static("0")), - BodySize::Sized(len) => res.headers_mut().insert( - CONTENT_LENGTH, - HeaderValue::try_from(format!("{}", len)).unwrap(), - ), + BodySize::Sized(len) => { + let mut buf = itoa::Buffer::new(); + + res.headers_mut().insert( + CONTENT_LENGTH, + HeaderValue::from_str(buf.format(len)).unwrap(), + ) + } }; // copy headers for (key, value) in head.headers.iter() { match *key { - // omit HTTP/1 only headers + // TODO: consider skipping other headers according to: + // https://tools.ietf.org/html/rfc7540#section-8.1.2.2 + // omit HTTP/1.x only headers CONNECTION | TRANSFER_ENCODING => continue, CONTENT_LENGTH if skip_len => continue, DATE => has_date = true, diff --git a/actix-http/src/response.rs b/actix-http/src/response.rs index f96f8f9b6..c5a4aec13 100644 --- a/actix-http/src/response.rs +++ b/actix-http/src/response.rs @@ -498,7 +498,8 @@ impl ResponseBuilder { /// Disable chunked transfer encoding for HTTP/1.1 streaming responses. #[inline] pub fn no_chunking(&mut self, len: u64) -> &mut Self { - self.insert_header((header::CONTENT_LENGTH, len)); + let mut buf = itoa::Buffer::new(); + self.insert_header((header::CONTENT_LENGTH, buf.format(len))); if let Some(parts) = parts(&mut self.head, &self.err) { parts.no_chunking(true); diff --git a/awc/src/request.rs b/awc/src/request.rs index 812c0e805..c39e0b4cd 100644 --- a/awc/src/request.rs +++ b/awc/src/request.rs @@ -248,29 +248,28 @@ impl ClientRequest { /// Set content length #[inline] pub fn content_length(self, len: u64) -> Self { - self.append_header((header::CONTENT_LENGTH, len)) + let mut buf = itoa::Buffer::new(); + self.insert_header((header::CONTENT_LENGTH, buf.format(len))) } /// Set HTTP basic authorization header - pub fn basic_auth(self, username: U, password: Option<&str>) -> Self - where - U: fmt::Display, - { + pub fn basic_auth( + self, + username: impl fmt::Display, + password: Option, + ) -> Self { let auth = match password { Some(password) => format!("{}:{}", username, password), None => format!("{}:", username), }; - self.append_header(( + self.insert_header(( header::AUTHORIZATION, format!("Basic {}", base64::encode(&auth)), )) } /// Set HTTP bearer authentication header - pub fn bearer_auth(self, token: T) -> Self - where - T: fmt::Display, - { + pub fn insert_auth(self, token: impl fmt::Display) -> Self { self.append_header((header::AUTHORIZATION, format!("Bearer {}", token))) }