Skip to content

Implement the Header trait #315

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Feb 12, 2021
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 12 additions & 2 deletions src/auth/authorization.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::auth::AuthenticationScheme;
use crate::bail_status as bail;
use crate::headers::{HeaderName, HeaderValue, Headers, AUTHORIZATION};
use crate::headers::{Header, HeaderName, HeaderValue, Headers, AUTHORIZATION};

/// Credentials to authenticate a user agent with a server.
///
@@ -78,7 +78,7 @@ impl Authorization {

/// Get the `HeaderName`.
pub fn name(&self) -> HeaderName {
AUTHORIZATION
self.header_name()
}

/// Get the `HeaderValue`.
@@ -110,6 +110,16 @@ impl Authorization {
}
}

impl Header for Authorization {
fn header_name(&self) -> HeaderName {
AUTHORIZATION
}

fn header_value(&self) -> HeaderValue {
self.value()
}
}

#[cfg(test)]
mod test {
use super::*;
10 changes: 10 additions & 0 deletions src/auth/basic_auth.rs
Original file line number Diff line number Diff line change
@@ -113,6 +113,16 @@ impl BasicAuth {
}
}

impl crate::headers::Header for BasicAuth {
fn header_name(&self) -> HeaderName {
AUTHORIZATION
}

fn header_value(&self) -> HeaderValue {
self.value()
}
}

#[cfg(test)]
mod test {
use super::*;
10 changes: 10 additions & 0 deletions src/auth/www_authenticate.rs
Original file line number Diff line number Diff line change
@@ -132,6 +132,16 @@ impl WwwAuthenticate {
}
}

impl crate::headers::Header for WwwAuthenticate {
fn header_name(&self) -> HeaderName {
WWW_AUTHENTICATE
}

fn header_value(&self) -> HeaderValue {
self.value()
}
}

#[cfg(test)]
mod test {
use super::*;
10 changes: 10 additions & 0 deletions src/cache/age.rs
Original file line number Diff line number Diff line change
@@ -95,6 +95,16 @@ impl ToHeaderValues for Age {
}
}

impl crate::headers::Header for Age {
fn header_name(&self) -> HeaderName {
AGE
}

fn header_value(&self) -> HeaderValue {
self.value()
}
}

#[cfg(test)]
mod test {
use super::*;
9 changes: 9 additions & 0 deletions src/cache/cache_control/cache_control.rs
Original file line number Diff line number Diff line change
@@ -104,6 +104,15 @@ impl CacheControl {
}
}

impl crate::headers::Header for CacheControl {
fn header_name(&self) -> HeaderName {
CACHE_CONTROL
}
fn header_value(&self) -> HeaderValue {
self.value()
}
}

impl IntoIterator for CacheControl {
type Item = CacheDirective;
type IntoIter = IntoIter;
9 changes: 9 additions & 0 deletions src/cache/clear_site_data/mod.rs
Original file line number Diff line number Diff line change
@@ -249,6 +249,15 @@ impl Debug for ClearSiteData {
}
}

impl crate::headers::Header for ClearSiteData {
fn header_name(&self) -> HeaderName {
CLEAR_SITE_DATA
}
fn header_value(&self) -> HeaderValue {
self.value()
}
}

#[cfg(test)]
mod test {
use crate::cache::{ClearDirective, ClearSiteData};
9 changes: 9 additions & 0 deletions src/cache/expires.rs
Original file line number Diff line number Diff line change
@@ -90,6 +90,15 @@ impl Expires {
}
}

impl crate::headers::Header for Expires {
fn header_name(&self) -> HeaderName {
EXPIRES
}
fn header_value(&self) -> HeaderValue {
self.value()
}
}

