From 6f714f438a4978afc1811f7c599315681cc8f205 Mon Sep 17 00:00:00 2001 From: nickelc Date: Fri, 13 Jan 2023 20:14:55 +0100 Subject: [PATCH] Unify basic-auth header generation (#1726) --- src/async_impl/request.rs | 13 +------------ src/blocking/request.rs | 9 ++------- src/proxy.rs | 8 +------- src/util.rs | 29 ++++++++++++++++------------- src/wasm/request.rs | 13 +------------ 5 files changed, 21 insertions(+), 51 deletions(-) diff --git a/src/async_impl/request.rs b/src/async_impl/request.rs index 1522c1467..914ff13ab 100644 --- a/src/async_impl/request.rs +++ b/src/async_impl/request.rs @@ -1,7 +1,6 @@ use std::convert::TryFrom; use std::fmt; use std::future::Future; -use std::io::Write; use std::time::Duration; use serde::Serialize; @@ -16,7 +15,6 @@ use super::response::Response; #[cfg(feature = "multipart")] use crate::header::CONTENT_LENGTH; use crate::header::{HeaderMap, HeaderName, HeaderValue, CONTENT_TYPE}; -use crate::util::base64; use crate::{Method, Url}; use http::{request::Parts, Request as HttpRequest, Version}; @@ -251,16 +249,7 @@ impl RequestBuilder { U: fmt::Display, P: fmt::Display, { - let mut header_value = b"Basic ".to_vec(); - { - let mut encoder = base64::encoder(&mut header_value); - // The unwraps here are fine because Vec::write* is infallible. - write!(encoder, "{}:", username).unwrap(); - if let Some(password) = password { - write!(encoder, "{}", password).unwrap(); - } - } - + let header_value = crate::util::basic_auth(username, password); self.header_sensitive(crate::header::AUTHORIZATION, header_value, true) } diff --git a/src/blocking/request.rs b/src/blocking/request.rs index 4ac4a4b92..6dd7935e7 100644 --- a/src/blocking/request.rs +++ b/src/blocking/request.rs @@ -13,7 +13,6 @@ use super::body::{self, Body}; use super::multipart; use super::Client; use crate::header::{HeaderMap, HeaderName, HeaderValue, CONTENT_TYPE}; -use crate::util::base64; use crate::{async_impl, Method, Url}; /// A request which can be executed with `Client::execute()`. @@ -266,12 +265,8 @@ impl RequestBuilder { U: fmt::Display, P: fmt::Display, { - let auth = match password { - Some(password) => format!("{}:{}", username, password), - None => format!("{}:", username), - }; - let header_value = format!("Basic {}", base64::encode(&auth)); - self.header_sensitive(crate::header::AUTHORIZATION, &*header_value, true) + let header_value = crate::util::basic_auth(username, password); + self.header_sensitive(crate::header::AUTHORIZATION, header_value, true) } /// Enable HTTP bearer authentication. diff --git a/src/proxy.rs b/src/proxy.rs index ee2447f4e..d2d434ee3 100644 --- a/src/proxy.rs +++ b/src/proxy.rs @@ -4,7 +4,6 @@ use std::net::SocketAddr; use std::sync::Arc; use crate::into_url::{IntoUrl, IntoUrlSealed}; -use crate::util::base64; use crate::Url; use http::{header::HeaderValue, Uri}; use ipnet::IpNet; @@ -763,12 +762,7 @@ impl fmt::Debug for Custom { } pub(crate) fn encode_basic_auth(username: &str, password: &str) -> HeaderValue { - let val = format!("{}:{}", username, password); - let mut header = format!("Basic {}", base64::encode(&val)) - .parse::() - .expect("base64 is always valid HeaderValue"); - header.set_sensitive(true); - header + crate::util::basic_auth(username, Some(password)) } /// A helper trait to allow testing `Proxy::intercept` without having to diff --git a/src/util.rs b/src/util.rs index c30a15b6e..018db307f 100644 --- a/src/util.rs +++ b/src/util.rs @@ -1,22 +1,25 @@ -use crate::header::{Entry, HeaderMap, OccupiedEntry}; +use crate::header::{Entry, HeaderMap, HeaderValue, OccupiedEntry}; -pub(crate) mod base64 { - use std::io; - - use base64::engine::GeneralPurpose; +pub fn basic_auth(username: U, password: Option

) -> HeaderValue +where + U: std::fmt::Display, + P: std::fmt::Display, +{ use base64::prelude::BASE64_STANDARD; use base64::write::EncoderWriter; + use std::io::Write; - if_hyper! { - pub fn encode>(input: T) -> String { - use base64::Engine; - BASE64_STANDARD.encode(input) + let mut buf = b"Basic ".to_vec(); + { + let mut encoder = EncoderWriter::new(&mut buf, &BASE64_STANDARD); + let _ = write!(encoder, "{}:", username); + if let Some(password) = password { + let _ = write!(encoder, "{}", password); } } - - pub fn encoder<'a, W: io::Write>(delegate: W) -> EncoderWriter<'a, GeneralPurpose, W> { - EncoderWriter::new(delegate, &BASE64_STANDARD) - } + let mut header = HeaderValue::from_bytes(&buf).expect("base64 is always valid HeaderValue"); + header.set_sensitive(true); + header } // xor-shift diff --git a/src/wasm/request.rs b/src/wasm/request.rs index 46f4d13f8..2b0a6bec7 100644 --- a/src/wasm/request.rs +++ b/src/wasm/request.rs @@ -1,6 +1,5 @@ use std::convert::TryFrom; use std::fmt; -use std::io::Write; use bytes::Bytes; use http::{request::Parts, Method, Request as HttpRequest}; @@ -12,7 +11,6 @@ use web_sys::RequestCredentials; use super::{Body, Client, Response}; use crate::header::{HeaderMap, HeaderName, HeaderValue, CONTENT_TYPE}; -use crate::util::base64; /// A request which can be executed with `Client::execute()`. pub struct Request { @@ -214,16 +212,7 @@ impl RequestBuilder { U: fmt::Display, P: fmt::Display, { - let mut header_value = b"Basic ".to_vec(); - { - let mut encoder = base64::encoder(&mut header_value); - // The unwraps here are fine because Vec::write* is infallible. - write!(encoder, "{}:", username).unwrap(); - if let Some(password) = password { - write!(encoder, "{}", password).unwrap(); - } - } - + let header_value = crate::util::basic_auth(username, password); self.header(crate::header::AUTHORIZATION, header_value) }