From 68b64b0ca6bfefb6d841a9f1b69bdea98fb4b766 Mon Sep 17 00:00:00 2001 From: Richard Whitehouse Date: Thu, 12 Dec 2019 13:21:38 +0000 Subject: [PATCH 1/4] Handle Hyper 0.11's Headers implementation In Hyper 0.11, the following code will panic: use hyper::header::{Authorization, Basic, Bearer, Headers}; fn main() { let mut headers = Headers::default(); let basic = Basic { username: "richard".to_string(), password: None }; headers.set::>(Authorization(basic)); println!("Auth: {:?}", headers.get::>()); } This is because `std::any::TypeId::of>` and `std::any::TypeId::of>` don't match, but the header name, `Authorization` does. We provide a `.safe_get::>` to workaround this issue. Signed-off-by: Richard Whitehouse --- src/headers.rs | 39 +++++++++++++++++++++++++++++++++++++++ src/lib.rs | 2 ++ 2 files changed, 41 insertions(+) create mode 100644 src/headers.rs diff --git a/src/headers.rs b/src/headers.rs new file mode 100644 index 0000000000..306585565e --- /dev/null +++ b/src/headers.rs @@ -0,0 +1,39 @@ +//! Support library for handling headers in a safe manner + +use hyper::header::{Header, Headers}; + +/// Trait to add a mechanism to safely retrieve a header. +/// +/// In Hyper 0.11, if you add an Authorization header, +/// and then attempt get an Authorization header, the code +/// will panic, as the type ID doesn't match. +pub trait SafeHeaders { + /// Safely get a header from a hyper::header::Headers + fn safe_get(&self) -> Option; +} + +impl SafeHeaders for Headers { + fn safe_get(&self) -> Option { + self.get_raw(H::header_name()) + .map(H::parse_header) + .map(Result::ok) + .unwrap_or(None) + } +} + +#[cfg(test)] +mod tests { + use super::*; + use hyper::header::{Authorization, Bearer, Basic}; + + #[test] + fn test() { + let mut headers = Headers::default(); + let basic = Basic { + username: "richard".to_string(), + password: None, + }; + headers.set::>(Authorization(basic)); + println!("Auth: {:?}", headers.safe_get::>()); + } +} diff --git a/src/lib.rs b/src/lib.rs index 16b8e56dd0..77cb0fd814 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -53,6 +53,8 @@ pub use drop_context::DropContext; pub mod request_parser; pub use request_parser::RequestParser; +pub mod headers; + header! { /// `X-Span-ID` header, used to track a request through a chain of microservices. (XSpanId, "X-Span-ID") => [String] From 6cc988146a3a66380c83b67b5a48cba9da608b75 Mon Sep 17 00:00:00 2001 From: Richard Whitehouse Date: Thu, 12 Dec 2019 13:36:14 +0000 Subject: [PATCH 2/4] Fix warnings in Rust 1.39 Signed-off-by: Richard Whitehouse --- src/base64_format.rs | 2 +- src/composites.rs | 8 ++++---- src/connector.rs | 10 +++++----- src/context.rs | 8 ++++---- src/lib.rs | 2 +- 5 files changed, 15 insertions(+), 15 deletions(-) diff --git a/src/base64_format.rs b/src/base64_format.rs index b00f1e875a..df4ee4e6ef 100644 --- a/src/base64_format.rs +++ b/src/base64_format.rs @@ -29,7 +29,7 @@ impl<'de> Deserialize<'de> for ByteArray { where D: Deserializer<'de>, { - let s = try!(String::deserialize(deserializer)); + let s = String::deserialize(deserializer)?; match decode(&s) { Ok(bin) => Ok(ByteArray(bin)), _ => Err(D::Error::custom("invalid base64")), diff --git a/src/composites.rs b/src/composites.rs index a32bf9981a..7b9582727c 100644 --- a/src/composites.rs +++ b/src/composites.rs @@ -41,10 +41,10 @@ impl NotFound for Response { } } -type BoxedFuture = Box>; -type CompositeNewServiceVec = Vec<(&'static str, Box>)>; +type BoxedFuture = Box>; +type CompositeNewServiceVec = Vec<(&'static str, Box>)>; type BoxedService = - Box>>; + Box>>; /// Trait for wrapping hyper `NewService`s to make the return type of `new_service` uniform. /// This is necessary in order for the `NewService`s with different `Instance` types to @@ -185,7 +185,7 @@ where type Request = U; type Response = V; type Error = W; - type Future = Box>; + type Future = Box>; fn call(&self, req: Self::Request) -> Self::Future { let mut result = None; diff --git a/src/connector.rs b/src/connector.rs index 968803079e..c1e901b3e7 100644 --- a/src/connector.rs +++ b/src/connector.rs @@ -13,7 +13,7 @@ use hyper; /// Returns a function which creates an http-connector. Used for instantiating /// clients with custom connectors -pub fn http_connector() -> Box hyper::client::HttpConnector + Send + Sync> { +pub fn http_connector() -> Box hyper::client::HttpConnector + Send + Sync> { Box::new(move |handle: &Handle| hyper::client::HttpConnector::new(4, handle)) } @@ -25,7 +25,7 @@ pub fn http_connector() -> Box hyper::client::HttpConnector + Sen #[cfg(not(any(target_os = "macos", target_os = "windows", target_os = "ios")))] pub fn https_connector( ca_certificate: CA, -) -> Box hyper_tls::HttpsConnector + Send + Sync> +) -> Box hyper_tls::HttpsConnector + Send + Sync> where CA: AsRef, { @@ -53,7 +53,7 @@ where #[cfg(any(target_os = "macos", target_os = "windows", target_os = "ios"))] pub fn https_connector( _ca_certificate: CA, -) -> Box hyper_tls::HttpsConnector + Send + Sync> +) -> Box hyper_tls::HttpsConnector + Send + Sync> where CA: AsRef, { @@ -71,7 +71,7 @@ pub fn https_mutual_connector( ca_certificate: CA, client_key: K, client_certificate: C, -) -> Box hyper_tls::HttpsConnector + Send + Sync> +) -> Box hyper_tls::HttpsConnector + Send + Sync> where CA: AsRef, K: AsRef, @@ -112,7 +112,7 @@ pub fn https_mutual_connector( _ca_certificate: CA, _client_key: K, _client_certificate: C, -) -> Box hyper_tls::HttpsConnector + Send + Sync> +) -> Box hyper_tls::HttpsConnector + Send + Sync> where CA: AsRef, K: AsRef, diff --git a/src/context.rs b/src/context.rs index 2c10be567a..b8faddee2c 100644 --- a/src/context.rs +++ b/src/context.rs @@ -38,7 +38,7 @@ use std::marker::Sized; /// type Request = (hyper::Request, C); /// type Response = hyper::Response; /// type Error = hyper::Error; -/// type Future = Box>; +/// type Future = Box>; /// fn call(&self, (req, context) : Self::Request) -> Self::Future { /// do_something_with_my_item(Has::::get(&context)); /// Box::new(ok(hyper::Response::new())) @@ -546,7 +546,7 @@ pub trait SwaggerService: Request = (hyper::server::Request, C), Response = hyper::server::Response, Error = hyper::Error, - Future = Box>, + Future = Box>, > where C: Has> + Has> + Has + Clone + 'static, @@ -560,7 +560,7 @@ where Request = (hyper::server::Request, C), Response = hyper::server::Response, Error = hyper::Error, - Future = Box>, + Future = Box>, >, C: Has> + Has> + Has + Clone + 'static, { @@ -603,7 +603,7 @@ mod context_tests { type Request = (Request, C); type Response = Response; type Error = Error; - type Future = Box>; + type Future = Box>; fn call(&self, (_, context): Self::Request) -> Self::Future { use_item_2(Has::::get(&context)); diff --git a/src/lib.rs b/src/lib.rs index 77cb0fd814..49e7a07ec0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -93,7 +93,7 @@ pub struct ApiError(pub String); impl fmt::Display for ApiError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let debug: &fmt::Debug = self; + let debug: &dyn fmt::Debug = self; debug.fmt(f) } } From 1b90891506884cbbb6ef3f202965b5f23285357e Mon Sep 17 00:00:00 2001 From: Richard Whitehouse Date: Thu, 12 Dec 2019 14:22:31 +0000 Subject: [PATCH 3/4] Fix formatting Signed-off-by: Richard Whitehouse --- src/headers.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/headers.rs b/src/headers.rs index 306585565e..e6348186b5 100644 --- a/src/headers.rs +++ b/src/headers.rs @@ -24,7 +24,7 @@ impl SafeHeaders for Headers { #[cfg(test)] mod tests { use super::*; - use hyper::header::{Authorization, Bearer, Basic}; + use hyper::header::{Authorization, Basic, Bearer}; #[test] fn test() { From ed5b6a9948121b86fee28d7ed051792c38613ff7 Mon Sep 17 00:00:00 2001 From: Richard Whitehouse Date: Thu, 12 Dec 2019 14:22:46 +0000 Subject: [PATCH 4/4] Update CHANGELOG Signed-off-by: Richard Whitehouse --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9f490a1798..6046a75754 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. ## [Unreleased] ### Added +- Add `SafeHeaders` to work around Hyper 0.11 panic handling differently type headers with the same name - e.g. Authorization +- Fix warnings present on Rust 1.39 ### Changed