diff --git a/core/codegen/tests/ui-fail-stable/responder-types.stderr b/core/codegen/tests/ui-fail-stable/responder-types.stderr index e728180758..614371f5f7 100644 --- a/core/codegen/tests/ui-fail-stable/responder-types.stderr +++ b/core/codegen/tests/ui-fail-stable/responder-types.stderr @@ -6,15 +6,18 @@ error[E0277]: the trait bound `u8: Responder<'_, '_>` is not satisfied | = note: required by `respond_to` -error[E0277]: the trait bound `Header<'_>: From` is not satisfied +error[E0277]: the trait bound `Header<'_>: std::convert::From` is not satisfied --> $DIR/responder-types.rs:11:5 | 11 | other: u8, - | ^^^^^ the trait `From` is not implemented for `Header<'_>` + | ^^^^^ the trait `std::convert::From` is not implemented for `Header<'_>` | = help: the following implementations were found: - as From<&Cookie<'_>>> - as From>> + as std::convert::From<&rocket::http::Cookie<'_>>> + as std::convert::From> + as std::convert::From> + as std::convert::From> + and 55 others = note: required because of the requirements on the impl of `Into>` for `u8` error[E0277]: the trait bound `u8: Responder<'_, '_>` is not satisfied @@ -25,26 +28,32 @@ error[E0277]: the trait bound `u8: Responder<'_, '_>` is not satisfied | = note: required by `respond_to` -error[E0277]: the trait bound `Header<'_>: From` is not satisfied +error[E0277]: the trait bound `Header<'_>: std::convert::From` is not satisfied --> $DIR/responder-types.rs:17:5 | 17 | other: u8, - | ^^^^^ the trait `From` is not implemented for `Header<'_>` + | ^^^^^ the trait `std::convert::From` is not implemented for `Header<'_>` | = help: the following implementations were found: - as From<&Cookie<'_>>> - as From>> + as std::convert::From<&rocket::http::Cookie<'_>>> + as std::convert::From> + as std::convert::From> + as std::convert::From> + and 55 others = note: required because of the requirements on the impl of `Into>` for `u8` -error[E0277]: the trait bound `Header<'_>: From` is not satisfied +error[E0277]: the trait bound `Header<'_>: std::convert::From` is not satisfied --> $DIR/responder-types.rs:24:5 | 24 | then: String, - | ^^^^ the trait `From` is not implemented for `Header<'_>` + | ^^^^ the trait `std::convert::From` is not implemented for `Header<'_>` | = help: the following implementations were found: - as From<&Cookie<'_>>> - as From>> + as std::convert::From<&rocket::http::Cookie<'_>>> + as std::convert::From> + as std::convert::From> + as std::convert::From> + and 55 others = note: required because of the requirements on the impl of `Into>` for `std::string::String` error[E0277]: the trait bound `usize: Responder<'_, '_>` is not satisfied diff --git a/core/http/Cargo.toml b/core/http/Cargo.toml index fad87ea4c5..3a816336a6 100644 --- a/core/http/Cargo.toml +++ b/core/http/Cargo.toml @@ -23,6 +23,7 @@ private-cookies = ["cookie/private", "cookie/key-expansion"] smallvec = "1.0" percent-encoding = "2" hyper = { version = "0.14", default-features = false, features = ["http1", "http2", "runtime", "server", "stream"] } +hyperx = { version = "1.3.0" } http = "0.2" mime = "0.3.13" time = "0.2.11" diff --git a/core/http/src/hyper.rs b/core/http/src/hyper.rs index cb007e8179..a137a07556 100644 --- a/core/http/src/hyper.rs +++ b/core/http/src/hyper.rs @@ -1,4 +1,4 @@ -//! Re-exported hyper HTTP library types. +//! Re-exported hyper HTTP library types and hyperx typed headers. //! //! All types that are re-exported from Hyper reside inside of this module. //! These types will, with certainty, be removed with time, but they reside here @@ -21,6 +21,9 @@ /// Reexported http header types. pub mod header { + use super::super::header::Header; + pub use hyperx::header::Header as HyperxHeaderTrait; + macro_rules! import_http_headers { ($($name:ident),*) => ($( pub use http::header::$name as $name; @@ -43,4 +46,89 @@ pub mod header { STRICT_TRANSPORT_SECURITY, TE, TRANSFER_ENCODING, UPGRADE, USER_AGENT, VARY } + + macro_rules! import_hyperx_items { + ($($item:ident),*) => ($(pub use hyperx::header::$item as $item;)*) + } + + macro_rules! import_hyperx_headers { + ($($name:ident),*) => ($( + impl ::std::convert::From for Header<'static> { + fn from(header: self::$name) -> Header<'static> { + Header::new($name::header_name(), header.to_string()) + } + } + )*) + } + + macro_rules! import_generic_hyperx_headers { + ($($name:ident<$bound:ident>),*) => ($( + impl ::std::convert::From> + for Header<'static> { + fn from(header: self::$name) -> Header<'static> { + Header::new($name::::header_name(), header.to_string()) + } + } + )*) + } + + import_hyperx_items! { + Accept, AcceptCharset, AcceptEncoding, AcceptLanguage, AcceptRanges, + AccessControlAllowCredentials, AccessControlAllowHeaders, + AccessControlAllowMethods, AccessControlAllowOrigin, + AccessControlExposeHeaders, AccessControlMaxAge, + AccessControlRequestHeaders, AccessControlRequestMethod, Allow, + Authorization, Basic, Bearer, ByteRangeSpec, CacheControl, + CacheDirective, Charset, Connection, ConnectionOption, + ContentDisposition, ContentEncoding, ContentLanguage, ContentLength, + ContentLocation, ContentRange, ContentRangeSpec, ContentType, Cookie, + Date, DispositionParam, DispositionType, Encoding, EntityTag, ETag, + Expect, Expires, From, Host, HttpDate, IfMatch, IfModifiedSince, + IfNoneMatch, IfRange, IfUnmodifiedSince, LastEventId, LastModified, + Link, LinkValue, Location, Origin, Pragma, Prefer, Preference, + PreferenceApplied, Protocol, ProtocolName, ProxyAuthorization, Quality, + QualityItem, Range, RangeUnit, Referer, ReferrerPolicy, RetryAfter, + Scheme, Server, SetCookie, StrictTransportSecurity, + Te, TransferEncoding, Upgrade, UserAgent, Vary, Warning, q, qitem + } + + import_hyperx_headers! { + Accept, AcceptCharset, AcceptEncoding, AcceptLanguage, AcceptRanges, + AccessControlAllowCredentials, AccessControlAllowHeaders, + AccessControlAllowMethods, AccessControlAllowOrigin, + AccessControlExposeHeaders, AccessControlMaxAge, + AccessControlRequestHeaders, AccessControlRequestMethod, Allow, + CacheControl, Connection, ContentDisposition, ContentEncoding, + ContentLanguage, ContentLength, ContentLocation, ContentRange, + ContentType, Cookie, Date, ETag, Expires, Expect, From, Host, IfMatch, + IfModifiedSince, IfNoneMatch, IfUnmodifiedSince, IfRange, LastEventId, + LastModified, Link, Location, Origin, Pragma, Prefer, PreferenceApplied, + Range, Referer, ReferrerPolicy, RetryAfter, Server, + StrictTransportSecurity, Te, TransferEncoding, Upgrade, UserAgent, Vary, + Warning + } + import_generic_hyperx_headers! { + Authorization, + ProxyAuthorization + } + // Note: SetCookie is missing, since it must be formatted as separate header lines... +} + +#[cfg(test)] +mod tests { + use super::header::{Accept, QualityItem, q, qitem}; + use crate::header::HeaderMap; + use super::header::HyperxHeaderTrait; // Needed for Accept::header_name() below?!?! + + #[test] + fn add_typed_header() { + + let mut map = HeaderMap::new(); + let header = Accept(vec![ + QualityItem::new("audio/*".parse().unwrap(), q(200)), + qitem("audio/basic".parse().unwrap()), + ]); + map.add(header); + assert_eq!(map.get_one(Accept::header_name()), Some("audio/*; q=0.2, audio/basic")); + } }