Skip to content
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

feat: impl ToHeader for all typed headers #285

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
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
6 changes: 6 additions & 0 deletions src/auth/authorization.rs
Original file line number Diff line number Diff line change
@@ -110,6 +110,12 @@ impl Authorization {
}
}

impl crate::headers::ToHeader for Authorization {
fn to_header(self) -> crate::Result<(HeaderName, HeaderValue)> {
Ok((self.name(), self.value()))
}
}

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

impl crate::headers::ToHeader for BasicAuth {
fn to_header(self) -> crate::Result<(HeaderName, HeaderValue)> {
Ok((self.name(), self.value()))
}
}

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

impl crate::headers::ToHeader for WwwAuthenticate {
fn to_header(self) -> crate::Result<(HeaderName, HeaderValue)> {
Ok((self.name(), self.value()))
}
}

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

impl crate::headers::ToHeader for Age {
fn to_header(self) -> crate::Result<(HeaderName, HeaderValue)> {
Ok((self.name(), self.value()))
}
}

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

impl crate::headers::ToHeader for CacheControl {
fn to_header(self) -> crate::Result<(HeaderName, HeaderValue)> {
Ok((self.name(), self.value()))
}
}

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

impl crate::headers::ToHeader for ClearSiteData {
fn to_header(self) -> crate::Result<(HeaderName, HeaderValue)> {
Ok((self.name(), self.value()))
}
}

impl IntoIterator for ClearSiteData {
type Item = ClearDirective;
type IntoIter = IntoIter;
6 changes: 6 additions & 0 deletions src/cache/expires.rs
Original file line number Diff line number Diff line change
@@ -90,6 +90,12 @@ impl Expires {
}
}

impl crate::headers::ToHeader for Expires {
fn to_header(self) -> crate::Result<(HeaderName, HeaderValue)> {
Ok((self.name(), self.value()))
}
}

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

impl crate::headers::ToHeader for ETag {
fn to_header(self) -> crate::Result<(HeaderName, HeaderValue)> {
Ok((self.name(), self.value()))
}
}

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

impl crate::headers::ToHeader for IfMatch {
fn to_header(self) -> crate::Result<(HeaderName, HeaderValue)> {
Ok((self.name(), self.value()))
}
}

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

impl crate::headers::ToHeader for IfModifiedSince {
fn to_header(self) -> crate::Result<(HeaderName, HeaderValue)> {
Ok((self.name(), self.value()))
}
}

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

impl crate::headers::ToHeader for IfNoneMatch {
fn to_header(self) -> crate::Result<(HeaderName, HeaderValue)> {
Ok((self.name(), self.value()))
}
}

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

impl crate::headers::ToHeader for IfUnmodifiedSince {
fn to_header(self) -> crate::Result<(HeaderName, HeaderValue)> {
Ok((self.name(), self.value()))
}
}

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

impl crate::headers::ToHeader for LastModified {
fn to_header(self) -> crate::Result<(HeaderName, HeaderValue)> {
Ok((self.name(), self.value()))
}
}

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

impl crate::headers::ToHeader for Vary {
fn to_header(self) -> crate::Result<(HeaderName, HeaderValue)> {
Ok((self.name(), self.value()))
}
}

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

impl crate::headers::ToHeader for AcceptEncoding {
fn to_header(self) -> crate::Result<(HeaderName, HeaderValue)> {
Ok((self.name(), self.value()))
}
}

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

impl crate::headers::ToHeader for ContentEncoding {
fn to_header(self) -> crate::Result<(HeaderName, HeaderValue)> {
Ok((self.name(), self.value()))
}
}

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

impl crate::headers::ToHeader for ContentLength {
fn to_header(self) -> crate::Result<(HeaderName, HeaderValue)> {
Ok((self.name(), self.value()))
}
}

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

impl crate::headers::ToHeader for ContentLocation {
fn to_header(self) -> crate::Result<(HeaderName, HeaderValue)> {
Ok((self.name(), self.value()))
}
}