impl ToHeaderValues for Expires {
type Iter = option::IntoIter<HeaderValue>;
fn to_header_values(&self) -> crate::Result<Self::Iter> {
9 changes: 9 additions & 0 deletions src/conditional/etag.rs
Original file line number Diff line number Diff line change
@@ -130,6 +130,15 @@ impl ETag {
}
}

impl crate::headers::Header for ETag {
fn header_name(&self) -> HeaderName {
ETAG
}
fn header_value(&self) -> HeaderValue {
self.value()
}
}

impl Display for ETag {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
9 changes: 9 additions & 0 deletions src/conditional/if_match.rs
Original file line number Diff line number Diff line change
@@ -134,6 +134,15 @@ impl IfMatch {
}
}

impl crate::headers::Header for IfMatch {
fn header_name(&self) -> HeaderName {
IF_MATCH
}
fn header_value(&self) -> HeaderValue {
self.value()
}
}

impl IntoIterator for IfMatch {
type Item = ETag;
type IntoIter = IntoIter;
9 changes: 9 additions & 0 deletions src/conditional/if_modified_since.rs
Original file line number Diff line number Diff line change
@@ -93,6 +93,15 @@ impl ToHeaderValues for IfModifiedSince {
}
}

impl crate::headers::Header for IfModifiedSince {
fn header_name(&self) -> HeaderName {
IF_MODIFIED_SINCE
}
fn header_value(&self) -> HeaderValue {
self.value()
}
}

#[cfg(test)]
mod test {
use super::*;
9 changes: 9 additions & 0 deletions src/conditional/if_none_match.rs
Original file line number Diff line number Diff line change
@@ -140,6 +140,15 @@ impl IfNoneMatch {
}
}

impl crate::headers::Header for IfNoneMatch {
fn header_name(&self) -> HeaderName {
IF_NONE_MATCH
}
fn header_value(&self) -> HeaderValue {
self.value()
}
}

impl IntoIterator for IfNoneMatch {
type Item = ETag;
type IntoIter = IntoIter;
9 changes: 9 additions & 0 deletions src/conditional/if_unmodified_since.rs
Original file line number Diff line number Diff line change
@@ -85,6 +85,15 @@ impl IfUnmodifiedSince {
}
}

impl crate::headers::Header for IfUnmodifiedSince {
fn header_name(&self) -> HeaderName {
IF_UNMODIFIED_SINCE
}
fn header_value(&self) -> HeaderValue {
self.value()
}
}

impl ToHeaderValues for IfUnmodifiedSince {
type Iter = option::IntoIter<HeaderValue>;
fn to_header_values(&self) -> crate::Result<Self::Iter> {
9 changes: 9 additions & 0 deletions src/conditional/last_modified.rs
Original file line number Diff line number Diff line change
@@ -84,6 +84,15 @@ impl LastModified {
}
}

impl crate::headers::Header for LastModified {
fn header_name(&self) -> HeaderName {
LAST_MODIFIED
}
fn header_value(&self) -> HeaderValue {
self.value()
}
}

impl ToHeaderValues for LastModified {
type Iter = option::IntoIter<HeaderValue>;
fn to_header_values(&self) -> crate::Result<Self::Iter> {
9 changes: 9 additions & 0 deletions src/conditional/vary.rs
Original file line number Diff line number Diff line change
@@ -140,6 +140,15 @@ impl Vary {
}
}

impl crate::headers::Header for Vary {
fn header_name(&self) -> HeaderName {
VARY
}
fn header_value(&self) -> HeaderValue {
self.value()
}
}

impl IntoIterator for Vary {
type Item = HeaderName;
type IntoIter = IntoIter;
9 changes: 9 additions & 0 deletions src/content/accept.rs
Original file line number Diff line number Diff line change
@@ -189,6 +189,15 @@ impl Accept {
}
}

impl crate::headers::Header for Accept {
fn header_name(&self) -> HeaderName {
ACCEPT
}
fn header_value(&self) -> HeaderValue {
self.value()
}
}

impl IntoIterator for Accept {
type Item = MediaTypeProposal;
type IntoIter = IntoIter;
9 changes: 9 additions & 0 deletions src/content/accept_encoding.rs
Original file line number Diff line number Diff line change
@@ -182,6 +182,15 @@ impl AcceptEncoding {
}
}

impl crate::headers::Header for AcceptEncoding {
fn header_name(&self) -> HeaderName {
ACCEPT_ENCODING
}
fn header_value(&self) -> HeaderValue {
self.value()
}
}

impl IntoIterator for AcceptEncoding {
type Item = EncodingProposal;
type IntoIter = IntoIter;
9 changes: 9 additions & 0 deletions src/content/content_encoding.rs
Original file line number Diff line number Diff line change
@@ -80,6 +80,15 @@ impl ContentEncoding {
}
}

impl crate::headers::Header for ContentEncoding {
fn header_name(&self) -> HeaderName {
CONTENT_ENCODING
}
fn header_value(&self) -> HeaderValue {
self.value()
}
}

impl ToHeaderValues for ContentEncoding {
type Iter = option::IntoIter<HeaderValue>;
fn to_header_values(&self) -> crate::Result<Self::Iter> {
9 changes: 9 additions & 0 deletions src/content/content_length.rs
Original file line number Diff line number Diff line change
@@ -80,6 +80,15 @@ impl ContentLength {
}
}

impl crate::headers::Header for ContentLength {
fn header_name(&self) -> HeaderName {
CONTENT_LENGTH
}
fn header_value(&self) -> HeaderValue {
self.value()
}
}

#[cfg(test)]
mod test {
use super::*;
9 changes: 9 additions & 0 deletions src/content/content_location.rs
Original file line number Diff line number Diff line change
@@ -99,6 +99,15 @@ impl ContentLocation {
}
}

impl crate::headers::Header for ContentLocation {
fn header_name(&self) -> HeaderName {
CONTENT_LOCATION
}
fn header_value(&self) -> HeaderValue {
self.value()
}
}

#[cfg(test)]
mod test {
use super::*;
9 changes: 9 additions & 0 deletions src/content/content_type.rs
Original file line number Diff line number Diff line change
@@ -91,6 +91,15 @@ impl ContentType {
}
}

impl crate::headers::Header for ContentType {
fn header_name(&self) -> HeaderName {
CONTENT_TYPE
}
fn header_value(&self) -> HeaderValue {
self.value()
}
}

impl PartialEq<Mime> for ContentType {
fn eq(&self, other: &Mime) -> bool {
&self.media_type == other
41 changes: 41 additions & 0 deletions src/headers/header.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
use crate::headers::{HeaderName, HeaderValue, Headers};

/// A trait representing a [`HeaderName`] and [`HeaderValue`] pair.
pub trait Header {
/// Access the header's name.
fn header_name(&self) -> HeaderName;

/// Access the header's value.
fn header_value(&self) -> HeaderValue;

/// Insert the header name and header value into something that looks like a
/// [`Headers`] map.
fn apply_header<H: AsMut<Headers>>(&self, mut headers: H) {
let name = self.header_name();
let value = self.header_value();
headers.as_mut().insert(name, value);
}
}

impl<'a, 'b> Header for (&'a str, &'b str) {
fn header_name(&self) -> HeaderName {
HeaderName::from(self.0)
}

fn header_value(&self) -> HeaderValue {
HeaderValue::from_bytes(self.1.to_owned().into_bytes())
.expect("String slice should be valid ASCII")
}
}

#[cfg(test)]
mod test {
use super::*;

#[test]
fn header_from_strings() {
let strings = ("Content-Length", "12");
assert_eq!(strings.header_name(), "Content-Length");
assert_eq!(strings.header_value(), "12");
}
}
2 changes: 2 additions & 0 deletions src/headers/mod.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
//! HTTP headers.
mod constants;
mod header;
mod header_name;
mod header_value;
mod header_values;
@@ -14,6 +15,7 @@ mod to_header_values;
mod values;

pub use constants::*;
pub use header::Header;
pub use header_name::HeaderName;
pub use header_value::HeaderValue;
pub use header_values::HeaderValues;
9 changes: 9 additions & 0 deletions src/other/date.rs
Original file line number Diff line number Diff line change
@@ -92,6 +92,15 @@ impl Date {
}
}

impl crate::headers::Header for Date {
fn header_name(&self) -> HeaderName {
DATE
}
fn header_value(&self) -> HeaderValue {
self.value()
}
}

impl From<Date> for SystemTime {
fn from(date: Date) -> Self {
date.at
9 changes: 9 additions & 0 deletions src/other/expect.rs
Original file line number Diff line number Diff line change
@@ -74,6 +74,15 @@ impl Expect {
}
}

impl crate::headers::Header for Expect {
fn header_name(&self) -> HeaderName {
EXPECT
}
fn header_value(&self) -> HeaderValue {
self.value()
}
}

impl ToHeaderValues for Expect {
type Iter = option::IntoIter<HeaderValue>;
fn to_header_values(&self) -> crate::Result<Self::Iter> {
9 changes: 9 additions & 0 deletions src/other/referer.rs
Original file line number Diff line number Diff line change
@@ -104,6 +104,15 @@ impl Referer {
}
}

impl crate::headers::Header for Referer {
fn header_name(&self) -> HeaderName {
REFERER
}
fn header_value(&self) -> HeaderValue {
self.value()
}
}

#[cfg(test)]
mod test {
use super::*;
9 changes: 9 additions & 0 deletions src/other/source_map.rs
Original file line number Diff line number Diff line change
@@ -101,6 +101,15 @@ impl SourceMap {
}
}

impl crate::headers::Header for SourceMap {
fn header_name(&self) -> HeaderName {
SOURCE_MAP
}
fn header_value(&self) -> HeaderValue {
self.value()
}
}

#[cfg(test)]
mod test {
use super::*;
12 changes: 12 additions & 0 deletions src/proxies/forwarded.rs
Original file line number Diff line number Diff line change
@@ -408,6 +408,18 @@ impl<'a> Forwarded<'a> {
}
}

impl<'a> crate::headers::Header for Forwarded<'a> {
fn header_name(&self) -> HeaderName {
FORWARDED
}
fn header_value(&self) -> HeaderValue {
// NOTE(yosh): This will never panic because we always write into a string.
let output = self.value().unwrap();
// SAFETY: the internal string is validated to be ASCII.
unsafe { HeaderValue::from_bytes_unchecked(output.into()) }
}
}

fn parse_value(input: &str) -> (Option<Cow<'_, str>>, &str) {
match parse_token(input) {
(Some(token), rest) => (Some(Cow::Borrowed(token)), rest),
9 changes: 9 additions & 0 deletions src/security/timing_allow_origin.rs
Original file line number Diff line number Diff line change
@@ -162,6 +162,15 @@ impl TimingAllowOrigin {
}
}

impl crate::headers::Header for TimingAllowOrigin {
fn header_name(&self) -> HeaderName {
TIMING_ALLOW_ORIGIN
}
fn header_value(&self) -> HeaderValue {
self.value()
}
}

impl IntoIterator for TimingAllowOrigin {
type Item = Url;
type IntoIter = IntoIter;
9 changes: 9 additions & 0 deletions src/server/allow.rs
Original file line number Diff line number Diff line change
@@ -108,6 +108,15 @@ impl Allow {
}
}

impl crate::headers::Header for Allow {
fn header_name(&self) -> HeaderName {
ALLOW
}
fn header_value(&self) -> HeaderValue {
self.value()
}
}

impl IntoIterator for Allow {
type Item = Method;
type IntoIter = IntoIter;
9 changes: 9 additions & 0 deletions src/trace/server_timing/mod.rs
Original file line number Diff line number Diff line change
@@ -131,6 +131,15 @@ impl ServerTiming {
}
}

impl crate::headers::Header for ServerTiming {
fn header_name(&self) -> HeaderName {
SERVER_TIMING
}
fn header_value(&self) -> HeaderValue {
self.value()
}
}

impl IntoIterator for ServerTiming {
type Item = Metric;
type IntoIter = IntoIter;
9 changes: 9 additions & 0 deletions src/trace/trace_context.rs
Original file line number Diff line number Diff line change
@@ -246,6 +246,15 @@ impl TraceContext {
}
}

impl crate::headers::Header for TraceContext {
fn header_name(&self) -> HeaderName {
TRACEPARENT
}
fn header_value(&self) -> HeaderValue {
self.value()
}
}

impl fmt::Display for TraceContext {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(
19 changes: 14 additions & 5 deletions src/transfer/te.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::headers::{HeaderName, HeaderValue, Headers, ToHeaderValues, ACCEPT_ENCODING};
use crate::headers::{self, HeaderName, HeaderValue, Headers, ToHeaderValues};
use crate::transfer::{Encoding, EncodingProposal, TransferEncoding};
use crate::utils::sort_by_weight;
use crate::{Error, StatusCode};
@@ -33,7 +33,7 @@ use std::slice;
/// let encoding = te.negotiate(&[Encoding::Brotli, Encoding::Gzip])?;
/// encoding.apply(&mut res);
///
/// assert_eq!(res["Content-Encoding"], "br");
/// assert_eq!(res["Transfer-Encoding"], "br");
/// #
/// # Ok(()) }
/// ```
@@ -54,7 +54,7 @@ impl TE {
/// Create an instance of `TE` from a `Headers` instance.
pub fn from_headers(headers: impl AsRef<Headers>) -> crate::Result<Option<Self>> {
let mut entries = vec![];
let headers = match headers.as_ref().get(ACCEPT_ENCODING) {
let headers = match headers.as_ref().get(headers::TE) {
Some(headers) => headers,
None => return Ok(None),
};
@@ -138,12 +138,12 @@ impl TE {

/// Sets the `Accept-Encoding` header.
pub fn apply(&self, mut headers: impl AsMut<Headers>) {
headers.as_mut().insert(ACCEPT_ENCODING, self.value());
headers.as_mut().insert(headers::TE, self.value());
}

/// Get the `HeaderName`.
pub fn name(&self) -> HeaderName {
ACCEPT_ENCODING
headers::TE
}

/// Get the `HeaderValue`.
@@ -183,6 +183,15 @@ impl TE {
}
}

impl crate::headers::Header for TE {
fn header_name(&self) -> HeaderName {
headers::TE
}
fn header_value(&self) -> HeaderValue {
self.value()
}
}

impl IntoIterator for TE {
type Item = EncodingProposal;
type IntoIter = IntoIter;
17 changes: 13 additions & 4 deletions src/transfer/transfer_encoding.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::headers::{HeaderName, HeaderValue, Headers, ToHeaderValues, CONTENT_ENCODING};
use crate::headers::{HeaderName, HeaderValue, Headers, ToHeaderValues, TRANSFER_ENCODING};
use crate::transfer::{Encoding, EncodingProposal};

use std::fmt::{self, Debug};
@@ -42,7 +42,7 @@ impl TransferEncoding {

/// Create a new instance from headers.
pub fn from_headers(headers: impl AsRef<Headers>) -> crate::Result<Option<Self>> {
let headers = match headers.as_ref().get(CONTENT_ENCODING) {
let headers = match headers.as_ref().get(TRANSFER_ENCODING) {
Some(headers) => headers,
None => return Ok(None),
};
@@ -61,12 +61,12 @@ impl TransferEncoding {

/// Sets the `Content-Encoding` header.
pub fn apply(&self, mut headers: impl AsMut<Headers>) {
headers.as_mut().insert(CONTENT_ENCODING, self.value());
headers.as_mut().insert(TRANSFER_ENCODING, self.value());
}

/// Get the `HeaderName`.
pub fn name(&self) -> HeaderName {
CONTENT_ENCODING
TRANSFER_ENCODING
}

/// Get the `HeaderValue`.
@@ -80,6 +80,15 @@ impl TransferEncoding {
}
}

impl crate::headers::Header for TransferEncoding {
fn header_name(&self) -> HeaderName {
TRANSFER_ENCODING
}
fn header_value(&self) -> HeaderValue {
self.value()
}
}

impl ToHeaderValues for TransferEncoding {
type Iter = option::IntoIter<HeaderValue>;
fn to_header_values(&self) -> crate::Result<Self::Iter> {