#[cfg(test)]
mod test {
use super::*;
6 changes: 6 additions & 0 deletions src/headers/constants.rs
Original file line number Diff line number Diff line change
@@ -12,6 +12,12 @@ pub const CONTENT_LOCATION: HeaderName = HeaderName::from_lowercase_str("content
pub const CONTENT_MD5: HeaderName = HeaderName::from_lowercase_str("content-md5");
/// The `Content-Range` Header
pub const CONTENT_RANGE: HeaderName = HeaderName::from_lowercase_str("content-range");
/// The `Content-Security-Policy` Header
pub const CONTENT_SECURITY_POLICY: HeaderName =
HeaderName::from_lowercase_str("content-security-policy");
/// The `Content-Security-Policy-Report-Only` Header
pub const CONTENT_SECURITY_POLICY_REPORT_ONLY: HeaderName =
HeaderName::from_lowercase_str("content-security-policy-report-only");
/// The `Content-Type` Header
pub const CONTENT_TYPE: HeaderName = HeaderName::from_lowercase_str("content-type");

2 changes: 2 additions & 0 deletions src/headers/mod.rs
Original file line number Diff line number Diff line change
@@ -10,6 +10,7 @@ mod into_iter;
mod iter;
mod iter_mut;
mod names;
mod to_header;
mod to_header_values;
mod values;

@@ -22,5 +23,6 @@ pub use into_iter::IntoIter;
pub use iter::Iter;
pub use iter_mut::IterMut;
pub use names::Names;
pub use to_header::ToHeader;
pub use to_header_values::ToHeaderValues;
pub use values::Values;
24 changes: 24 additions & 0 deletions src/headers/to_header.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
use std::convert::TryInto;

use crate::headers::{HeaderName, HeaderValue};

/// A trait for objects which can be converted or resolved to a `HeaderName` and `HeaderValue` pair.
pub trait ToHeader {
/// Converts this object to a `HeaderName` and `HeaderValue` pair.
fn to_header(self) -> crate::Result<(HeaderName, HeaderValue)>;
}

impl<N, V> ToHeader for (N, V)
where
N: TryInto<HeaderName>,
V: TryInto<HeaderValue>,
<N as TryInto<HeaderName>>::Error: Into<crate::Error>,
<V as TryInto<HeaderValue>>::Error: Into<crate::Error>,
{
fn to_header(self) -> crate::Result<(HeaderName, HeaderValue)> {
Ok((
self.0.try_into().map_err(Into::into)?,
self.1.try_into().map_err(Into::into)?,
))
}
}
6 changes: 6 additions & 0 deletions src/other/date.rs
Original file line number Diff line number Diff line change
@@ -92,6 +92,12 @@ impl Date {
}
}

impl crate::headers::ToHeader for Date {
fn to_header(self) -> crate::Result<(HeaderName, HeaderValue)> {
Ok((self.name(), self.value()))
}
}

impl From<Date> for SystemTime {
fn from(date: Date) -> Self {
date.at
11 changes: 11 additions & 0 deletions src/proxies/forwarded.rs
Original file line number Diff line number Diff line change
@@ -318,6 +318,11 @@ impl<'a> Forwarded<'a> {
headers.as_mut().insert(FORWARDED, self);
}

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

/// Builds a Forwarded header as a String.
///
/// # Example
@@ -408,6 +413,12 @@ impl<'a> Forwarded<'a> {
}
}

impl<'a> crate::headers::ToHeader for Forwarded<'a> {
fn to_header(self) -> crate::Result<(HeaderName, HeaderValue)> {
Ok((self.name(), self.value()?.parse()?))
}
}

fn parse_value(input: &str) -> (Option<Cow<'_, str>>, &str) {
match parse_token(input) {
(Some(token), rest) => (Some(Cow::Borrowed(token)), rest),
48 changes: 37 additions & 11 deletions src/security/csp.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
use crate::headers::{
HeaderName, HeaderValue, CONTENT_SECURITY_POLICY, CONTENT_SECURITY_POLICY_REPORT_ONLY,
};
use crate::Headers;

use serde::{Deserialize, Serialize};

use std::collections::HashMap;
use std::fmt;

@@ -337,23 +342,44 @@ impl ContentSecurityPolicy {
self
}

/// Get the `HeaderName`.
pub fn name(&self) -> HeaderName {
if self.report_only_flag {
CONTENT_SECURITY_POLICY_REPORT_ONLY
} else {
CONTENT_SECURITY_POLICY
}
}

/// Create and retrieve the policy value
fn value(&mut self) -> String {
for (directive, sources) in &self.directives {
let policy = format!("{} {}", directive, sources.join(" "));
self.policy.push(policy);
self.policy.sort();
}
self.policy.extend(
self.directives
.iter()
.map(|(directive, sources)| format!("{} {}", directive, sources.join(" "))),
);
self.policy.sort();
self.policy.join("; ")
}

/// Sets the `Content-Security-Policy` (CSP) HTTP header to prevent cross-site injections
pub fn apply(&mut self, mut headers: impl AsMut<Headers>) {
let name = if self.report_only_flag {
"Content-Security-Policy-Report-Only"
} else {
"Content-Security-Policy"
};
headers.as_mut().insert(name, self.value());
headers.as_mut().insert(self.name(), self.value());
}
}

impl crate::headers::ToHeader for ContentSecurityPolicy {
fn to_header(self) -> crate::Result<(HeaderName, HeaderValue)> {
let mut policies = self.policy.clone();
policies.extend(
self.directives
.iter()
.map(|(directive, sources)| format!("{} {}", directive, sources.join(" "))),
);
policies.sort();

let value = policies.join("; ");

Ok((self.name(), value.parse()?))
}
}
Loading