mirror of https://github.com/http-rs/http-types
Compare commits
7 Commits
c99a9e0606
...
eb1f011341
Author | SHA1 | Date |
---|---|---|
Yoshua Wuyts | eb1f011341 | |
Yoshua Wuyts | b0c50be2db | |
Yoshua Wuyts | 7a1a518179 | |
Yoshua Wuyts | fe27416dd6 | |
Yoshua Wuyts | 04953ce909 | |
Yoshua Wuyts | a9fc3590c3 | |
Yoshua Wuyts | d9120102b2 |
|
@ -1,6 +1,6 @@
|
|||
use crate::auth::AuthenticationScheme;
|
||||
use crate::bail_status as bail;
|
||||
use crate::headers::{Header, HeaderName, HeaderValue, Headers, AUTHORIZATION};
|
||||
use crate::headers::{Field, FieldName, FieldValue, Fields, AUTHORIZATION};
|
||||
|
||||
/// Credentials to authenticate a user agent with a server.
|
||||
///
|
||||
|
@ -46,7 +46,7 @@ impl Authorization {
|
|||
}
|
||||
|
||||
/// Create a new instance from headers.
|
||||
pub fn from_headers(headers: impl AsRef<Headers>) -> crate::Result<Option<Self>> {
|
||||
pub fn from_headers(headers: impl AsRef<Fields>) -> crate::Result<Option<Self>> {
|
||||
let headers = match headers.as_ref().get(AUTHORIZATION) {
|
||||
Some(headers) => headers,
|
||||
None => return Ok(None),
|
||||
|
@ -92,23 +92,21 @@ impl Authorization {
|
|||
}
|
||||
}
|
||||
|
||||
impl Header for Authorization {
|
||||
fn header_name(&self) -> HeaderName {
|
||||
AUTHORIZATION
|
||||
}
|
||||
impl Field for Authorization {
|
||||
const FIELD_NAME: FieldName = AUTHORIZATION;
|
||||
|
||||
fn header_value(&self) -> HeaderValue {
|
||||
fn field_value(&self) -> FieldValue {
|
||||
let output = format!("{} {}", self.scheme, self.credentials);
|
||||
|
||||
// SAFETY: the internal string is validated to be ASCII.
|
||||
unsafe { HeaderValue::from_bytes_unchecked(output.into()) }
|
||||
unsafe { FieldValue::from_bytes_unchecked(output.into()) }
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use crate::headers::Headers;
|
||||
use crate::headers::Fields;
|
||||
|
||||
#[test]
|
||||
fn smoke() -> crate::Result<()> {
|
||||
|
@ -116,8 +114,8 @@ mod test {
|
|||
let credentials = "0xdeadbeef202020";
|
||||
let authz = Authorization::new(scheme, credentials.into());
|
||||
|
||||
let mut headers = Headers::new();
|
||||
headers.insert(authz);
|
||||
let mut headers = Fields::new();
|
||||
headers.insert_typed(authz);
|
||||
|
||||
let authz = Authorization::from_headers(headers)?.unwrap();
|
||||
|
||||
|
@ -128,7 +126,7 @@ mod test {
|
|||
|
||||
#[test]
|
||||
fn bad_request_on_parse_error() {
|
||||
let mut headers = Headers::new();
|
||||
let mut headers = Fields::new();
|
||||
headers
|
||||
.insert(AUTHORIZATION, "<nori ate the tag. yum.>")
|
||||
.unwrap();
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
use crate::headers::{HeaderName, HeaderValue, Headers, AUTHORIZATION};
|
||||
use crate::headers::{FieldName, FieldValue, Fields, AUTHORIZATION};
|
||||
use crate::Status;
|
||||
use crate::{
|
||||
auth::{AuthenticationScheme, Authorization},
|
||||
headers::Header,
|
||||
headers::Field,
|
||||
};
|
||||
use crate::{bail_status as bail, ensure_status as ensure};
|
||||
|
||||
|
@ -53,7 +53,7 @@ impl BasicAuth {
|
|||
}
|
||||
|
||||
/// Create a new instance from headers.
|
||||
pub fn from_headers(headers: impl AsRef<Headers>) -> crate::Result<Option<Self>> {
|
||||
pub fn from_headers(headers: impl AsRef<Fields>) -> crate::Result<Option<Self>> {
|
||||
let auth = match Authorization::from_headers(headers)? {
|
||||
Some(auth) => auth,
|
||||
None => return Ok(None),
|
||||
|
@ -98,23 +98,21 @@ impl BasicAuth {
|
|||
}
|
||||
}
|
||||
|
||||
impl Header for BasicAuth {
|
||||
fn header_name(&self) -> HeaderName {
|
||||
AUTHORIZATION
|
||||
}
|
||||
impl Field for BasicAuth {
|
||||
const FIELD_NAME: FieldName = AUTHORIZATION;
|
||||
|
||||
fn header_value(&self) -> HeaderValue {
|
||||
fn field_value(&self) -> FieldValue {
|
||||
let scheme = AuthenticationScheme::Basic;
|
||||
let credentials = base64::encode(format!("{}:{}", self.username, self.password));
|
||||
let auth = Authorization::new(scheme, credentials);
|
||||
auth.header_value()
|
||||
auth.field_value()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use crate::headers::Headers;
|
||||
use crate::headers::Fields;
|
||||
|
||||
#[test]
|
||||
fn smoke() -> crate::Result<()> {
|
||||
|
@ -122,8 +120,8 @@ mod test {
|
|||
let password = "secret_fish!!";
|
||||
let authz = BasicAuth::new(username, password);
|
||||
|
||||
let mut headers = Headers::new();
|
||||
headers.insert(authz);
|
||||
let mut headers = Fields::new();
|
||||
headers.insert_typed(authz);
|
||||
|
||||
let authz = BasicAuth::from_headers(headers)?.unwrap();
|
||||
|
||||
|
@ -134,7 +132,7 @@ mod test {
|
|||
|
||||
#[test]
|
||||
fn bad_request_on_parse_error() {
|
||||
let mut headers = Headers::new();
|
||||
let mut headers = Fields::new();
|
||||
headers
|
||||
.insert(AUTHORIZATION, "<nori ate the tag. yum.>")
|
||||
.unwrap();
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use crate::bail_status as bail;
|
||||
use crate::headers::{HeaderName, HeaderValue, Headers, WWW_AUTHENTICATE};
|
||||
use crate::{auth::AuthenticationScheme, headers::Header};
|
||||
use crate::headers::{FieldName, FieldValue, Fields, WWW_AUTHENTICATE};
|
||||
use crate::{auth::AuthenticationScheme, headers::Field};
|
||||
|
||||
/// Define the authentication method that should be used to gain access to a
|
||||
/// resource.
|
||||
|
@ -49,7 +49,7 @@ impl WwwAuthenticate {
|
|||
}
|
||||
|
||||
/// Create a new instance from headers.
|
||||
pub fn from_headers(headers: impl AsRef<Headers>) -> crate::Result<Option<Self>> {
|
||||
pub fn from_headers(headers: impl AsRef<Fields>) -> crate::Result<Option<Self>> {
|
||||
let headers = match headers.as_ref().get(WWW_AUTHENTICATE) {
|
||||
Some(headers) => headers,
|
||||
None => return Ok(None),
|
||||
|
@ -114,23 +114,21 @@ impl WwwAuthenticate {
|
|||
}
|
||||
}
|
||||
|
||||
impl Header for WwwAuthenticate {
|
||||
fn header_name(&self) -> HeaderName {
|
||||
WWW_AUTHENTICATE
|
||||
}
|
||||
impl Field for WwwAuthenticate {
|
||||
const FIELD_NAME: FieldName = WWW_AUTHENTICATE;
|
||||
|
||||
fn header_value(&self) -> HeaderValue {
|
||||
fn field_value(&self) -> FieldValue {
|
||||
let output = format!(r#"{} realm="{}", charset="UTF-8""#, self.scheme, self.realm);
|
||||
|
||||
// SAFETY: the internal string is validated to be ASCII.
|
||||
unsafe { HeaderValue::from_bytes_unchecked(output.into()) }
|
||||
unsafe { FieldValue::from_bytes_unchecked(output.into()) }
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use crate::headers::Headers;
|
||||
use crate::headers::Fields;
|
||||
|
||||
#[test]
|
||||
fn smoke() -> crate::Result<()> {
|
||||
|
@ -138,8 +136,8 @@ mod test {
|
|||
let realm = "Access to the staging site";
|
||||
let authz = WwwAuthenticate::new(scheme, realm.into());
|
||||
|
||||
let mut headers = Headers::new();
|
||||
headers.insert(authz);
|
||||
let mut headers = Fields::new();
|
||||
headers.insert_typed(authz);
|
||||
|
||||
assert_eq!(
|
||||
headers["WWW-Authenticate"],
|
||||
|
@ -155,7 +153,7 @@ mod test {
|
|||
|
||||
#[test]
|
||||
fn bad_request_on_parse_error() {
|
||||
let mut headers = Headers::new();
|
||||
let mut headers = Fields::new();
|
||||
headers
|
||||
.insert(WWW_AUTHENTICATE, "<nori ate the tag. yum.>")
|
||||
.unwrap();
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use crate::headers::{Header, HeaderName, HeaderValue, Headers, AGE};
|
||||
use crate::headers::{Field, FieldName, FieldValue, Fields, AGE};
|
||||
use crate::Status;
|
||||
|
||||
use std::fmt::Debug;
|
||||
|
@ -52,7 +52,7 @@ impl Age {
|
|||
}
|
||||
|
||||
/// Create an instance of `Age` from a `Headers` instance.
|
||||
pub fn from_headers(headers: impl AsRef<Headers>) -> crate::Result<Option<Self>> {
|
||||
pub fn from_headers(headers: impl AsRef<Fields>) -> crate::Result<Option<Self>> {
|
||||
let headers = match headers.as_ref().get(AGE) {
|
||||
Some(headers) => headers,
|
||||
None => return Ok(None),
|
||||
|
@ -69,30 +69,28 @@ impl Age {
|
|||
}
|
||||
}
|
||||
|
||||
impl Header for Age {
|
||||
fn header_name(&self) -> HeaderName {
|
||||
AGE
|
||||
}
|
||||
impl Field for Age {
|
||||
const FIELD_NAME: FieldName = AGE;
|
||||
|
||||
fn header_value(&self) -> HeaderValue {
|
||||
fn field_value(&self) -> FieldValue {
|
||||
let output = self.dur.as_secs().to_string();
|
||||
|
||||
// SAFETY: the internal string is validated to be ASCII.
|
||||
unsafe { HeaderValue::from_bytes_unchecked(output.into()) }
|
||||
unsafe { FieldValue::from_bytes_unchecked(output.into()) }
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use crate::headers::Headers;
|
||||
use crate::headers::Fields;
|
||||
|
||||
#[test]
|
||||
fn smoke() -> crate::Result<()> {
|
||||
let age = Age::new(Duration::from_secs(12));
|
||||
|
||||
let mut headers = Headers::new();
|
||||
headers.insert(age);
|
||||
let mut headers = Fields::new();
|
||||
headers.insert_typed(age);
|
||||
|
||||
let age = Age::from_headers(headers)?.unwrap();
|
||||
assert_eq!(age, Age::new(Duration::from_secs(12)));
|
||||
|
@ -101,7 +99,7 @@ mod test {
|
|||
|
||||
#[test]
|
||||
fn bad_request_on_parse_error() {
|
||||
let mut headers = Headers::new();
|
||||
let mut headers = Fields::new();
|
||||
headers.insert(AGE, "<nori ate the tag. yum.>").unwrap();
|
||||
let err = Age::from_headers(headers).unwrap_err();
|
||||
assert_eq!(err.status(), 400);
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use headers::Header;
|
||||
use headers::Field;
|
||||
|
||||
use crate::headers::{HeaderName, HeaderValue, Headers, CACHE_CONTROL};
|
||||
use crate::headers::{FieldName, FieldValue, Fields, CACHE_CONTROL};
|
||||
use crate::{cache::CacheDirective, headers};
|
||||
|
||||
use std::fmt::{self, Debug, Write};
|
||||
|
@ -42,7 +42,7 @@ impl CacheControl {
|
|||
}
|
||||
|
||||
/// Create a new instance from headers.
|
||||
pub fn from_headers(headers: impl AsRef<Headers>) -> crate::Result<Option<Self>> {
|
||||
pub fn from_headers(headers: impl AsRef<Fields>) -> crate::Result<Option<Self>> {
|
||||
let mut entries = vec![];
|
||||
let headers = match headers.as_ref().get(CACHE_CONTROL) {
|
||||
Some(headers) => headers,
|
||||
|
@ -81,14 +81,12 @@ impl CacheControl {
|
|||
}
|
||||
}
|
||||
|
||||
impl Header for CacheControl {
|
||||
fn header_name(&self) -> HeaderName {
|
||||
CACHE_CONTROL
|
||||
}
|
||||
fn header_value(&self) -> HeaderValue {
|
||||
impl Field for CacheControl {
|
||||
const FIELD_NAME: FieldName = CACHE_CONTROL;
|
||||
fn field_value(&self) -> FieldValue {
|
||||
let mut output = String::new();
|
||||
for (n, directive) in self.entries.iter().enumerate() {
|
||||
let directive: HeaderValue = directive.clone().into();
|
||||
let directive: FieldValue = directive.clone().into();
|
||||
match n {
|
||||
0 => write!(output, "{}", directive).unwrap(),
|
||||
_ => write!(output, ", {}", directive).unwrap(),
|
||||
|
@ -96,7 +94,7 @@ impl Header for CacheControl {
|
|||
}
|
||||
|
||||
// SAFETY: the internal string is validated to be ASCII.
|
||||
unsafe { HeaderValue::from_bytes_unchecked(output.into()) }
|
||||
unsafe { FieldValue::from_bytes_unchecked(output.into()) }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use crate::headers::HeaderValue;
|
||||
use crate::headers::FieldValue;
|
||||
use crate::Status;
|
||||
|
||||
use std::time::Duration;
|
||||
|
@ -127,10 +127,10 @@ impl CacheDirective {
|
|||
}
|
||||
}
|
||||
|
||||
impl From<CacheDirective> for HeaderValue {
|
||||
impl From<CacheDirective> for FieldValue {
|
||||
fn from(directive: CacheDirective) -> Self {
|
||||
use CacheDirective::*;
|
||||
let h = |s: String| unsafe { HeaderValue::from_bytes_unchecked(s.into_bytes()) };
|
||||
let h = |s: String| unsafe { FieldValue::from_bytes_unchecked(s.into_bytes()) };
|
||||
|
||||
match directive {
|
||||
Immutable => h("immutable".to_string()),
|
||||
|
|
|
@ -16,7 +16,7 @@ pub use cache_directive::CacheDirective;
|
|||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use crate::headers::{Header, Headers, CACHE_CONTROL};
|
||||
use crate::headers::{Fields, CACHE_CONTROL};
|
||||
|
||||
#[test]
|
||||
fn smoke() -> crate::Result<()> {
|
||||
|
@ -24,8 +24,8 @@ mod test {
|
|||
entries.push(CacheDirective::Immutable);
|
||||
entries.push(CacheDirective::NoStore);
|
||||
|
||||
let mut headers = Headers::new();
|
||||
headers.insert(entries);
|
||||
let mut headers = Fields::new();
|
||||
headers.insert_typed(entries);
|
||||
|
||||
let entries = CacheControl::from_headers(headers)?.unwrap();
|
||||
let mut entries = entries.iter();
|
||||
|
@ -36,7 +36,7 @@ mod test {
|
|||
|
||||
#[test]
|
||||
fn ignore_unkonwn_directives() -> crate::Result<()> {
|
||||
let mut headers = Headers::new();
|
||||
let mut headers = Fields::new();
|
||||
headers.insert(CACHE_CONTROL, "barrel_roll").unwrap();
|
||||
let entries = CacheControl::from_headers(headers)?.unwrap();
|
||||
let mut entries = entries.iter();
|
||||
|
@ -46,7 +46,7 @@ mod test {
|
|||
|
||||
#[test]
|
||||
fn bad_request_on_parse_error() {
|
||||
let mut headers = Headers::new();
|
||||
let mut headers = Fields::new();
|
||||
headers.insert(CACHE_CONTROL, "min-fresh=0.9").unwrap(); // floats are not supported
|
||||
let err = CacheControl::from_headers(headers).unwrap_err();
|
||||
assert_eq!(err.status(), 400);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
//! Clear browsing data (cookies, storage, cache) associated with the
|
||||
//! requesting website
|
||||
|
||||
use crate::headers::{self, HeaderName, HeaderValue, Headers, CLEAR_SITE_DATA};
|
||||
use crate::headers::{self, FieldName, FieldValue, Fields, CLEAR_SITE_DATA};
|
||||
|
||||
use std::fmt::{self, Debug, Write};
|
||||
use std::iter::Iterator;
|
||||
|
@ -12,7 +12,7 @@ use std::str::FromStr;
|
|||
mod directive;
|
||||
|
||||
pub use directive::ClearDirective;
|
||||
use headers::Header;
|
||||
use headers::Field;
|
||||
|
||||
/// Clear browsing data (cookies, storage, cache) associated with the
|
||||
/// requesting website.
|
||||
|
@ -60,7 +60,7 @@ impl ClearSiteData {
|
|||
}
|
||||
|
||||
/// Create a new instance from headers.
|
||||
pub fn from_headers(headers: impl AsRef<Headers>) -> crate::Result<Option<Self>> {
|
||||
pub fn from_headers(headers: impl AsRef<Fields>) -> crate::Result<Option<Self>> {
|
||||
let mut entries = vec![];
|
||||
let header_values = match headers.as_ref().get(CLEAR_SITE_DATA) {
|
||||
Some(headers) => headers,
|
||||
|
@ -211,12 +211,10 @@ impl Debug for ClearSiteData {
|
|||
}
|
||||
}
|
||||
|
||||
impl Header for ClearSiteData {
|
||||
fn header_name(&self) -> HeaderName {
|
||||
CLEAR_SITE_DATA
|
||||
}
|
||||
impl Field for ClearSiteData {
|
||||
const FIELD_NAME: FieldName = CLEAR_SITE_DATA;
|
||||
|
||||
fn header_value(&self) -> HeaderValue {
|
||||
fn field_value(&self) -> FieldValue {
|
||||
let mut output = String::new();
|
||||
for (n, etag) in self.entries.iter().enumerate() {
|
||||
match n {
|
||||
|
@ -233,7 +231,7 @@ impl Header for ClearSiteData {
|
|||
}
|
||||
|
||||
// SAFETY: the internal string is validated to be ASCII.
|
||||
unsafe { HeaderValue::from_bytes_unchecked(output.into()) }
|
||||
unsafe { FieldValue::from_bytes_unchecked(output.into()) }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -250,7 +248,7 @@ mod test {
|
|||
entries.push(ClearDirective::Cookies);
|
||||
|
||||
let mut res = Response::new(200);
|
||||
entries.apply_header(&mut res);
|
||||
res.insert_typed_header(entries);
|
||||
|
||||
let entries = ClearSiteData::from_headers(res)?.unwrap();
|
||||
let mut entries = entries.iter();
|
||||
|
@ -266,7 +264,7 @@ mod test {
|
|||
entries.set_wildcard(true);
|
||||
|
||||
let mut res = Response::new(200);
|
||||
entries.apply_header(&mut res);
|
||||
res.insert_typed_header(entries);
|
||||
|
||||
let entries = ClearSiteData::from_headers(res)?.unwrap();
|
||||
assert!(entries.wildcard());
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use crate::headers::{Header, HeaderName, HeaderValue, Headers, EXPIRES};
|
||||
use crate::headers::{Field, FieldName, FieldValue, Fields, EXPIRES};
|
||||
use crate::utils::{fmt_http_date, parse_http_date};
|
||||
|
||||
use std::fmt::Debug;
|
||||
|
@ -56,7 +56,7 @@ impl Expires {
|
|||
}
|
||||
|
||||
/// Create an instance of `Expires` from a `Headers` instance.
|
||||
pub fn from_headers(headers: impl AsRef<Headers>) -> crate::Result<Option<Self>> {
|
||||
pub fn from_headers(headers: impl AsRef<Fields>) -> crate::Result<Option<Self>> {
|
||||
let headers = match headers.as_ref().get(EXPIRES) {
|
||||
Some(headers) => headers,
|
||||
None => return Ok(None),
|
||||
|
@ -71,30 +71,28 @@ impl Expires {
|
|||
}
|
||||
}
|
||||
|
||||
impl Header for Expires {
|
||||
fn header_name(&self) -> HeaderName {
|
||||
EXPIRES
|
||||
}
|
||||
fn header_value(&self) -> HeaderValue {
|
||||
impl Field for Expires {
|
||||
const FIELD_NAME: FieldName = EXPIRES;
|
||||
fn field_value(&self) -> FieldValue {
|
||||
let output = fmt_http_date(self.instant);
|
||||
|
||||
// SAFETY: the internal string is validated to be ASCII.
|
||||
unsafe { HeaderValue::from_bytes_unchecked(output.into()) }
|
||||
unsafe { FieldValue::from_bytes_unchecked(output.into()) }
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use crate::headers::Headers;
|
||||
use crate::headers::Fields;
|
||||
|
||||
#[test]
|
||||
fn smoke() -> crate::Result<()> {
|
||||
let time = SystemTime::now() + Duration::from_secs(5 * 60);
|
||||
let expires = Expires::new_at(time);
|
||||
|
||||
let mut headers = Headers::new();
|
||||
headers.insert(expires);
|
||||
let mut headers = Fields::new();
|
||||
headers.insert_typed(expires);
|
||||
|
||||
let expires = Expires::from_headers(headers)?.unwrap();
|
||||
|
||||
|
@ -106,7 +104,7 @@ mod test {
|
|||
|
||||
#[test]
|
||||
fn bad_request_on_parse_error() {
|
||||
let mut headers = Headers::new();
|
||||
let mut headers = Fields::new();
|
||||
headers.insert(EXPIRES, "<nori ate the tag. yum.>").unwrap();
|
||||
let err = Expires::from_headers(headers).unwrap_err();
|
||||
assert_eq!(err.status(), 400);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use crate::headers::{Header, HeaderName, HeaderValue, Headers, ETAG};
|
||||
use crate::headers::{Field, FieldName, FieldValue, Fields, ETAG};
|
||||
use crate::{Error, StatusCode};
|
||||
|
||||
use std::fmt::{self, Debug, Display};
|
||||
|
@ -55,7 +55,7 @@ impl ETag {
|
|||
///
|
||||
/// Only a single ETag per resource is assumed to exist. If multiple ETag
|
||||
/// headers are found the last one is used.
|
||||
pub fn from_headers(headers: impl AsRef<Headers>) -> crate::Result<Option<Self>> {
|
||||
pub fn from_headers(headers: impl AsRef<Fields>) -> crate::Result<Option<Self>> {
|
||||
let headers = match headers.as_ref().get(ETAG) {
|
||||
Some(headers) => headers,
|
||||
None => return Ok(None),
|
||||
|
@ -112,14 +112,12 @@ impl ETag {
|
|||
}
|
||||
}
|
||||
|
||||
impl Header for ETag {
|
||||
fn header_name(&self) -> HeaderName {
|
||||
ETAG
|
||||
}
|
||||
fn header_value(&self) -> HeaderValue {
|
||||
impl Field for ETag {
|
||||
const FIELD_NAME: FieldName = ETAG;
|
||||
fn field_value(&self) -> FieldValue {
|
||||
let s = self.to_string();
|
||||
// SAFETY: the internal string is validated to be ASCII.
|
||||
unsafe { HeaderValue::from_bytes_unchecked(s.into()) }
|
||||
unsafe { FieldValue::from_bytes_unchecked(s.into()) }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -135,14 +133,14 @@ impl Display for ETag {
|
|||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use crate::headers::Headers;
|
||||
use crate::headers::Fields;
|
||||
|
||||
#[test]
|
||||
fn smoke() -> crate::Result<()> {
|
||||
let etag = ETag::new("0xcafebeef".to_string());
|
||||
|
||||
let mut headers = Headers::new();
|
||||
headers.insert(etag);
|
||||
let mut headers = Fields::new();
|
||||
headers.insert_typed(etag);
|
||||
|
||||
let etag = ETag::from_headers(headers)?.unwrap();
|
||||
assert_eq!(etag, ETag::Strong(String::from("0xcafebeef")));
|
||||
|
@ -153,8 +151,8 @@ mod test {
|
|||
fn smoke_weak() -> crate::Result<()> {
|
||||
let etag = ETag::new_weak("0xcafebeef".to_string());
|
||||
|
||||
let mut headers = Headers::new();
|
||||
headers.insert(etag);
|
||||
let mut headers = Fields::new();
|
||||
headers.insert_typed(etag);
|
||||
|
||||
let etag = ETag::from_headers(headers)?.unwrap();
|
||||
assert_eq!(etag, ETag::Weak(String::from("0xcafebeef")));
|
||||
|
@ -163,7 +161,7 @@ mod test {
|
|||
|
||||
#[test]
|
||||
fn bad_request_on_parse_error() {
|
||||
let mut headers = Headers::new();
|
||||
let mut headers = Fields::new();
|
||||
headers.insert(ETAG, "<nori ate the tag. yum.>").unwrap();
|
||||
let err = ETag::from_headers(headers).unwrap_err();
|
||||
assert_eq!(err.status(), 400);
|
||||
|
@ -178,7 +176,7 @@ mod test {
|
|||
}
|
||||
|
||||
fn assert_entry_err(s: &str, msg: &str) {
|
||||
let mut headers = Headers::new();
|
||||
let mut headers = Fields::new();
|
||||
headers.insert(ETAG, s).unwrap();
|
||||
let err = ETag::from_headers(headers).unwrap_err();
|
||||
assert_eq!(format!("{}", err), msg);
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
//! Apply the HTTP method if the ETag matches.
|
||||
|
||||
use crate::headers::{HeaderName, HeaderValue, Headers, IF_MATCH};
|
||||
use crate::{conditional::ETag, headers::Header};
|
||||
use crate::headers::{FieldName, FieldValue, Fields, IF_MATCH};
|
||||
use crate::{conditional::ETag, headers::Field};
|
||||
|
||||
use std::fmt::{self, Debug, Write};
|
||||
use std::iter::Iterator;
|
||||
|
@ -51,7 +51,7 @@ impl IfMatch {
|
|||
}
|
||||
|
||||
/// Create a new instance from headers.
|
||||
pub fn from_headers(headers: impl AsRef<Headers>) -> crate::Result<Option<Self>> {
|
||||
pub fn from_headers(headers: impl AsRef<Fields>) -> crate::Result<Option<Self>> {
|
||||
let mut entries = vec![];
|
||||
let headers = match headers.as_ref().get(IF_MATCH) {
|
||||
Some(headers) => headers,
|
||||
|
@ -103,11 +103,9 @@ impl IfMatch {
|
|||
}
|
||||
}
|
||||
|
||||
impl Header for IfMatch {
|
||||
fn header_name(&self) -> HeaderName {
|
||||
IF_MATCH
|
||||
}
|
||||
fn header_value(&self) -> HeaderValue {
|
||||
impl Field for IfMatch {
|
||||
const FIELD_NAME: FieldName = IF_MATCH;
|
||||
fn field_value(&self) -> FieldValue {
|
||||
let mut output = String::new();
|
||||
for (n, etag) in self.entries.iter().enumerate() {
|
||||
match n {
|
||||
|
@ -124,7 +122,7 @@ impl Header for IfMatch {
|
|||
}
|
||||
|
||||
// SAFETY: the internal string is validated to be ASCII.
|
||||
unsafe { HeaderValue::from_bytes_unchecked(output.into()) }
|
||||
unsafe { FieldValue::from_bytes_unchecked(output.into()) }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -240,7 +238,7 @@ mod test {
|
|||
entries.push(ETag::new("0xbeefcafe".to_string()));
|
||||
|
||||
let mut res = Response::new(200);
|
||||
entries.apply_header(&mut res);
|
||||
res.insert_typed_header(entries);
|
||||
|
||||
let entries = IfMatch::from_headers(res)?.unwrap();
|
||||
let mut entries = entries.iter();
|
||||
|
@ -262,7 +260,7 @@ mod test {
|
|||
entries.set_wildcard(true);
|
||||
|
||||
let mut res = Response::new(200);
|
||||
entries.apply_header(&mut res);
|
||||
res.insert_typed_header(entries);
|
||||
|
||||
let entries = IfMatch::from_headers(res)?.unwrap();
|
||||
assert!(entries.wildcard());
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use crate::headers::{Header, HeaderName, HeaderValue, Headers, IF_MODIFIED_SINCE};
|
||||
use crate::headers::{Field, FieldName, FieldValue, Fields, IF_MODIFIED_SINCE};
|
||||
use crate::utils::{fmt_http_date, parse_http_date};
|
||||
|
||||
use std::fmt::Debug;
|
||||
|
@ -52,7 +52,7 @@ impl IfModifiedSince {
|
|||
}
|
||||
|
||||
/// Create an instance of `IfModifiedSince` from a `Headers` instance.
|
||||
pub fn from_headers(headers: impl AsRef<Headers>) -> crate::Result<Option<Self>> {
|
||||
pub fn from_headers(headers: impl AsRef<Fields>) -> crate::Result<Option<Self>> {
|
||||
let headers = match headers.as_ref().get(IF_MODIFIED_SINCE) {
|
||||
Some(headers) => headers,
|
||||
None => return Ok(None),
|
||||
|
@ -67,22 +67,20 @@ impl IfModifiedSince {
|
|||
}
|
||||
}
|
||||
|
||||
impl Header for IfModifiedSince {
|
||||
fn header_name(&self) -> HeaderName {
|
||||
IF_MODIFIED_SINCE
|
||||
}
|
||||
fn header_value(&self) -> HeaderValue {
|
||||
impl Field for IfModifiedSince {
|
||||
const FIELD_NAME: FieldName = IF_MODIFIED_SINCE;
|
||||
fn field_value(&self) -> FieldValue {
|
||||
let output = fmt_http_date(self.instant);
|
||||
|
||||
// SAFETY: the internal string is validated to be ASCII.
|
||||
unsafe { HeaderValue::from_bytes_unchecked(output.into()) }
|
||||
unsafe { FieldValue::from_bytes_unchecked(output.into()) }
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use crate::headers::Headers;
|
||||
use crate::headers::Fields;
|
||||
use std::time::Duration;
|
||||
|
||||
#[test]
|
||||
|
@ -90,8 +88,8 @@ mod test {
|
|||
let time = SystemTime::now() + Duration::from_secs(5 * 60);
|
||||
let expires = IfModifiedSince::new(time);
|
||||
|
||||
let mut headers = Headers::new();
|
||||
headers.insert(expires);
|
||||
let mut headers = Fields::new();
|
||||
headers.insert_typed(expires);
|
||||
|
||||
let expires = IfModifiedSince::from_headers(headers)?.unwrap();
|
||||
|
||||
|
@ -103,7 +101,7 @@ mod test {
|
|||
|
||||
#[test]
|
||||
fn bad_request_on_parse_error() {
|
||||
let mut headers = Headers::new();
|
||||
let mut headers = Fields::new();
|
||||
headers
|
||||
.insert(IF_MODIFIED_SINCE, "<nori ate the tag. yum.>")
|
||||
.unwrap();
|
||||
|
|
|
@ -3,8 +3,8 @@
|
|||
//! This is used to update caches or to prevent uploading a new resource when
|
||||
//! one already exists.
|
||||
|
||||
use crate::headers::{HeaderName, HeaderValue, Headers, IF_NONE_MATCH};
|
||||
use crate::{conditional::ETag, headers::Header};
|
||||
use crate::headers::{FieldName, FieldValue, Fields, IF_NONE_MATCH};
|
||||
use crate::{conditional::ETag, headers::Field};
|
||||
|
||||
use std::fmt::{self, Debug, Write};
|
||||
use std::iter::Iterator;
|
||||
|
@ -57,7 +57,7 @@ impl IfNoneMatch {
|
|||
}
|
||||
|
||||
/// Create a new instance from headers.
|
||||
pub fn from_headers(headers: impl AsRef<Headers>) -> crate::Result<Option<Self>> {
|
||||
pub fn from_headers(headers: impl AsRef<Fields>) -> crate::Result<Option<Self>> {
|
||||
let mut entries = vec![];
|
||||
let headers = match headers.as_ref().get(IF_NONE_MATCH) {
|
||||
Some(headers) => headers,
|
||||
|
@ -109,11 +109,9 @@ impl IfNoneMatch {
|
|||
}
|
||||
}
|
||||
|
||||
impl Header for IfNoneMatch {
|
||||
fn header_name(&self) -> HeaderName {
|
||||
IF_NONE_MATCH
|
||||
}
|
||||
fn header_value(&self) -> HeaderValue {
|
||||
impl Field for IfNoneMatch {
|
||||
const FIELD_NAME: FieldName = IF_NONE_MATCH;
|
||||
fn field_value(&self) -> FieldValue {
|
||||
let mut output = String::new();
|
||||
for (n, etag) in self.entries.iter().enumerate() {
|
||||
match n {
|
||||
|
@ -130,7 +128,7 @@ impl Header for IfNoneMatch {
|
|||
}
|
||||
|
||||
// SAFETY: the internal string is validated to be ASCII.
|
||||
unsafe { HeaderValue::from_bytes_unchecked(output.into()) }
|
||||
unsafe { FieldValue::from_bytes_unchecked(output.into()) }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -246,7 +244,7 @@ mod test {
|
|||
entries.push(ETag::new("0xbeefcafe".to_string()));
|
||||
|
||||
let mut res = Response::new(200);
|
||||
entries.apply_header(&mut res);
|
||||
res.insert_typed_header(entries);
|
||||
|
||||
let entries = IfNoneMatch::from_headers(res)?.unwrap();
|
||||
let mut entries = entries.iter();
|
||||
|
@ -268,7 +266,7 @@ mod test {
|
|||
entries.set_wildcard(true);
|
||||
|
||||
let mut res = Response::new(200);
|
||||
entries.apply_header(&mut res);
|
||||
res.insert_typed_header(entries);
|
||||
|
||||
let entries = IfNoneMatch::from_headers(res)?.unwrap();
|
||||
assert!(entries.wildcard());
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use crate::headers::{Header, HeaderName, HeaderValue, Headers, IF_UNMODIFIED_SINCE};
|
||||
use crate::headers::{Field, FieldName, FieldValue, Fields, IF_UNMODIFIED_SINCE};
|
||||
use crate::utils::{fmt_http_date, parse_http_date};
|
||||
|
||||
use std::fmt::Debug;
|
||||
|
@ -52,7 +52,7 @@ impl IfUnmodifiedSince {
|
|||
}
|
||||
|
||||
/// Create an instance of `IfUnmodifiedSince` from a `Headers` instance.
|
||||
pub fn from_headers(headers: impl AsRef<Headers>) -> crate::Result<Option<Self>> {
|
||||
pub fn from_headers(headers: impl AsRef<Fields>) -> crate::Result<Option<Self>> {
|
||||
let headers = match headers.as_ref().get(IF_UNMODIFIED_SINCE) {
|
||||
Some(headers) => headers,
|
||||
None => return Ok(None),
|
||||
|
@ -67,22 +67,20 @@ impl IfUnmodifiedSince {
|
|||
}
|
||||
}
|
||||
|
||||
impl Header for IfUnmodifiedSince {
|
||||
fn header_name(&self) -> HeaderName {
|
||||
IF_UNMODIFIED_SINCE
|
||||
}
|
||||
fn header_value(&self) -> HeaderValue {
|
||||
impl Field for IfUnmodifiedSince {
|
||||
const FIELD_NAME: FieldName = IF_UNMODIFIED_SINCE;
|
||||
fn field_value(&self) -> FieldValue {
|
||||
let output = fmt_http_date(self.instant);
|
||||
|
||||
// SAFETY: the internal string is validated to be ASCII.
|
||||
unsafe { HeaderValue::from_bytes_unchecked(output.into()) }
|
||||
unsafe { FieldValue::from_bytes_unchecked(output.into()) }
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use crate::headers::Headers;
|
||||
use crate::headers::Fields;
|
||||
use std::time::Duration;
|
||||
|
||||
#[test]
|
||||
|
@ -90,8 +88,8 @@ mod test {
|
|||
let time = SystemTime::now() + Duration::from_secs(5 * 60);
|
||||
let expires = IfUnmodifiedSince::new(time);
|
||||
|
||||
let mut headers = Headers::new();
|
||||
headers.insert(expires);
|
||||
let mut headers = Fields::new();
|
||||
headers.insert_typed(expires);
|
||||
|
||||
let expires = IfUnmodifiedSince::from_headers(headers)?.unwrap();
|
||||
|
||||
|
@ -103,7 +101,7 @@ mod test {
|
|||
|
||||
#[test]
|
||||
fn bad_request_on_parse_error() {
|
||||
let mut headers = Headers::new();
|
||||
let mut headers = Fields::new();
|
||||
headers
|
||||
.insert(IF_UNMODIFIED_SINCE, "<nori ate the tag. yum.>")
|
||||
.unwrap();
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use crate::headers::{Header, HeaderName, HeaderValue, Headers, LAST_MODIFIED};
|
||||
use crate::headers::{Field, FieldName, FieldValue, Fields, LAST_MODIFIED};
|
||||
use crate::utils::{fmt_http_date, parse_http_date};
|
||||
|
||||
use std::fmt::Debug;
|
||||
|
@ -51,7 +51,7 @@ impl LastModified {
|
|||
}
|
||||
|
||||
/// Create an instance of `LastModified` from a `Headers` instance.
|
||||
pub fn from_headers(headers: impl AsRef<Headers>) -> crate::Result<Option<Self>> {
|
||||
pub fn from_headers(headers: impl AsRef<Fields>) -> crate::Result<Option<Self>> {
|
||||
let headers = match headers.as_ref().get(LAST_MODIFIED) {
|
||||
Some(headers) => headers,
|
||||
None => return Ok(None),
|
||||
|
@ -66,22 +66,20 @@ impl LastModified {
|
|||
}
|
||||
}
|
||||
|
||||
impl Header for LastModified {
|
||||
fn header_name(&self) -> HeaderName {
|
||||
LAST_MODIFIED
|
||||
}
|
||||
fn header_value(&self) -> HeaderValue {
|
||||
impl Field for LastModified {
|
||||
const FIELD_NAME: FieldName = LAST_MODIFIED;
|
||||
fn field_value(&self) -> FieldValue {
|
||||
let output = fmt_http_date(self.instant);
|
||||
|
||||
// SAFETY: the internal string is validated to be ASCII.
|
||||
unsafe { HeaderValue::from_bytes_unchecked(output.into()) }
|
||||
unsafe { FieldValue::from_bytes_unchecked(output.into()) }
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use crate::headers::Headers;
|
||||
use crate::headers::Fields;
|
||||
use std::time::Duration;
|
||||
|
||||
#[test]
|
||||
|
@ -89,8 +87,8 @@ mod test {
|
|||
let time = SystemTime::now() + Duration::from_secs(5 * 60);
|
||||
let last_modified = LastModified::new(time);
|
||||
|
||||
let mut headers = Headers::new();
|
||||
last_headers.insert(modified);
|
||||
let mut headers = Fields::new();
|
||||
headers.insert_typed(last_modified);
|
||||
|
||||
let last_modified = LastModified::from_headers(headers)?.unwrap();
|
||||
|
||||
|
@ -102,7 +100,7 @@ mod test {
|
|||
|
||||
#[test]
|
||||
fn bad_request_on_parse_error() {
|
||||
let mut headers = Headers::new();
|
||||
let mut headers = Fields::new();
|
||||
headers
|
||||
.insert(LAST_MODIFIED, "<nori ate the tag. yum.>")
|
||||
.unwrap();
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
//! Apply the HTTP method if the ETag matches.
|
||||
|
||||
use crate::headers::{Header, HeaderName, HeaderValue, Headers, VARY};
|
||||
use crate::headers::{Field, FieldName, FieldValue, Fields, VARY};
|
||||
|
||||
use std::fmt::{self, Debug, Write};
|
||||
use std::iter::Iterator;
|
||||
|
@ -37,7 +37,7 @@ use std::str::FromStr;
|
|||
/// # Ok(()) }
|
||||
/// ```
|
||||
pub struct Vary {
|
||||
entries: Vec<HeaderName>,
|
||||
entries: Vec<FieldName>,
|
||||
wildcard: bool,
|
||||
}
|
||||
|
||||
|
@ -51,7 +51,7 @@ impl Vary {
|
|||
}
|
||||
|
||||
/// Create a new instance from headers.
|
||||
pub fn from_headers(headers: impl AsRef<Headers>) -> crate::Result<Option<Self>> {
|
||||
pub fn from_headers(headers: impl AsRef<Fields>) -> crate::Result<Option<Self>> {
|
||||
let mut entries = vec![];
|
||||
let headers = match headers.as_ref().get(VARY) {
|
||||
Some(headers) => headers,
|
||||
|
@ -66,7 +66,7 @@ impl Vary {
|
|||
wildcard = true;
|
||||
continue;
|
||||
}
|
||||
let entry = HeaderName::from_str(part.trim())?;
|
||||
let entry = FieldName::from_str(part.trim())?;
|
||||
entries.push(entry);
|
||||
}
|
||||
}
|
||||
|
@ -85,7 +85,7 @@ impl Vary {
|
|||
}
|
||||
|
||||
/// Push a directive into the list of entries.
|
||||
pub fn push(&mut self, directive: impl Into<HeaderName>) -> crate::Result<()> {
|
||||
pub fn push(&mut self, directive: impl Into<FieldName>) -> crate::Result<()> {
|
||||
self.entries.push(directive.into());
|
||||
Ok(())
|
||||
}
|
||||
|
@ -105,15 +105,13 @@ impl Vary {
|
|||
}
|
||||
}
|
||||
|
||||
impl Header for Vary {
|
||||
fn header_name(&self) -> HeaderName {
|
||||
VARY
|
||||
}
|
||||
impl Field for Vary {
|
||||
const FIELD_NAME: FieldName = VARY;
|
||||
|
||||
fn header_value(&self) -> HeaderValue {
|
||||
fn field_value(&self) -> FieldValue {
|
||||
let mut output = String::new();
|
||||
for (n, name) in self.entries.iter().enumerate() {
|
||||
let directive: HeaderValue = name
|
||||
let directive: FieldValue = name
|
||||
.as_str()
|
||||
.parse()
|
||||
.expect("Could not convert a HeaderName into a HeaderValue");
|
||||
|
@ -131,12 +129,12 @@ impl Header for Vary {
|
|||
}
|
||||
|
||||
// SAFETY: the internal string is validated to be ASCII.
|
||||
unsafe { HeaderValue::from_bytes_unchecked(output.into()) }
|
||||
unsafe { FieldValue::from_bytes_unchecked(output.into()) }
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoIterator for Vary {
|
||||
type Item = HeaderName;
|
||||
type Item = FieldName;
|
||||
type IntoIter = IntoIter;
|
||||
|
||||
#[inline]
|
||||
|
@ -148,7 +146,7 @@ impl IntoIterator for Vary {
|
|||
}
|
||||
|
||||
impl<'a> IntoIterator for &'a Vary {
|
||||
type Item = &'a HeaderName;
|
||||
type Item = &'a FieldName;
|
||||
type IntoIter = Iter<'a>;
|
||||
|
||||
#[inline]
|
||||
|
@ -158,7 +156,7 @@ impl<'a> IntoIterator for &'a Vary {
|
|||
}
|
||||
|
||||
impl<'a> IntoIterator for &'a mut Vary {
|
||||
type Item = &'a mut HeaderName;
|
||||
type Item = &'a mut FieldName;
|
||||
type IntoIter = IterMut<'a>;
|
||||
|
||||
#[inline]
|
||||
|
@ -170,11 +168,11 @@ impl<'a> IntoIterator for &'a mut Vary {
|
|||
/// A borrowing iterator over entries in `Vary`.
|
||||
#[derive(Debug)]
|
||||
pub struct IntoIter {
|
||||
inner: std::vec::IntoIter<HeaderName>,
|
||||
inner: std::vec::IntoIter<FieldName>,
|
||||
}
|
||||
|
||||
impl Iterator for IntoIter {
|
||||
type Item = HeaderName;
|
||||
type Item = FieldName;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
self.inner.next()
|
||||
|
@ -189,11 +187,11 @@ impl Iterator for IntoIter {
|
|||
/// A lending iterator over entries in `Vary`.
|
||||
#[derive(Debug)]
|
||||
pub struct Iter<'a> {
|
||||
inner: slice::Iter<'a, HeaderName>,
|
||||
inner: slice::Iter<'a, FieldName>,
|
||||
}
|
||||
|
||||
impl<'a> Iterator for Iter<'a> {
|
||||
type Item = &'a HeaderName;
|
||||
type Item = &'a FieldName;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
self.inner.next()
|
||||
|
@ -208,11 +206,11 @@ impl<'a> Iterator for Iter<'a> {
|
|||
/// A mutable iterator over entries in `Vary`.
|
||||
#[derive(Debug)]
|
||||
pub struct IterMut<'a> {
|
||||
inner: slice::IterMut<'a, HeaderName>,
|
||||
inner: slice::IterMut<'a, FieldName>,
|
||||
}
|
||||
|
||||
impl<'a> Iterator for IterMut<'a> {
|
||||
type Item = &'a mut HeaderName;
|
||||
type Item = &'a mut FieldName;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
self.inner.next()
|
||||
|
@ -247,7 +245,7 @@ mod test {
|
|||
entries.push("Accept-Encoding")?;
|
||||
|
||||
let mut res = Response::new(200);
|
||||
entries.apply_header(&mut res);
|
||||
res.insert_typed_header(entries);
|
||||
|
||||
let entries = Vary::from_headers(res)?.unwrap();
|
||||
let mut entries = entries.iter();
|
||||
|
@ -263,7 +261,7 @@ mod test {
|
|||
entries.set_wildcard(true);
|
||||
|
||||
let mut res = Response::new(200);
|
||||
entries.apply_header(&mut res);
|
||||
res.insert_typed_header(entries);
|
||||
|
||||
let entries = Vary::from_headers(res)?.unwrap();
|
||||
assert!(entries.wildcard());
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
//! Client header advertising which media types the client is able to understand.
|
||||
|
||||
use crate::headers::{HeaderName, HeaderValue, Headers, ACCEPT};
|
||||
use crate::headers::{FieldName, FieldValue, Fields, ACCEPT};
|
||||
use crate::mime::Mime;
|
||||
use crate::utils::sort_by_weight;
|
||||
use crate::{
|
||||
content::{ContentType, MediaTypeProposal},
|
||||
headers::Header,
|
||||
headers::Field,
|
||||
};
|
||||
use crate::{Error, StatusCode};
|
||||
|
||||
|
@ -63,7 +63,7 @@ impl Accept {
|
|||
}
|
||||
|
||||
/// Create an instance of `Accept` from a `Headers` instance.
|
||||
pub fn from_headers(headers: impl AsRef<Headers>) -> crate::Result<Option<Self>> {
|
||||
pub fn from_headers(headers: impl AsRef<Fields>) -> crate::Result<Option<Self>> {
|
||||
let mut entries = vec![];
|
||||
let headers = match headers.as_ref().get(ACCEPT) {
|
||||
Some(headers) => headers,
|
||||
|
@ -161,14 +161,12 @@ impl Accept {
|
|||
}
|
||||
}
|
||||
|
||||
impl Header for Accept {
|
||||
fn header_name(&self) -> HeaderName {
|
||||
ACCEPT
|
||||
}
|
||||
fn header_value(&self) -> HeaderValue {
|
||||
impl Field for Accept {
|
||||
const FIELD_NAME: FieldName = ACCEPT;
|
||||
fn field_value(&self) -> FieldValue {
|
||||
let mut output = String::new();
|
||||
for (n, directive) in self.entries.iter().enumerate() {
|
||||
let directive: HeaderValue = directive.clone().into();
|
||||
let directive: FieldValue = directive.clone().into();
|
||||
match n {
|
||||
0 => write!(output, "{}", directive).unwrap(),
|
||||
_ => write!(output, ", {}", directive).unwrap(),
|
||||
|
@ -183,7 +181,7 @@ impl Header for Accept {
|
|||
}
|
||||
|
||||
// SAFETY: the internal string is validated to be ASCII.
|
||||
unsafe { HeaderValue::from_bytes_unchecked(output.into()) }
|
||||
unsafe { FieldValue::from_bytes_unchecked(output.into()) }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -298,7 +296,7 @@ mod test {
|
|||
accept.push(mime::HTML);
|
||||
|
||||
let mut headers = Response::new(200);
|
||||
headers.insert(accept);
|
||||
headers.insert_typed_header(accept);
|
||||
|
||||
let accept = Accept::from_headers(headers)?.unwrap();
|
||||
assert_eq!(accept.iter().next().unwrap(), mime::HTML);
|
||||
|
@ -311,7 +309,7 @@ mod test {
|
|||
accept.set_wildcard(true);
|
||||
|
||||
let mut headers = Response::new(200);
|
||||
headers.insert(accept);
|
||||
headers.insert_typed_header(accept);
|
||||
|
||||
let accept = Accept::from_headers(headers)?.unwrap();
|
||||
assert!(accept.wildcard());
|
||||
|
@ -325,7 +323,7 @@ mod test {
|
|||
accept.set_wildcard(true);
|
||||
|
||||
let mut headers = Response::new(200);
|
||||
headers.insert(accept);
|
||||
headers.insert_typed_header(accept);
|
||||
|
||||
let accept = Accept::from_headers(headers)?.unwrap();
|
||||
assert!(accept.wildcard());
|
||||
|
@ -340,7 +338,7 @@ mod test {
|
|||
accept.push(mime::XML);
|
||||
|
||||
let mut headers = Response::new(200);
|
||||
headers.insert(accept);
|
||||
headers.insert_typed_header(accept);
|
||||
|
||||
let accept = Accept::from_headers(headers)?.unwrap();
|
||||
let mut accept = accept.iter();
|
||||
|
@ -357,7 +355,7 @@ mod test {
|
|||
accept.push(MediaTypeProposal::new(mime::PLAIN, Some(0.8))?);
|
||||
|
||||
let mut headers = Response::new(200);
|
||||
headers.insert(accept);
|
||||
headers.insert_typed_header(accept);
|
||||
|
||||
let mut accept = Accept::from_headers(headers)?.unwrap();
|
||||
accept.sort();
|
||||
|
@ -376,7 +374,7 @@ mod test {
|
|||
accept.push(MediaTypeProposal::new(mime::PLAIN, Some(0.8))?);
|
||||
|
||||
let mut res = Response::new(200);
|
||||
accept.apply_header(&mut res);
|
||||
res.insert_typed_header(accept);
|
||||
|
||||
let mut accept = Accept::from_headers(res)?.unwrap();
|
||||
accept.sort();
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
//! Client header advertising available compression algorithms.
|
||||
|
||||
use crate::headers::{HeaderName, HeaderValue, Headers, ACCEPT_ENCODING};
|
||||
use crate::headers::{FieldName, FieldValue, Fields, ACCEPT_ENCODING};
|
||||
use crate::utils::sort_by_weight;
|
||||
use crate::{
|
||||
content::{ContentEncoding, Encoding, EncodingProposal},
|
||||
headers::Header,
|
||||
headers::Field,
|
||||
};
|
||||
use crate::{Error, StatusCode};
|
||||
|
||||
|
@ -54,7 +54,7 @@ impl AcceptEncoding {
|
|||
}
|
||||
|
||||
/// Create an instance of `AcceptEncoding` from a `Headers` instance.
|
||||
pub fn from_headers(headers: impl AsRef<Headers>) -> crate::Result<Option<Self>> {
|
||||
pub fn from_headers(headers: impl AsRef<Fields>) -> crate::Result<Option<Self>> {
|
||||
let mut entries = vec![];
|
||||
let headers = match headers.as_ref().get(ACCEPT_ENCODING) {
|
||||
Some(headers) => headers,
|
||||
|
@ -153,15 +153,13 @@ impl AcceptEncoding {
|
|||
}
|
||||
}
|
||||
|
||||
impl Header for AcceptEncoding {
|
||||
fn header_name(&self) -> HeaderName {
|
||||
ACCEPT_ENCODING
|
||||
}
|
||||
impl Field for AcceptEncoding {
|
||||
const FIELD_NAME: FieldName = ACCEPT_ENCODING;
|
||||
|
||||
fn header_value(&self) -> HeaderValue {
|
||||
fn field_value(&self) -> FieldValue {
|
||||
let mut output = String::new();
|
||||
for (n, directive) in self.entries.iter().enumerate() {
|
||||
let directive: HeaderValue = (*directive).into();
|
||||
let directive: FieldValue = (*directive).into();
|
||||
match n {
|
||||
0 => write!(output, "{}", directive).unwrap(),
|
||||
_ => write!(output, ", {}", directive).unwrap(),
|
||||
|
@ -176,7 +174,7 @@ impl Header for AcceptEncoding {
|
|||
}
|
||||
|
||||
// SAFETY: the internal string is validated to be ASCII.
|
||||
unsafe { HeaderValue::from_bytes_unchecked(output.into()) }
|
||||
unsafe { FieldValue::from_bytes_unchecked(output.into()) }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -291,7 +289,7 @@ mod test {
|
|||
accept.push(Encoding::Gzip);
|
||||
|
||||
let mut headers = Response::new(200);
|
||||
headers.insert(accept);
|
||||
headers.insert_typed_header(accept);
|
||||
|
||||
let accept = AcceptEncoding::from_headers(headers)?.unwrap();
|
||||
assert_eq!(accept.iter().next().unwrap(), Encoding::Gzip);
|
||||
|
@ -304,7 +302,7 @@ mod test {
|
|||
accept.set_wildcard(true);
|
||||
|
||||
let mut headers = Response::new(200);
|
||||
headers.insert(accept);
|
||||
headers.insert_typed_header(accept);
|
||||
|
||||
let accept = AcceptEncoding::from_headers(headers)?.unwrap();
|
||||
assert!(accept.wildcard());
|
||||
|
@ -318,7 +316,7 @@ mod test {
|
|||
accept.set_wildcard(true);
|
||||
|
||||
let mut headers = Response::new(200);
|
||||
headers.insert(accept);
|
||||
headers.insert_typed_header(accept);
|
||||
|
||||
let accept = AcceptEncoding::from_headers(headers)?.unwrap();
|
||||
assert!(accept.wildcard());
|
||||
|
@ -333,7 +331,7 @@ mod test {
|
|||
accept.push(Encoding::Brotli);
|
||||
|
||||
let mut headers = Response::new(200);
|
||||
headers.insert(accept);
|
||||
headers.insert_typed_header(accept);
|
||||
|
||||
let accept = AcceptEncoding::from_headers(headers)?.unwrap();
|
||||
let mut accept = accept.iter();
|
||||
|
@ -350,7 +348,7 @@ mod test {
|
|||
accept.push(EncodingProposal::new(Encoding::Brotli, Some(0.8))?);
|
||||
|
||||
let mut headers = Response::new(200);
|
||||
headers.insert(accept);
|
||||
headers.insert_typed_header(accept);
|
||||
|
||||
let mut accept = AcceptEncoding::from_headers(headers)?.unwrap();
|
||||
accept.sort();
|
||||
|
@ -369,7 +367,7 @@ mod test {
|
|||
accept.push(EncodingProposal::new(Encoding::Brotli, Some(0.8))?);
|
||||
|
||||
let mut res = Response::new(200);
|
||||
accept.apply_header(&mut res);
|
||||
res.insert_typed_header(accept);
|
||||
|
||||
let mut accept = AcceptEncoding::from_headers(res)?.unwrap();
|
||||
accept.sort();
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
//! Specify the compression algorithm.
|
||||
|
||||
use crate::headers::{HeaderName, HeaderValue, Headers, CONTENT_ENCODING};
|
||||
use crate::headers::{FieldName, FieldValue, Fields, CONTENT_ENCODING};
|
||||
use crate::{
|
||||
content::{Encoding, EncodingProposal},
|
||||
headers::Header,
|
||||
headers::Field,
|
||||
};
|
||||
|
||||
use std::fmt::{self, Debug};
|
||||
|
@ -43,7 +43,7 @@ impl ContentEncoding {
|
|||
}
|
||||
|
||||
/// Create a new instance from headers.
|
||||
pub fn from_headers(headers: impl AsRef<Headers>) -> crate::Result<Option<Self>> {
|
||||
pub fn from_headers(headers: impl AsRef<Fields>) -> crate::Result<Option<Self>> {
|
||||
let headers = match headers.as_ref().get(CONTENT_ENCODING) {
|
||||
Some(headers) => headers,
|
||||
None => return Ok(None),
|
||||
|
@ -67,11 +67,9 @@ impl ContentEncoding {
|
|||
}
|
||||
}
|
||||
|
||||
impl Header for ContentEncoding {
|
||||
fn header_name(&self) -> HeaderName {
|
||||
CONTENT_ENCODING
|
||||
}
|
||||
fn header_value(&self) -> HeaderValue {
|
||||
impl Field for ContentEncoding {
|
||||
const FIELD_NAME: FieldName = CONTENT_ENCODING;
|
||||
fn field_value(&self) -> FieldValue {
|
||||
self.inner.into()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use crate::headers::{Header, HeaderName, HeaderValue, Headers, CONTENT_LENGTH};
|
||||
use crate::headers::{Field, FieldName, FieldValue, Fields, CONTENT_LENGTH};
|
||||
use crate::Status;
|
||||
|
||||
/// The size of the entity-body, in bytes, sent to the recipient.
|
||||
|
@ -38,7 +38,7 @@ impl ContentLength {
|
|||
}
|
||||
|
||||
/// Create a new instance from headers.
|
||||
pub fn from_headers(headers: impl AsRef<Headers>) -> crate::Result<Option<Self>> {
|
||||
pub fn from_headers(headers: impl AsRef<Fields>) -> crate::Result<Option<Self>> {
|
||||
let headers = match headers.as_ref().get(CONTENT_LENGTH) {
|
||||
Some(headers) => headers,
|
||||
None => return Ok(None),
|
||||
|
@ -62,29 +62,27 @@ impl ContentLength {
|
|||
}
|
||||
}
|
||||
|
||||
impl Header for ContentLength {
|
||||
fn header_name(&self) -> HeaderName {
|
||||
CONTENT_LENGTH
|
||||
}
|
||||
fn header_value(&self) -> HeaderValue {
|
||||
impl Field for ContentLength {
|
||||
const FIELD_NAME: FieldName = CONTENT_LENGTH;
|
||||
fn field_value(&self) -> FieldValue {
|
||||
let output = format!("{}", self.length);
|
||||
|
||||
// SAFETY: the internal string is validated to be ASCII.
|
||||
unsafe { HeaderValue::from_bytes_unchecked(output.into()) }
|
||||
unsafe { FieldValue::from_bytes_unchecked(output.into()) }
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use crate::headers::Headers;
|
||||
use crate::headers::Fields;
|
||||
|
||||
#[test]
|
||||
fn smoke() -> crate::Result<()> {
|
||||
let content_len = ContentLength::new(12);
|
||||
|
||||
let mut headers = Headers::new();
|
||||
content_headers.insert(len);
|
||||
let mut headers = Fields::new();
|
||||
headers.insert_typed(content_len);
|
||||
|
||||
let content_len = ContentLength::from_headers(headers)?.unwrap();
|
||||
assert_eq!(content_len.len(), 12);
|
||||
|
@ -93,7 +91,7 @@ mod test {
|
|||
|
||||
#[test]
|
||||
fn bad_request_on_parse_error() {
|
||||
let mut headers = Headers::new();
|
||||
let mut headers = Fields::new();
|
||||
headers
|
||||
.insert(CONTENT_LENGTH, "<nori ate the tag. yum.>")
|
||||
.unwrap();
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use crate::headers::{Header, HeaderName, HeaderValue, Headers, CONTENT_LOCATION};
|
||||
use crate::headers::{Field, FieldName, FieldValue, Fields, CONTENT_LOCATION};
|
||||
use crate::{bail_status as bail, Status, Url};
|
||||
|
||||
use std::convert::TryInto;
|
||||
|
@ -42,7 +42,7 @@ impl ContentLocation {
|
|||
}
|
||||
|
||||
/// Create a new instance from headers.
|
||||
pub fn from_headers<U>(base_url: U, headers: impl AsRef<Headers>) -> crate::Result<Option<Self>>
|
||||
pub fn from_headers<U>(base_url: U, headers: impl AsRef<Fields>) -> crate::Result<Option<Self>>
|
||||
where
|
||||
U: TryInto<Url>,
|
||||
U::Error: std::fmt::Debug,
|
||||
|
@ -81,29 +81,27 @@ impl ContentLocation {
|
|||
}
|
||||
}
|
||||
|
||||
impl Header for ContentLocation {
|
||||
fn header_name(&self) -> HeaderName {
|
||||
CONTENT_LOCATION
|
||||
}
|
||||
fn header_value(&self) -> HeaderValue {
|
||||
impl Field for ContentLocation {
|
||||
const FIELD_NAME: FieldName = CONTENT_LOCATION;
|
||||
fn field_value(&self) -> FieldValue {
|
||||
let output = self.url.to_string();
|
||||
|
||||
// SAFETY: the internal string is validated to be ASCII.
|
||||
unsafe { HeaderValue::from_bytes_unchecked(output.into()) }
|
||||
unsafe { FieldValue::from_bytes_unchecked(output.into()) }
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use crate::headers::Headers;
|
||||
use crate::headers::Fields;
|
||||
|
||||
#[test]
|
||||
fn smoke() -> crate::Result<()> {
|
||||
let content_location = ContentLocation::new(Url::parse("https://example.net/test.json")?);
|
||||
|
||||
let mut headers = Headers::new();
|
||||
content_headers.insert(location);
|
||||
let mut headers = Fields::new();
|
||||
headers.insert_typed(content_location);
|
||||
|
||||
let content_location =
|
||||
ContentLocation::from_headers(Url::parse("https://example.net/").unwrap(), headers)?
|
||||
|
@ -117,7 +115,7 @@ mod test {
|
|||
|
||||
#[test]
|
||||
fn bad_request_on_parse_error() {
|
||||
let mut headers = Headers::new();
|
||||
let mut headers = Fields::new();
|
||||
headers
|
||||
.insert(CONTENT_LOCATION, "htt://<nori ate the tag. yum.>")
|
||||
.unwrap();
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use std::{convert::TryInto, str::FromStr};
|
||||
|
||||
use crate::headers::{Header, HeaderName, HeaderValue, Headers, CONTENT_TYPE};
|
||||
use crate::headers::{Field, FieldName, FieldValue, Fields, CONTENT_TYPE};
|
||||
use crate::mime::Mime;
|
||||
|
||||
/// Indicate the media type of a resource's content.
|
||||
|
@ -57,7 +57,7 @@ impl ContentType {
|
|||
/// order to always return fully qualified URLs, a base URL must be passed to
|
||||
/// reference the current environment. In HTTP/1.1 and above this value can
|
||||
/// always be determined from the request.
|
||||
pub fn from_headers(headers: impl AsRef<Headers>) -> crate::Result<Option<Self>> {
|
||||
pub fn from_headers(headers: impl AsRef<Fields>) -> crate::Result<Option<Self>> {
|
||||
let headers = match headers.as_ref().get(CONTENT_TYPE) {
|
||||
Some(headers) => headers,
|
||||
None => return Ok(None),
|
||||
|
@ -75,14 +75,12 @@ impl ContentType {
|
|||
}
|
||||
}
|
||||
|
||||
impl Header for ContentType {
|
||||
fn header_name(&self) -> HeaderName {
|
||||
CONTENT_TYPE
|
||||
}
|
||||
fn header_value(&self) -> HeaderValue {
|
||||
impl Field for ContentType {
|
||||
const FIELD_NAME: FieldName = CONTENT_TYPE;
|
||||
fn field_value(&self) -> FieldValue {
|
||||
let output = format!("{}", self.media_type);
|
||||
// SAFETY: the internal string is validated to be ASCII.
|
||||
unsafe { HeaderValue::from_bytes_unchecked(output.into()) }
|
||||
unsafe { FieldValue::from_bytes_unchecked(output.into()) }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -107,18 +105,18 @@ impl From<Mime> for ContentType {
|
|||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use crate::headers::Headers;
|
||||
use crate::headers::Fields;
|
||||
|
||||
#[test]
|
||||
fn smoke() -> crate::Result<()> {
|
||||
let ct = ContentType::new(Mime::from_str("text/*")?);
|
||||
|
||||
let mut headers = Headers::new();
|
||||
headers.insert(ct);
|
||||
let mut headers = Fields::new();
|
||||
headers.insert_typed(ct);
|
||||
|
||||
let ct = ContentType::from_headers(headers)?.unwrap();
|
||||
assert_eq!(
|
||||
ct.header_value(),
|
||||
ct.field_value(),
|
||||
format!("{}", Mime::from_str("text/*")?).as_str()
|
||||
);
|
||||
Ok(())
|
||||
|
@ -126,7 +124,7 @@ mod test {
|
|||
|
||||
#[test]
|
||||
fn bad_request_on_parse_error() {
|
||||
let mut headers = Headers::new();
|
||||
let mut headers = Fields::new();
|
||||
headers
|
||||
.insert(CONTENT_TYPE, "<nori ate the tag. yum.>")
|
||||
.unwrap();
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use crate::headers::HeaderValue;
|
||||
use crate::headers::FieldValue;
|
||||
use std::fmt::{self, Display};
|
||||
|
||||
/// Available compression algorithms.
|
||||
|
@ -50,9 +50,9 @@ impl Display for Encoding {
|
|||
}
|
||||
}
|
||||
|
||||
impl From<Encoding> for HeaderValue {
|
||||
impl From<Encoding> for FieldValue {
|
||||
fn from(directive: Encoding) -> Self {
|
||||
let s = directive.to_string();
|
||||
unsafe { HeaderValue::from_bytes_unchecked(s.into_bytes()) }
|
||||
unsafe { FieldValue::from_bytes_unchecked(s.into_bytes()) }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use crate::content::Encoding;
|
||||
use crate::ensure;
|
||||
use crate::headers::HeaderValue;
|
||||
use crate::headers::FieldValue;
|
||||
use crate::utils::parse_weight;
|
||||
|
||||
use std::cmp::{Ordering, PartialEq};
|
||||
|
@ -108,13 +108,13 @@ impl PartialOrd for EncodingProposal {
|
|||
}
|
||||
}
|
||||
|
||||
impl From<EncodingProposal> for HeaderValue {
|
||||
fn from(entry: EncodingProposal) -> HeaderValue {
|
||||
impl From<EncodingProposal> for FieldValue {
|
||||
fn from(entry: EncodingProposal) -> FieldValue {
|
||||
let s = match entry.weight {
|
||||
Some(weight) => format!("{};q={:.3}", entry.encoding, weight),
|
||||
None => entry.encoding.to_string(),
|
||||
};
|
||||
unsafe { HeaderValue::from_bytes_unchecked(s.into_bytes()) }
|
||||
unsafe { FieldValue::from_bytes_unchecked(s.into_bytes()) }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use crate::ensure;
|
||||
use crate::headers::HeaderValue;
|
||||
use crate::headers::FieldValue;
|
||||
use crate::mime::Mime;
|
||||
|
||||
use std::ops::{Deref, DerefMut};
|
||||
|
@ -125,13 +125,13 @@ impl PartialOrd for MediaTypeProposal {
|
|||
}
|
||||
}
|
||||
|
||||
impl From<MediaTypeProposal> for HeaderValue {
|
||||
fn from(entry: MediaTypeProposal) -> HeaderValue {
|
||||
impl From<MediaTypeProposal> for FieldValue {
|
||||
fn from(entry: MediaTypeProposal) -> FieldValue {
|
||||
let s = match entry.weight {
|
||||
Some(weight) => format!("{};q={:.3}", entry.media_type, weight),
|
||||
None => entry.media_type.to_string(),
|
||||
};
|
||||
unsafe { HeaderValue::from_bytes_unchecked(s.into_bytes()) }
|
||||
unsafe { FieldValue::from_bytes_unchecked(s.into_bytes()) }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,188 +1,188 @@
|
|||
use super::HeaderName;
|
||||
use super::FieldName;
|
||||
|
||||
/// The `Content-Encoding` Header
|
||||
pub const CONTENT_ENCODING: HeaderName = HeaderName::from_lowercase_str("content-encoding");
|
||||
pub const CONTENT_ENCODING: FieldName = FieldName::from_lowercase_str("content-encoding");
|
||||
/// The `Content-Language` Header
|
||||
pub const CONTENT_LANGUAGE: HeaderName = HeaderName::from_lowercase_str("content-language");
|
||||
pub const CONTENT_LANGUAGE: FieldName = FieldName::from_lowercase_str("content-language");
|
||||
/// The `Content-Length` Header
|
||||
pub const CONTENT_LENGTH: HeaderName = HeaderName::from_lowercase_str("content-length");
|
||||
pub const CONTENT_LENGTH: FieldName = FieldName::from_lowercase_str("content-length");
|
||||
/// The `Content-Location` Header
|
||||
pub const CONTENT_LOCATION: HeaderName = HeaderName::from_lowercase_str("content-location");
|
||||
pub const CONTENT_LOCATION: FieldName = FieldName::from_lowercase_str("content-location");
|
||||
/// The `Content-MD5` Header
|
||||
pub const CONTENT_MD5: HeaderName = HeaderName::from_lowercase_str("content-md5");
|
||||
pub const CONTENT_MD5: FieldName = FieldName::from_lowercase_str("content-md5");
|
||||
/// The `Content-Range` Header
|
||||
pub const CONTENT_RANGE: HeaderName = HeaderName::from_lowercase_str("content-range");
|
||||
pub const CONTENT_RANGE: FieldName = FieldName::from_lowercase_str("content-range");
|
||||
/// The `Content-Type` Header
|
||||
pub const CONTENT_TYPE: HeaderName = HeaderName::from_lowercase_str("content-type");
|
||||
pub const CONTENT_TYPE: FieldName = FieldName::from_lowercase_str("content-type");
|
||||
|
||||
/// The `Cookie` Header
|
||||
pub const COOKIE: HeaderName = HeaderName::from_lowercase_str("cookie");
|
||||
pub const COOKIE: FieldName = FieldName::from_lowercase_str("cookie");
|
||||
|
||||
/// The `Set-Cookie` Header
|
||||
pub const SET_COOKIE: HeaderName = HeaderName::from_lowercase_str("set-cookie");
|
||||
pub const SET_COOKIE: FieldName = FieldName::from_lowercase_str("set-cookie");
|
||||
|
||||
/// The `Transfer-Encoding` Header
|
||||
pub const TRANSFER_ENCODING: HeaderName = HeaderName::from_lowercase_str("transfer-encoding");
|
||||
pub const TRANSFER_ENCODING: FieldName = FieldName::from_lowercase_str("transfer-encoding");
|
||||
|
||||
/// The `Date` Header
|
||||
pub const DATE: HeaderName = HeaderName::from_lowercase_str("date");
|
||||
pub const DATE: FieldName = FieldName::from_lowercase_str("date");
|
||||
|
||||
/// The `Host` Header
|
||||
pub const HOST: HeaderName = HeaderName::from_lowercase_str("host");
|
||||
pub const HOST: FieldName = FieldName::from_lowercase_str("host");
|
||||
|
||||
/// The `Origin` Header
|
||||
pub const ORIGIN: HeaderName = HeaderName::from_lowercase_str("origin");
|
||||
pub const ORIGIN: FieldName = FieldName::from_lowercase_str("origin");
|
||||
|
||||
/// The `access-control-max-age` Header
|
||||
pub const ACCESS_CONTROL_MAX_AGE: HeaderName =
|
||||
HeaderName::from_lowercase_str("access-control-max-age");
|
||||
pub const ACCESS_CONTROL_MAX_AGE: FieldName =
|
||||
FieldName::from_lowercase_str("access-control-max-age");
|
||||
/// The `access-control-allow-origin` Header
|
||||
pub const ACCESS_CONTROL_ALLOW_ORIGIN: HeaderName =
|
||||
HeaderName::from_lowercase_str("access-control-allow-origin");
|
||||
pub const ACCESS_CONTROL_ALLOW_ORIGIN: FieldName =
|
||||
FieldName::from_lowercase_str("access-control-allow-origin");
|
||||
/// The `access-control-allow-headers` Header
|
||||
pub const ACCESS_CONTROL_ALLOW_HEADERS: HeaderName =
|
||||
HeaderName::from_lowercase_str("access-control-allow-headers");
|
||||
pub const ACCESS_CONTROL_ALLOW_HEADERS: FieldName =
|
||||
FieldName::from_lowercase_str("access-control-allow-headers");
|
||||
/// The `access-control-allow-methods` Header
|
||||
pub const ACCESS_CONTROL_ALLOW_METHODS: HeaderName =
|
||||
HeaderName::from_lowercase_str("access-control-allow-methods");
|
||||
pub const ACCESS_CONTROL_ALLOW_METHODS: FieldName =
|
||||
FieldName::from_lowercase_str("access-control-allow-methods");
|
||||
/// The `access-control-expose-headers` Header
|
||||
pub const ACCESS_CONTROL_EXPOSE_HEADERS: HeaderName =
|
||||
HeaderName::from_lowercase_str("access-control-expose-headers");
|
||||
pub const ACCESS_CONTROL_EXPOSE_HEADERS: FieldName =
|
||||
FieldName::from_lowercase_str("access-control-expose-headers");
|
||||
/// The `access-control-request-method` Header
|
||||
pub const ACCESS_CONTROL_REQUEST_METHOD: HeaderName =
|
||||
HeaderName::from_lowercase_str("access-control-request-method");
|
||||
pub const ACCESS_CONTROL_REQUEST_METHOD: FieldName =
|
||||
FieldName::from_lowercase_str("access-control-request-method");
|
||||
/// The `access-control-request-headers` Header
|
||||
pub const ACCESS_CONTROL_REQUEST_HEADERS: HeaderName =
|
||||
HeaderName::from_lowercase_str("access-control-request-headers");
|
||||
pub const ACCESS_CONTROL_REQUEST_HEADERS: FieldName =
|
||||
FieldName::from_lowercase_str("access-control-request-headers");
|
||||
/// The `access-control-allow-credentials` Header
|
||||
pub const ACCESS_CONTROL_ALLOW_CREDENTIALS: HeaderName =
|
||||
HeaderName::from_lowercase_str("access-control-allow-credentials");
|
||||
pub const ACCESS_CONTROL_ALLOW_CREDENTIALS: FieldName =
|
||||
FieldName::from_lowercase_str("access-control-allow-credentials");
|
||||
|
||||
/// The `Accept` Header
|
||||
pub const ACCEPT: HeaderName = HeaderName::from_lowercase_str("accept");
|
||||
pub const ACCEPT: FieldName = FieldName::from_lowercase_str("accept");
|
||||
/// The `Accept-Charset` Header
|
||||
pub const ACCEPT_CHARSET: HeaderName = HeaderName::from_lowercase_str("accept-charset");
|
||||
pub const ACCEPT_CHARSET: FieldName = FieldName::from_lowercase_str("accept-charset");
|
||||
/// The `Accept-Encoding` Header
|
||||
pub const ACCEPT_ENCODING: HeaderName = HeaderName::from_lowercase_str("accept-encoding");
|
||||
pub const ACCEPT_ENCODING: FieldName = FieldName::from_lowercase_str("accept-encoding");
|
||||
/// The `Accept-Language` Header
|
||||
pub const ACCEPT_LANGUAGE: HeaderName = HeaderName::from_lowercase_str("accept-language");
|
||||
pub const ACCEPT_LANGUAGE: FieldName = FieldName::from_lowercase_str("accept-language");
|
||||
/// The `Accept-Ranges` Header
|
||||
pub const ACCEPT_RANGES: HeaderName = HeaderName::from_lowercase_str("accept-ranges");
|
||||
pub const ACCEPT_RANGES: FieldName = FieldName::from_lowercase_str("accept-ranges");
|
||||
|
||||
/// The `Age` Header
|
||||
pub const AGE: HeaderName = HeaderName::from_lowercase_str("age");
|
||||
pub const AGE: FieldName = FieldName::from_lowercase_str("age");
|
||||
|
||||
/// The `Allow` Header
|
||||
pub const ALLOW: HeaderName = HeaderName::from_lowercase_str("allow");
|
||||
pub const ALLOW: FieldName = FieldName::from_lowercase_str("allow");
|
||||
|
||||
/// The `Authorization` Header
|
||||
pub const AUTHORIZATION: HeaderName = HeaderName::from_lowercase_str("authorization");
|
||||
pub const AUTHORIZATION: FieldName = FieldName::from_lowercase_str("authorization");
|
||||
|
||||
/// The `Cache-Control` Header
|
||||
pub const CACHE_CONTROL: HeaderName = HeaderName::from_lowercase_str("cache-control");
|
||||
pub const CACHE_CONTROL: FieldName = FieldName::from_lowercase_str("cache-control");
|
||||
|
||||
/// The `Clear-Site-Data` Header
|
||||
pub const CLEAR_SITE_DATA: HeaderName = HeaderName::from_lowercase_str("clear-site-data");
|
||||
pub const CLEAR_SITE_DATA: FieldName = FieldName::from_lowercase_str("clear-site-data");
|
||||
|
||||
/// The `Connection` Header
|
||||
pub const CONNECTION: HeaderName = HeaderName::from_lowercase_str("connection");
|
||||
pub const CONNECTION: FieldName = FieldName::from_lowercase_str("connection");
|
||||
|
||||
/// The `ETag` Header
|
||||
pub const ETAG: HeaderName = HeaderName::from_lowercase_str("etag");
|
||||
pub const ETAG: FieldName = FieldName::from_lowercase_str("etag");
|
||||
|
||||
/// The `Expect` Header
|
||||
pub const EXPECT: HeaderName = HeaderName::from_lowercase_str("expect");
|
||||
pub const EXPECT: FieldName = FieldName::from_lowercase_str("expect");
|
||||
|
||||
/// The `Expires` Header
|
||||
pub const EXPIRES: HeaderName = HeaderName::from_lowercase_str("expires");
|
||||
pub const EXPIRES: FieldName = FieldName::from_lowercase_str("expires");
|
||||
|
||||
/// The `Forwarded` Header
|
||||
pub const FORWARDED: HeaderName = HeaderName::from_lowercase_str("forwarded");
|
||||
pub const FORWARDED: FieldName = FieldName::from_lowercase_str("forwarded");
|
||||
|
||||
/// The `From` Header
|
||||
pub const FROM: HeaderName = HeaderName::from_lowercase_str("from");
|
||||
pub const FROM: FieldName = FieldName::from_lowercase_str("from");
|
||||
|
||||
/// The `If-Match` Header
|
||||
pub const IF_MATCH: HeaderName = HeaderName::from_lowercase_str("if-match");
|
||||
pub const IF_MATCH: FieldName = FieldName::from_lowercase_str("if-match");
|
||||
|
||||
/// The `If-Modified-Since` Header
|
||||
pub const IF_MODIFIED_SINCE: HeaderName = HeaderName::from_lowercase_str("if-modified-since");
|
||||
pub const IF_MODIFIED_SINCE: FieldName = FieldName::from_lowercase_str("if-modified-since");
|
||||
|
||||
/// The `If-None-Match` Header
|
||||
pub const IF_NONE_MATCH: HeaderName = HeaderName::from_lowercase_str("if-none-match");
|
||||
pub const IF_NONE_MATCH: FieldName = FieldName::from_lowercase_str("if-none-match");
|
||||
|
||||
/// The `If-Range` Header
|
||||
pub const IF_RANGE: HeaderName = HeaderName::from_lowercase_str("if-range");
|
||||
pub const IF_RANGE: FieldName = FieldName::from_lowercase_str("if-range");
|
||||
|
||||
/// The `If-Unmodified-Since` Header
|
||||
pub const IF_UNMODIFIED_SINCE: HeaderName = HeaderName::from_lowercase_str("if-unmodified-since");
|
||||
pub const IF_UNMODIFIED_SINCE: FieldName = FieldName::from_lowercase_str("if-unmodified-since");
|
||||
|
||||
/// The `Last-Modified` Header
|
||||
pub const LAST_MODIFIED: HeaderName = HeaderName::from_lowercase_str("last-modified");
|
||||
pub const LAST_MODIFIED: FieldName = FieldName::from_lowercase_str("last-modified");
|
||||
|
||||
/// The `Location` Header
|
||||
pub const LOCATION: HeaderName = HeaderName::from_lowercase_str("location");
|
||||
pub const LOCATION: FieldName = FieldName::from_lowercase_str("location");
|
||||
|
||||
/// The `Max-Forwards` Header
|
||||
pub const MAX_FORWARDS: HeaderName = HeaderName::from_lowercase_str("max-forwards");
|
||||
pub const MAX_FORWARDS: FieldName = FieldName::from_lowercase_str("max-forwards");
|
||||
|
||||
/// The `Pragma` Header
|
||||
pub const PRAGMA: HeaderName = HeaderName::from_lowercase_str("pragma");
|
||||
pub const PRAGMA: FieldName = FieldName::from_lowercase_str("pragma");
|
||||
|
||||
/// The `Proxy-Authenticate` Header
|
||||
pub const PROXY_AUTHENTICATE: HeaderName = HeaderName::from_lowercase_str("proxy-authenticate");
|
||||
pub const PROXY_AUTHENTICATE: FieldName = FieldName::from_lowercase_str("proxy-authenticate");
|
||||
|
||||
/// The `Proxy-Authorization` Header
|
||||
pub const PROXY_AUTHORIZATION: HeaderName = HeaderName::from_lowercase_str("proxy-authorization");
|
||||
pub const PROXY_AUTHORIZATION: FieldName = FieldName::from_lowercase_str("proxy-authorization");
|
||||
|
||||
/// The `Proxy-Connection` Header
|
||||
pub const PROXY_CONNECTION: HeaderName = HeaderName::from_lowercase_str("proxy-connection");
|
||||
pub const PROXY_CONNECTION: FieldName = FieldName::from_lowercase_str("proxy-connection");
|
||||
|
||||
/// The `Referer` Header
|
||||
pub const REFERER: HeaderName = HeaderName::from_lowercase_str("referer");
|
||||
pub const REFERER: FieldName = FieldName::from_lowercase_str("referer");
|
||||
|
||||
/// The `Retry-After` Header
|
||||
pub const RETRY_AFTER: HeaderName = HeaderName::from_lowercase_str("retry-after");
|
||||
pub const RETRY_AFTER: FieldName = FieldName::from_lowercase_str("retry-after");
|
||||
|
||||
/// The `Server` Header
|
||||
pub const SERVER: HeaderName = HeaderName::from_lowercase_str("server");
|
||||
pub const SERVER: FieldName = FieldName::from_lowercase_str("server");
|
||||
|
||||
/// The `Server` Header
|
||||
pub const SERVER_TIMING: HeaderName = HeaderName::from_lowercase_str("server-timing");
|
||||
pub const SERVER_TIMING: FieldName = FieldName::from_lowercase_str("server-timing");
|
||||
|
||||
/// The `SourceMap` Header
|
||||
pub const SOURCE_MAP: HeaderName = HeaderName::from_lowercase_str("sourcemap");
|
||||
pub const SOURCE_MAP: FieldName = FieldName::from_lowercase_str("sourcemap");
|
||||
|
||||
/// The `Strict-Transport-Security` Header
|
||||
pub const STRICT_TRANSPORT_SECURITY: HeaderName =
|
||||
HeaderName::from_lowercase_str("strict-transport-security");
|
||||
pub const STRICT_TRANSPORT_SECURITY: FieldName =
|
||||
FieldName::from_lowercase_str("strict-transport-security");
|
||||
|
||||
/// The `Te` Header
|
||||
pub const TE: HeaderName = HeaderName::from_lowercase_str("te");
|
||||
pub const TE: FieldName = FieldName::from_lowercase_str("te");
|
||||
|
||||
/// The `Timing-Allow-Origin` Header
|
||||
pub const TIMING_ALLOW_ORIGIN: HeaderName = HeaderName::from_lowercase_str("timing-allow-origin");
|
||||
pub const TIMING_ALLOW_ORIGIN: FieldName = FieldName::from_lowercase_str("timing-allow-origin");
|
||||
|
||||
/// The `Traceparent` Header
|
||||
pub const TRACEPARENT: HeaderName = HeaderName::from_lowercase_str("traceparent");
|
||||
pub const TRACEPARENT: FieldName = FieldName::from_lowercase_str("traceparent");
|
||||
|
||||
/// The `Trailer` Header
|
||||
pub const TRAILER: HeaderName = HeaderName::from_lowercase_str("trailer");
|
||||
pub const TRAILER: FieldName = FieldName::from_lowercase_str("trailer");
|
||||
|
||||
/// The `Upgrade` Header
|
||||
pub const UPGRADE: HeaderName = HeaderName::from_lowercase_str("upgrade");
|
||||
pub const UPGRADE: FieldName = FieldName::from_lowercase_str("upgrade");
|
||||
|
||||
/// The `User-Agent` Header
|
||||
pub const USER_AGENT: HeaderName = HeaderName::from_lowercase_str("user-agent");
|
||||
pub const USER_AGENT: FieldName = FieldName::from_lowercase_str("user-agent");
|
||||
|
||||
/// The `Vary` Header
|
||||
pub const VARY: HeaderName = HeaderName::from_lowercase_str("vary");
|
||||
pub const VARY: FieldName = FieldName::from_lowercase_str("vary");
|
||||
|
||||
/// The `Via` Header
|
||||
pub const VIA: HeaderName = HeaderName::from_lowercase_str("via");
|
||||
pub const VIA: FieldName = FieldName::from_lowercase_str("via");
|
||||
|
||||
/// The `Warning` Header
|
||||
pub const WARNING: HeaderName = HeaderName::from_lowercase_str("warning");
|
||||
pub const WARNING: FieldName = FieldName::from_lowercase_str("warning");
|
||||
|
||||
/// The `WWW-Authenticate` Header
|
||||
pub const WWW_AUTHENTICATE: HeaderName = HeaderName::from_lowercase_str("www-authenticate");
|
||||
pub const WWW_AUTHENTICATE: FieldName = FieldName::from_lowercase_str("www-authenticate");
|
||||
|
|
|
@ -1,58 +1,23 @@
|
|||
use std::ops::Deref;
|
||||
|
||||
use crate::headers::{HeaderName, HeaderValue};
|
||||
use crate::headers::{FieldName, FieldValue};
|
||||
|
||||
/// A trait representing a [`HeaderName`] and [`HeaderValue`] pair.
|
||||
pub trait Header
|
||||
///
|
||||
/// # Specifications
|
||||
///
|
||||
/// - [RFC 9110, section 5: Fields](https://www.rfc-editor.org/rfc/rfc9110.html#fields)
|
||||
#[doc(alias = "Header")]
|
||||
#[doc(alias = "FieldHeader")]
|
||||
pub trait Field
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
/// The header's name.
|
||||
fn header_name(&self) -> HeaderName;
|
||||
/// The header's field name.
|
||||
const FIELD_NAME: FieldName;
|
||||
|
||||
/// Access the header's value.
|
||||
fn header_value(&self) -> HeaderValue;
|
||||
fn field_value(&self) -> FieldValue;
|
||||
|
||||
/// Create an instance from a header value.
|
||||
fn from_parts(name: HeaderName, value: HeaderValue) -> crate::Result<Self>;
|
||||
}
|
||||
|
||||
impl Header for (HeaderName, HeaderValue) {
|
||||
fn header_name(&self) -> HeaderName {
|
||||
self.0
|
||||
}
|
||||
|
||||
fn header_value(&self) -> HeaderValue {
|
||||
self.1
|
||||
}
|
||||
|
||||
fn from_parts(name: HeaderName, value: HeaderValue) -> crate::Result<Self> {
|
||||
Ok((name, value))
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, T: Header> Header for &'a T {
|
||||
fn header_name(&self) -> HeaderName {
|
||||
self.deref().header_name()
|
||||
}
|
||||
|
||||
fn header_value(&self) -> HeaderValue {
|
||||
self.deref().header_value()
|
||||
}
|
||||
|
||||
fn from_parts(name: HeaderName, value: HeaderValue) -> crate::Result<Self> {
|
||||
T::from_parts(name, value)
|
||||
}
|
||||
}
|
||||
|
||||
#[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");
|
||||
}
|
||||
// /// Create a field from its parts.
|
||||
// // TODO: move this to a separate trait.
|
||||
// fn from_field_pair(name: FieldName, value: FieldValue) -> Result<Self, ()>;
|
||||
}
|
||||
|
|
|
@ -4,13 +4,13 @@ use std::str::FromStr;
|
|||
|
||||
use crate::Error;
|
||||
|
||||
use super::Header;
|
||||
use super::Field;
|
||||
|
||||
/// A header name.
|
||||
#[derive(Clone, PartialEq, Eq, Hash)]
|
||||
pub struct HeaderName(Cow<'static, str>);
|
||||
pub struct FieldName(Cow<'static, str>);
|
||||
|
||||
impl HeaderName {
|
||||
impl FieldName {
|
||||
/// Create a new `HeaderName` from a Vec of ASCII bytes.
|
||||
///
|
||||
/// # Error
|
||||
|
@ -22,7 +22,7 @@ impl HeaderName {
|
|||
|
||||
// This is permitted because ASCII is valid UTF-8, and we just checked that.
|
||||
let string = unsafe { String::from_utf8_unchecked(bytes.to_vec()) };
|
||||
Ok(HeaderName(Cow::Owned(string)))
|
||||
Ok(FieldName(Cow::Owned(string)))
|
||||
}
|
||||
|
||||
/// Create a new `HeaderName` from an ASCII string.
|
||||
|
@ -51,28 +51,28 @@ impl HeaderName {
|
|||
pub unsafe fn from_bytes_unchecked(mut bytes: Vec<u8>) -> Self {
|
||||
bytes.make_ascii_lowercase();
|
||||
let string = String::from_utf8_unchecked(bytes);
|
||||
HeaderName(Cow::Owned(string))
|
||||
FieldName(Cow::Owned(string))
|
||||
}
|
||||
|
||||
/// Converts a string assumed to lowercase into a `HeaderName`
|
||||
pub(crate) const fn from_lowercase_str(str: &'static str) -> Self {
|
||||
HeaderName(Cow::Borrowed(str))
|
||||
FieldName(Cow::Borrowed(str))
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for HeaderName {
|
||||
impl Debug for FieldName {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{:?}", self.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for HeaderName {
|
||||
impl Display for FieldName {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{}", self.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl FromStr for HeaderName {
|
||||
impl FromStr for FieldName {
|
||||
type Err = Error;
|
||||
|
||||
/// Create a new `HeaderName`.
|
||||
|
@ -80,58 +80,58 @@ impl FromStr for HeaderName {
|
|||
/// This checks it's valid ASCII, and lowercases it.
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
crate::ensure!(s.is_ascii(), "String slice should be valid ASCII");
|
||||
Ok(HeaderName(Cow::Owned(s.to_ascii_lowercase())))
|
||||
Ok(FieldName(Cow::Owned(s.to_ascii_lowercase())))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&HeaderName> for HeaderName {
|
||||
fn from(value: &HeaderName) -> HeaderName {
|
||||
impl From<&FieldName> for FieldName {
|
||||
fn from(value: &FieldName) -> FieldName {
|
||||
value.clone()
|
||||
}
|
||||
}
|
||||
|
||||
impl<T: Header> From<T> for HeaderName {
|
||||
fn from(header: T) -> HeaderName {
|
||||
header.header_name()
|
||||
impl<T: Field> From<T> for FieldName {
|
||||
fn from(_field: T) -> FieldName {
|
||||
T::FIELD_NAME
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> From<&'a str> for HeaderName {
|
||||
impl<'a> From<&'a str> for FieldName {
|
||||
fn from(value: &'a str) -> Self {
|
||||
Self::from_str(value).expect("String slice should be valid ASCII")
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq<str> for HeaderName {
|
||||
impl PartialEq<str> for FieldName {
|
||||
fn eq(&self, other: &str) -> bool {
|
||||
match HeaderName::from_str(other) {
|
||||
match FieldName::from_str(other) {
|
||||
Err(_) => false,
|
||||
Ok(other) => self == &other,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> PartialEq<&'a str> for HeaderName {
|
||||
impl<'a> PartialEq<&'a str> for FieldName {
|
||||
fn eq(&self, other: &&'a str) -> bool {
|
||||
match HeaderName::from_str(other) {
|
||||
match FieldName::from_str(other) {
|
||||
Err(_) => false,
|
||||
Ok(other) => self == &other,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq<String> for HeaderName {
|
||||
impl PartialEq<String> for FieldName {
|
||||
fn eq(&self, other: &String) -> bool {
|
||||
match HeaderName::from_str(other) {
|
||||
match FieldName::from_str(other) {
|
||||
Err(_) => false,
|
||||
Ok(other) => self == &other,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> PartialEq<&String> for HeaderName {
|
||||
impl<'a> PartialEq<&String> for FieldName {
|
||||
fn eq(&self, other: &&String) -> bool {
|
||||
match HeaderName::from_str(other) {
|
||||
match FieldName::from_str(other) {
|
||||
Err(_) => false,
|
||||
Ok(other) => self == &other,
|
||||
}
|
||||
|
@ -145,8 +145,8 @@ mod tests {
|
|||
#[test]
|
||||
#[allow(clippy::eq_op)]
|
||||
fn test_header_name_static_non_static() {
|
||||
let static_header = HeaderName::from_lowercase_str("hello");
|
||||
let non_static_header = HeaderName::from_str("hello").unwrap();
|
||||
let static_header = FieldName::from_lowercase_str("hello");
|
||||
let non_static_header = FieldName::from_str("hello").unwrap();
|
||||
|
||||
assert_eq!(&static_header, &non_static_header);
|
||||
assert_eq!(&static_header, &static_header);
|
||||
|
@ -159,7 +159,7 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn equality() {
|
||||
let static_header = HeaderName::from_lowercase_str("hello");
|
||||
let static_header = FieldName::from_lowercase_str("hello");
|
||||
assert_eq!(static_header, "hello");
|
||||
assert_eq!(&static_header, "hello");
|
||||
assert_eq!(static_header, String::from("hello"));
|
||||
|
@ -178,7 +178,7 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn test_debug() {
|
||||
let header_name = HeaderName::from_str("hello").unwrap();
|
||||
let header_name = FieldName::from_str("hello").unwrap();
|
||||
assert_eq!(format!("{:?}", header_name), "\"hello\"");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,17 +4,17 @@ use std::str::FromStr;
|
|||
|
||||
#[cfg(feature = "cookies")]
|
||||
use crate::cookies::Cookie;
|
||||
use crate::headers::HeaderValues;
|
||||
use crate::headers::FieldValues;
|
||||
use crate::mime::Mime;
|
||||
use crate::Error;
|
||||
|
||||
/// A header value.
|
||||
#[derive(Clone, Eq, PartialEq, Hash)]
|
||||
pub struct HeaderValue {
|
||||
pub struct FieldValue {
|
||||
inner: String,
|
||||
}
|
||||
|
||||
impl HeaderValue {
|
||||
impl FieldValue {
|
||||
/// Create a new `HeaderValue` from a Vec of ASCII bytes.
|
||||
///
|
||||
/// # Error
|
||||
|
@ -48,32 +48,32 @@ impl HeaderValue {
|
|||
}
|
||||
}
|
||||
|
||||
impl From<Mime> for HeaderValue {
|
||||
impl From<Mime> for FieldValue {
|
||||
fn from(mime: Mime) -> Self {
|
||||
HeaderValue {
|
||||
FieldValue {
|
||||
inner: format!("{}", mime),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "cookies")]
|
||||
impl From<Cookie<'_>> for HeaderValue {
|
||||
impl From<Cookie<'_>> for FieldValue {
|
||||
fn from(cookie: Cookie<'_>) -> Self {
|
||||
HeaderValue {
|
||||
FieldValue {
|
||||
inner: cookie.to_string(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&Mime> for HeaderValue {
|
||||
impl From<&Mime> for FieldValue {
|
||||
fn from(mime: &Mime) -> Self {
|
||||
HeaderValue {
|
||||
FieldValue {
|
||||
inner: format!("{}", mime),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl FromStr for HeaderValue {
|
||||
impl FromStr for FieldValue {
|
||||
type Err = Error;
|
||||
|
||||
/// Create a new `HeaderValue`.
|
||||
|
@ -87,7 +87,7 @@ impl FromStr for HeaderValue {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a> TryFrom<&'a str> for HeaderValue {
|
||||
impl<'a> TryFrom<&'a str> for FieldValue {
|
||||
type Error = Error;
|
||||
|
||||
fn try_from(value: &'a str) -> Result<Self, Self::Error> {
|
||||
|
@ -95,44 +95,44 @@ impl<'a> TryFrom<&'a str> for HeaderValue {
|
|||
}
|
||||
}
|
||||
|
||||
impl Debug for HeaderValue {
|
||||
impl Debug for FieldValue {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{:?}", self.inner)
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for HeaderValue {
|
||||
impl Display for FieldValue {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(f, "{}", self.inner)
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq<str> for HeaderValue {
|
||||
impl PartialEq<str> for FieldValue {
|
||||
fn eq(&self, other: &str) -> bool {
|
||||
self.inner == other
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> PartialEq<&'a str> for HeaderValue {
|
||||
impl<'a> PartialEq<&'a str> for FieldValue {
|
||||
fn eq(&self, other: &&'a str) -> bool {
|
||||
&self.inner == other
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq<String> for HeaderValue {
|
||||
impl PartialEq<String> for FieldValue {
|
||||
fn eq(&self, other: &String) -> bool {
|
||||
&self.inner == other
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> PartialEq<&String> for HeaderValue {
|
||||
impl<'a> PartialEq<&String> for FieldValue {
|
||||
fn eq(&self, other: &&String) -> bool {
|
||||
&&self.inner == other
|
||||
}
|
||||
}
|
||||
|
||||
impl From<HeaderValues> for HeaderValue {
|
||||
fn from(mut other: HeaderValues) -> Self {
|
||||
impl From<FieldValues> for FieldValue {
|
||||
fn from(mut other: FieldValues) -> Self {
|
||||
other.inner.reverse();
|
||||
other
|
||||
.inner
|
||||
|
@ -147,7 +147,7 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn test_debug() {
|
||||
let header_value = HeaderValue::from_str("foo0").unwrap();
|
||||
let header_value = FieldValue::from_str("foo0").unwrap();
|
||||
assert_eq!(format!("{:?}", header_value), "\"foo0\"");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use crate::headers::{HeaderValue, Values};
|
||||
use crate::headers::{FieldValue, Values};
|
||||
|
||||
use std::fmt::{self, Debug, Display};
|
||||
use std::iter::FromIterator;
|
||||
|
@ -9,34 +9,34 @@ use std::slice::SliceIndex;
|
|||
///
|
||||
/// This always contains at least one header value.
|
||||
#[derive(Clone)]
|
||||
pub struct HeaderValues {
|
||||
pub(crate) inner: Vec<HeaderValue>,
|
||||
pub struct FieldValues {
|
||||
pub(crate) inner: Vec<FieldValue>,
|
||||
}
|
||||
|
||||
impl HeaderValues {
|
||||
impl FieldValues {
|
||||
/// Move all values from `other` into `self`, leaving `other` empty.
|
||||
pub fn append(&mut self, other: &mut Self) {
|
||||
self.inner.append(&mut other.inner)
|
||||
}
|
||||
|
||||
/// Returns a reference or a value depending on the type of index.
|
||||
pub fn get(&self, index: usize) -> Option<&HeaderValue> {
|
||||
pub fn get(&self, index: usize) -> Option<&FieldValue> {
|
||||
self.inner.get(index)
|
||||
}
|
||||
|
||||
/// Returns a mutable reference or a value depending on the type of index.
|
||||
pub fn get_mut(&mut self, index: usize) -> Option<&mut HeaderValue> {
|
||||
pub fn get_mut(&mut self, index: usize) -> Option<&mut FieldValue> {
|
||||
self.inner.get_mut(index)
|
||||
}
|
||||
|
||||
/// Returns `true` if there is a value corresponding to the specified `HeaderValue` in the list,
|
||||
/// `false` otherwise.
|
||||
pub fn contains(&self, value: &HeaderValue) -> bool {
|
||||
pub fn contains(&self, value: &FieldValue) -> bool {
|
||||
self.inner.contains(value)
|
||||
}
|
||||
|
||||
/// Returns the last `HeaderValue`.
|
||||
pub fn last(&self) -> &HeaderValue {
|
||||
pub fn last(&self) -> &FieldValue {
|
||||
self.inner
|
||||
.last()
|
||||
.expect("HeaderValues must always contain at least one value")
|
||||
|
@ -56,7 +56,7 @@ impl HeaderValues {
|
|||
// }
|
||||
}
|
||||
|
||||
impl<I: SliceIndex<[HeaderValue]>> Index<I> for HeaderValues {
|
||||
impl<I: SliceIndex<[FieldValue]>> Index<I> for FieldValues {
|
||||
type Output = I::Output;
|
||||
|
||||
#[inline]
|
||||
|
@ -65,21 +65,21 @@ impl<I: SliceIndex<[HeaderValue]>> Index<I> for HeaderValues {
|
|||
}
|
||||
}
|
||||
|
||||
impl FromIterator<HeaderValue> for HeaderValues {
|
||||
fn from_iter<I>(iter: I) -> HeaderValues
|
||||
impl FromIterator<FieldValue> for FieldValues {
|
||||
fn from_iter<I>(iter: I) -> FieldValues
|
||||
where
|
||||
I: IntoIterator<Item = HeaderValue>,
|
||||
I: IntoIterator<Item = FieldValue>,
|
||||
{
|
||||
let iter = iter.into_iter();
|
||||
let mut output = Vec::with_capacity(iter.size_hint().0);
|
||||
for v in iter {
|
||||
output.push(v);
|
||||
}
|
||||
HeaderValues { inner: output }
|
||||
FieldValues { inner: output }
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for HeaderValues {
|
||||
impl Debug for FieldValues {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
if self.inner.len() == 1 {
|
||||
write!(f, "{:?}", self.inner[0])
|
||||
|
@ -89,7 +89,7 @@ impl Debug for HeaderValues {
|
|||
}
|
||||
}
|
||||
|
||||
impl Display for HeaderValues {
|
||||
impl Display for FieldValues {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
let mut list = f.debug_list();
|
||||
for v in &self.inner {
|
||||
|
@ -99,70 +99,70 @@ impl Display for HeaderValues {
|
|||
}
|
||||
}
|
||||
|
||||
impl PartialEq<str> for HeaderValues {
|
||||
impl PartialEq<str> for FieldValues {
|
||||
fn eq(&self, other: &str) -> bool {
|
||||
self.inner.len() == 1 && self.inner[0] == other
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> PartialEq<&'a str> for HeaderValues {
|
||||
impl<'a> PartialEq<&'a str> for FieldValues {
|
||||
fn eq(&self, other: &&'a str) -> bool {
|
||||
self.inner.len() == 1 && &self.inner[0] == other
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> PartialEq<[&'a str]> for HeaderValues {
|
||||
impl<'a> PartialEq<[&'a str]> for FieldValues {
|
||||
fn eq(&self, other: &[&'a str]) -> bool {
|
||||
self.inner.iter().eq(other.iter())
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq<String> for HeaderValues {
|
||||
impl PartialEq<String> for FieldValues {
|
||||
fn eq(&self, other: &String) -> bool {
|
||||
self.inner.len() == 1 && self.inner[0] == *other
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> PartialEq<&String> for HeaderValues {
|
||||
impl<'a> PartialEq<&String> for FieldValues {
|
||||
fn eq(&self, other: &&String) -> bool {
|
||||
self.inner.len() == 1 && self.inner[0] == **other
|
||||
}
|
||||
}
|
||||
|
||||
impl From<HeaderValue> for HeaderValues {
|
||||
fn from(other: HeaderValue) -> Self {
|
||||
impl From<FieldValue> for FieldValues {
|
||||
fn from(other: FieldValue) -> Self {
|
||||
Self { inner: vec![other] }
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<HeaderValue> for HeaderValues {
|
||||
fn as_ref(&self) -> &HeaderValue {
|
||||
impl AsRef<FieldValue> for FieldValues {
|
||||
fn as_ref(&self) -> &FieldValue {
|
||||
&self.inner[0]
|
||||
}
|
||||
}
|
||||
|
||||
impl AsMut<HeaderValue> for HeaderValues {
|
||||
fn as_mut(&mut self) -> &mut HeaderValue {
|
||||
impl AsMut<FieldValue> for FieldValues {
|
||||
fn as_mut(&mut self) -> &mut FieldValue {
|
||||
&mut self.inner[0]
|
||||
}
|
||||
}
|
||||
|
||||
impl Deref for HeaderValues {
|
||||
type Target = HeaderValue;
|
||||
impl Deref for FieldValues {
|
||||
type Target = FieldValue;
|
||||
|
||||
fn deref(&self) -> &HeaderValue {
|
||||
fn deref(&self) -> &FieldValue {
|
||||
&self.inner[0]
|
||||
}
|
||||
}
|
||||
|
||||
impl DerefMut for HeaderValues {
|
||||
fn deref_mut(&mut self) -> &mut HeaderValue {
|
||||
impl DerefMut for FieldValues {
|
||||
fn deref_mut(&mut self) -> &mut FieldValue {
|
||||
&mut self.inner[0]
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> IntoIterator for &'a HeaderValues {
|
||||
type Item = &'a HeaderValue;
|
||||
impl<'a> IntoIterator for &'a FieldValues {
|
||||
type Item = &'a FieldValue;
|
||||
type IntoIter = Values<'a>;
|
||||
|
||||
#[inline]
|
||||
|
@ -171,15 +171,15 @@ impl<'a> IntoIterator for &'a HeaderValues {
|
|||
}
|
||||
}
|
||||
|
||||
impl From<Vec<HeaderValue>> for HeaderValues {
|
||||
fn from(headers: Vec<HeaderValue>) -> Self {
|
||||
impl From<Vec<FieldValue>> for FieldValues {
|
||||
fn from(headers: Vec<FieldValue>) -> Self {
|
||||
Self { inner: headers }
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoIterator for HeaderValues {
|
||||
type Item = HeaderValue;
|
||||
type IntoIter = std::vec::IntoIter<HeaderValue>;
|
||||
impl IntoIterator for FieldValues {
|
||||
type Item = FieldValue;
|
||||
type IntoIter = std::vec::IntoIter<FieldValue>;
|
||||
|
||||
#[inline]
|
||||
fn into_iter(self) -> Self::IntoIter {
|
||||
|
@ -193,14 +193,14 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn test_debug_single() {
|
||||
let header_values = HeaderValues {
|
||||
let header_values = FieldValues {
|
||||
inner: vec!["foo0".parse().unwrap()],
|
||||
};
|
||||
assert_eq!(format!("{:?}", header_values), "\"foo0\"");
|
||||
}
|
||||
#[test]
|
||||
fn test_debug_multiple() {
|
||||
let header_values = HeaderValues {
|
||||
let header_values = FieldValues {
|
||||
inner: vec!["foo0".parse().unwrap(), "foo1".parse().unwrap()],
|
||||
};
|
||||
assert_eq!(format!("{:?}", header_values), r#"["foo0", "foo1"]"#);
|
||||
|
|
|
@ -8,16 +8,14 @@ use std::ops::Index;
|
|||
use std::str::FromStr;
|
||||
|
||||
use crate::headers::{
|
||||
Header, HeaderName, HeaderValues, IntoIter, Iter, IterMut, Names, ToHeaderValues, Values,
|
||||
Field, FieldName, FieldValues, IntoIter, Iter, IterMut, Names, ToFieldValues, Values,
|
||||
};
|
||||
|
||||
use super::HeaderValue;
|
||||
|
||||
/// A collection of HTTP Headers.
|
||||
/// A collection of HTTP Fields.
|
||||
///
|
||||
/// Headers are never manually constructed, but are part of `Request`,
|
||||
/// `Response`, and `Trailers`. Each of these types implements `AsRef<Headers>`
|
||||
/// and `AsMut<Headers>` so functions that want to modify headers can be generic
|
||||
/// Fields are never manually constructed, but are part of `Request`,
|
||||
/// `Response`, and `Trailers`. Each of these types implements `AsRef<Fields>`
|
||||
/// and `AsMut<Fields>` so functions that want to modify headers can be generic
|
||||
/// over either of these traits.
|
||||
///
|
||||
/// # Examples
|
||||
|
@ -30,11 +28,11 @@ use super::HeaderValue;
|
|||
/// assert_eq!(res["hello"], "foo0");
|
||||
/// ```
|
||||
#[derive(Clone)]
|
||||
pub struct Headers {
|
||||
pub(crate) headers: HashMap<HeaderName, HeaderValue>,
|
||||
pub struct Fields {
|
||||
pub(crate) headers: HashMap<FieldName, FieldValues>,
|
||||
}
|
||||
|
||||
impl Headers {
|
||||
impl Fields {
|
||||
/// Create a new instance.
|
||||
pub(crate) fn new() -> Self {
|
||||
Self {
|
||||
|
@ -45,25 +43,58 @@ impl Headers {
|
|||
/// Insert a header into the headers.
|
||||
///
|
||||
/// Not that this will replace all header values for a given header name.
|
||||
pub fn insert<H: Header>(&mut self, header: H) -> Option<HeaderValue> {
|
||||
let name = header.header_name();
|
||||
let value = header.header_value();
|
||||
self.headers.insert(name, value)
|
||||
pub fn insert(
|
||||
&mut self,
|
||||
name: impl Into<FieldName>,
|
||||
values: impl ToFieldValues,
|
||||
) -> crate::Result<Option<FieldValues>> {
|
||||
let name = name.into();
|
||||
let values: FieldValues = values.to_field_values().unwrap().collect();
|
||||
Ok(self.headers.insert(name, values))
|
||||
}
|
||||
|
||||
/// Insert a typed header into the headers.
|
||||
///
|
||||
/// Not that this will replace all header values for a given header name.
|
||||
pub fn insert_typed<F: Field>(&mut self, field: F) -> Option<FieldValues> {
|
||||
self.headers
|
||||
.insert(F::FIELD_NAME, field.field_value().into())
|
||||
}
|
||||
|
||||
/// Append a header to the headers.
|
||||
///
|
||||
/// Unlike `insert` this function will not override the contents of a header, but insert a
|
||||
/// header if there aren't any. Or else append to the existing list of headers.
|
||||
pub fn append(
|
||||
&mut self,
|
||||
name: impl Into<FieldName>,
|
||||
values: impl ToFieldValues,
|
||||
) -> crate::Result<()> {
|
||||
let name = name.into();
|
||||
match self.get_mut(&name) {
|
||||
Some(headers) => {
|
||||
let mut values: FieldValues = values.to_field_values()?.collect();
|
||||
headers.append(&mut values);
|
||||
}
|
||||
None => {
|
||||
self.insert(name, values)?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Get a reference to a header.
|
||||
pub fn get<H: Header>(&self, name: HeaderName) -> Option<H> {
|
||||
let value = self.headers.get(&name)?;
|
||||
H::from_parts(name, value.clone()).ok()
|
||||
pub fn get(&self, name: impl Into<FieldName>) -> Option<&FieldValues> {
|
||||
self.headers.get(&name.into())
|
||||
}
|
||||
|
||||
/// Get a mutable reference to a header.
|
||||
pub fn get_mut(&mut self, name: impl Into<HeaderName>) -> Option<&mut HeaderValues> {
|
||||
pub fn get_mut(&mut self, name: impl Into<FieldName>) -> Option<&mut FieldValues> {
|
||||
self.headers.get_mut(&name.into())
|
||||
}
|
||||
|
||||
/// Remove a header.
|
||||
pub fn remove<H: Header>(&mut self, name: HeaderName) -> Option<HeaderValue> {
|
||||
pub fn remove(&mut self, name: impl Into<FieldName>) -> Option<FieldValues> {
|
||||
self.headers.remove(&name.into())
|
||||
}
|
||||
|
||||
|
@ -95,37 +126,37 @@ impl Headers {
|
|||
}
|
||||
}
|
||||
|
||||
impl Index<HeaderName> for Headers {
|
||||
type Output = HeaderValues;
|
||||
impl Index<FieldName> for Fields {
|
||||
type Output = FieldValues;
|
||||
|
||||
/// Returns a reference to the value corresponding to the supplied name.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if the name is not present in `Headers`.
|
||||
/// Panics if the name is not present in `Fields`.
|
||||
#[inline]
|
||||
fn index(&self, name: HeaderName) -> &HeaderValues {
|
||||
fn index(&self, name: FieldName) -> &FieldValues {
|
||||
self.get(name).expect("no entry found for name")
|
||||
}
|
||||
}
|
||||
|
||||
impl Index<&str> for Headers {
|
||||
type Output = HeaderValues;
|
||||
impl Index<&str> for Fields {
|
||||
type Output = FieldValues;
|
||||
|
||||
/// Returns a reference to the value corresponding to the supplied name.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if the name is not present in `Headers`.
|
||||
/// Panics if the name is not present in `Fields`.
|
||||
#[inline]
|
||||
fn index(&self, name: &str) -> &HeaderValues {
|
||||
let name = HeaderName::from_str(name).expect("string slice needs to be valid ASCII");
|
||||
fn index(&self, name: &str) -> &FieldValues {
|
||||
let name = FieldName::from_str(name).expect("string slice needs to be valid ASCII");
|
||||
self.get(name).expect("no entry found for name")
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoIterator for Headers {
|
||||
type Item = (HeaderName, HeaderValues);
|
||||
impl IntoIterator for Fields {
|
||||
type Item = (FieldName, FieldValues);
|
||||
type IntoIter = IntoIter;
|
||||
|
||||
/// Returns a iterator of references over the remaining items.
|
||||
|
@ -137,8 +168,8 @@ impl IntoIterator for Headers {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a> IntoIterator for &'a Headers {
|
||||
type Item = (&'a HeaderName, &'a HeaderValues);
|
||||
impl<'a> IntoIterator for &'a Fields {
|
||||
type Item = (&'a FieldName, &'a FieldValues);
|
||||
type IntoIter = Iter<'a>;
|
||||
|
||||
#[inline]
|
||||
|
@ -147,8 +178,8 @@ impl<'a> IntoIterator for &'a Headers {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a> IntoIterator for &'a mut Headers {
|
||||
type Item = (&'a HeaderName, &'a mut HeaderValues);
|
||||
impl<'a> IntoIterator for &'a mut Fields {
|
||||
type Item = (&'a FieldName, &'a mut FieldValues);
|
||||
type IntoIter = IterMut<'a>;
|
||||
|
||||
#[inline]
|
||||
|
@ -157,20 +188,20 @@ impl<'a> IntoIterator for &'a mut Headers {
|
|||
}
|
||||
}
|
||||
|
||||
impl Debug for Headers {
|
||||
impl Debug for Fields {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_map().entries(self.headers.iter()).finish()
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRef<Headers> for Headers {
|
||||
fn as_ref(&self) -> &Headers {
|
||||
impl AsRef<Fields> for Fields {
|
||||
fn as_ref(&self) -> &Fields {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
impl AsMut<Headers> for Headers {
|
||||
fn as_mut(&mut self) -> &mut Headers {
|
||||
impl AsMut<Fields> for Fields {
|
||||
fn as_mut(&mut self) -> &mut Fields {
|
||||
self
|
||||
}
|
||||
}
|
||||
|
@ -180,14 +211,14 @@ mod tests {
|
|||
use super::*;
|
||||
use std::str::FromStr;
|
||||
|
||||
const STATIC_HEADER: HeaderName = HeaderName::from_lowercase_str("hello");
|
||||
const STATIC_HEADER: FieldName = FieldName::from_lowercase_str("hello");
|
||||
|
||||
#[test]
|
||||
fn test_header_name_static_non_static() -> crate::Result<()> {
|
||||
let static_header = HeaderName::from_lowercase_str("hello");
|
||||
let non_static_header = HeaderName::from_str("hello")?;
|
||||
let static_header = FieldName::from_lowercase_str("hello");
|
||||
let non_static_header = FieldName::from_str("hello")?;
|
||||
|
||||
let mut headers = Headers::new();
|
||||
let mut headers = Fields::new();
|
||||
headers.append(STATIC_HEADER, "foo0").unwrap();
|
||||
headers.append(static_header.clone(), "foo1").unwrap();
|
||||
headers.append(non_static_header.clone(), "foo2").unwrap();
|
||||
|
@ -201,7 +232,7 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn index_into_headers() {
|
||||
let mut headers = Headers::new();
|
||||
let mut headers = Fields::new();
|
||||
headers.insert("hello", "foo0").unwrap();
|
||||
assert_eq!(headers["hello"], "foo0");
|
||||
assert_eq!(headers.get("hello").unwrap(), "foo0");
|
||||
|
@ -209,14 +240,14 @@ mod tests {
|
|||
|
||||
#[test]
|
||||
fn test_debug_single() {
|
||||
let mut headers = Headers::new();
|
||||
let mut headers = Fields::new();
|
||||
headers.insert("single", "foo0").unwrap();
|
||||
assert_eq!(format!("{:?}", headers), r#"{"single": "foo0"}"#);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_debug_multiple() {
|
||||
let mut headers = Headers::new();
|
||||
let mut headers = Fields::new();
|
||||
headers.append("multi", "foo0").unwrap();
|
||||
headers.append("multi", "foo1").unwrap();
|
||||
assert_eq!(format!("{:?}", headers), r#"{"multi": ["foo0", "foo1"]}"#);
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
use std::collections::hash_map;
|
||||
use std::iter::Iterator;
|
||||
|
||||
use crate::headers::{HeaderName, HeaderValues};
|
||||
use crate::headers::{FieldName, FieldValues};
|
||||
|
||||
/// An owning iterator over the entries of `Headers`.
|
||||
#[derive(Debug)]
|
||||
pub struct IntoIter {
|
||||
pub(super) inner: hash_map::IntoIter<HeaderName, HeaderValues>,
|
||||
pub(super) inner: hash_map::IntoIter<FieldName, FieldValues>,
|
||||
}
|
||||
|
||||
impl Iterator for IntoIter {
|
||||
type Item = (HeaderName, HeaderValues);
|
||||
type Item = (FieldName, FieldValues);
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
self.inner.next()
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
use std::collections::hash_map;
|
||||
use std::iter::Iterator;
|
||||
|
||||
use crate::headers::{HeaderName, HeaderValues};
|
||||
use crate::headers::{FieldName, FieldValues};
|
||||
|
||||
/// Iterator over the headers.
|
||||
#[derive(Debug)]
|
||||
pub struct Iter<'a> {
|
||||
pub(super) inner: hash_map::Iter<'a, HeaderName, HeaderValues>,
|
||||
pub(super) inner: hash_map::Iter<'a, FieldName, FieldValues>,
|
||||
}
|
||||
|
||||
impl<'a> Iterator for Iter<'a> {
|
||||
type Item = (&'a HeaderName, &'a HeaderValues);
|
||||
type Item = (&'a FieldName, &'a FieldValues);
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
self.inner.next()
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
use std::collections::hash_map;
|
||||
use std::iter::Iterator;
|
||||
|
||||
use crate::headers::{HeaderName, HeaderValues};
|
||||
use crate::headers::{FieldName, FieldValues};
|
||||
|
||||
/// Iterator over the headers.
|
||||
#[derive(Debug)]
|
||||
pub struct IterMut<'a> {
|
||||
pub(super) inner: hash_map::IterMut<'a, HeaderName, HeaderValues>,
|
||||
pub(super) inner: hash_map::IterMut<'a, FieldName, FieldValues>,
|
||||
}
|
||||
|
||||
impl<'a> Iterator for IterMut<'a> {
|
||||
type Item = (&'a HeaderName, &'a mut HeaderValues);
|
||||
type Item = (&'a FieldName, &'a mut FieldValues);
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
self.inner.next()
|
||||
|
|
|
@ -15,14 +15,14 @@ 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;
|
||||
pub use headers::Headers;
|
||||
pub use header::Field;
|
||||
pub use header_name::FieldName;
|
||||
pub use header_value::FieldValue;
|
||||
pub use header_values::FieldValues;
|
||||
pub use headers::Fields;
|
||||
pub use into_iter::IntoIter;
|
||||
pub use iter::Iter;
|
||||
pub use iter_mut::IterMut;
|
||||
pub use names::Names;
|
||||
pub use to_header_values::ToHeaderValues;
|
||||
pub use to_header_values::ToFieldValues;
|
||||
pub use values::Values;
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
use std::collections::hash_map;
|
||||
use std::iter::Iterator;
|
||||
|
||||
use crate::headers::{HeaderName, HeaderValues};
|
||||
use crate::headers::{FieldName, FieldValues};
|
||||
|
||||
/// Iterator over the headers.
|
||||
#[derive(Debug)]
|
||||
pub struct Names<'a> {
|
||||
pub(super) inner: hash_map::Keys<'a, HeaderName, HeaderValues>,
|
||||
pub(super) inner: hash_map::Keys<'a, FieldName, FieldValues>,
|
||||
}
|
||||
|
||||
impl<'a> Iterator for Names<'a> {
|
||||
type Item = &'a HeaderName;
|
||||
type Item = &'a FieldName;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
self.inner.next()
|
||||
|
|
|
@ -4,53 +4,53 @@ use std::iter;
|
|||
use std::option;
|
||||
use std::slice;
|
||||
|
||||
use crate::headers::{Header, HeaderValue, HeaderValues, Values};
|
||||
use crate::headers::{Field, FieldValue, FieldValues, Values};
|
||||
|
||||
/// A trait for objects which can be converted or resolved to one or more `HeaderValue`s.
|
||||
pub trait ToHeaderValues {
|
||||
pub trait ToFieldValues {
|
||||
/// Returned iterator over header values which this type may correspond to.
|
||||
type Iter: Iterator<Item = HeaderValue>;
|
||||
type Iter: Iterator<Item = FieldValue>;
|
||||
|
||||
/// Converts this object to an iterator of resolved `HeaderValues`.
|
||||
fn to_header_values(&self) -> crate::Result<Self::Iter>;
|
||||
fn to_field_values(&self) -> crate::Result<Self::Iter>;
|
||||
}
|
||||
|
||||
impl<T: Header> ToHeaderValues for T {
|
||||
type Iter = option::IntoIter<HeaderValue>;
|
||||
impl<T: Field> ToFieldValues for T {
|
||||
type Iter = option::IntoIter<FieldValue>;
|
||||
|
||||
fn to_header_values(&self) -> crate::Result<Self::Iter> {
|
||||
Ok(Some(self.header_value()).into_iter())
|
||||
fn to_field_values(&self) -> crate::Result<Self::Iter> {
|
||||
Ok(Some(self.field_value()).into_iter())
|
||||
}
|
||||
}
|
||||
|
||||
impl ToHeaderValues for HeaderValue {
|
||||
type Iter = option::IntoIter<HeaderValue>;
|
||||
impl ToFieldValues for FieldValue {
|
||||
type Iter = option::IntoIter<FieldValue>;
|
||||
|
||||
fn to_header_values(&self) -> crate::Result<Self::Iter> {
|
||||
fn to_field_values(&self) -> crate::Result<Self::Iter> {
|
||||
Ok(Some(self.clone()).into_iter())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> ToHeaderValues for &'a HeaderValues {
|
||||
impl<'a> ToFieldValues for &'a FieldValues {
|
||||
type Iter = iter::Cloned<Values<'a>>;
|
||||
|
||||
fn to_header_values(&self) -> crate::Result<Self::Iter> {
|
||||
fn to_field_values(&self) -> crate::Result<Self::Iter> {
|
||||
Ok(self.iter().cloned())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> ToHeaderValues for &'a [HeaderValue] {
|
||||
type Iter = iter::Cloned<slice::Iter<'a, HeaderValue>>;
|
||||
impl<'a> ToFieldValues for &'a [FieldValue] {
|
||||
type Iter = iter::Cloned<slice::Iter<'a, FieldValue>>;
|
||||
|
||||
fn to_header_values(&self) -> crate::Result<Self::Iter> {
|
||||
fn to_field_values(&self) -> crate::Result<Self::Iter> {
|
||||
Ok(self.iter().cloned())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> ToHeaderValues for &'a str {
|
||||
type Iter = option::IntoIter<HeaderValue>;
|
||||
impl<'a> ToFieldValues for &'a str {
|
||||
type Iter = option::IntoIter<FieldValue>;
|
||||
|
||||
fn to_header_values(&self) -> crate::Result<Self::Iter> {
|
||||
fn to_field_values(&self) -> crate::Result<Self::Iter> {
|
||||
let value = self
|
||||
.parse()
|
||||
.map_err(|err| io::Error::new(io::ErrorKind::Other, err))?;
|
||||
|
@ -58,26 +58,26 @@ impl<'a> ToHeaderValues for &'a str {
|
|||
}
|
||||
}
|
||||
|
||||
impl ToHeaderValues for String {
|
||||
type Iter = option::IntoIter<HeaderValue>;
|
||||
impl ToFieldValues for String {
|
||||
type Iter = option::IntoIter<FieldValue>;
|
||||
|
||||
fn to_header_values(&self) -> crate::Result<Self::Iter> {
|
||||
self.as_str().to_header_values()
|
||||
fn to_field_values(&self) -> crate::Result<Self::Iter> {
|
||||
self.as_str().to_field_values()
|
||||
}
|
||||
}
|
||||
|
||||
impl ToHeaderValues for &String {
|
||||
type Iter = option::IntoIter<HeaderValue>;
|
||||
impl ToFieldValues for &String {
|
||||
type Iter = option::IntoIter<FieldValue>;
|
||||
|
||||
fn to_header_values(&self) -> crate::Result<Self::Iter> {
|
||||
self.as_str().to_header_values()
|
||||
fn to_field_values(&self) -> crate::Result<Self::Iter> {
|
||||
self.as_str().to_field_values()
|
||||
}
|
||||
}
|
||||
|
||||
impl ToHeaderValues for Cow<'_, str> {
|
||||
type Iter = option::IntoIter<HeaderValue>;
|
||||
impl ToFieldValues for Cow<'_, str> {
|
||||
type Iter = option::IntoIter<FieldValue>;
|
||||
|
||||
fn to_header_values(&self) -> crate::Result<Self::Iter> {
|
||||
self.as_ref().to_header_values()
|
||||
fn to_field_values(&self) -> crate::Result<Self::Iter> {
|
||||
self.as_ref().to_field_values()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,19 +1,19 @@
|
|||
use std::collections::hash_map;
|
||||
use std::iter::Iterator;
|
||||
|
||||
use crate::headers::{HeaderName, HeaderValue, HeaderValues};
|
||||
use crate::headers::{FieldName, FieldValue, FieldValues};
|
||||
|
||||
/// Iterator over the header values.
|
||||
#[derive(Debug)]
|
||||
pub struct Values<'a> {
|
||||
pub(super) inner: Option<hash_map::Values<'a, HeaderName, HeaderValues>>,
|
||||
slot: Option<&'a HeaderValues>,
|
||||
pub(super) inner: Option<hash_map::Values<'a, FieldName, FieldValues>>,
|
||||
slot: Option<&'a FieldValues>,
|
||||
cursor: usize,
|
||||
}
|
||||
|
||||
impl<'a> Values<'a> {
|
||||
/// Constructor for `Headers`.
|
||||
pub(crate) fn new(inner: hash_map::Values<'a, HeaderName, HeaderValues>) -> Self {
|
||||
pub(crate) fn new(inner: hash_map::Values<'a, FieldName, FieldValues>) -> Self {
|
||||
Self {
|
||||
inner: Some(inner),
|
||||
slot: None,
|
||||
|
@ -22,7 +22,7 @@ impl<'a> Values<'a> {
|
|||
}
|
||||
|
||||
/// Constructor for `HeaderValues`.
|
||||
pub(crate) fn new_values(values: &'a HeaderValues) -> Self {
|
||||
pub(crate) fn new_values(values: &'a FieldValues) -> Self {
|
||||
Self {
|
||||
inner: None,
|
||||
slot: Some(values),
|
||||
|
@ -32,7 +32,7 @@ impl<'a> Values<'a> {
|
|||
}
|
||||
|
||||
impl<'a> Iterator for Values<'a> {
|
||||
type Item = &'a HeaderValue;
|
||||
type Item = &'a FieldValue;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
loop {
|
||||
|
|
|
@ -112,7 +112,7 @@ impl TryFrom<http::HeaderMap> for Headers {
|
|||
}
|
||||
}
|
||||
|
||||
impl TryFrom<Headers> for http::HeaderMap {
|
||||
impl TryFrom<Fields> for http::HeaderMap {
|
||||
type Error = Error;
|
||||
|
||||
fn try_from(headers: Headers) -> Result<Self, Self::Error> {
|
||||
|
@ -156,7 +156,7 @@ fn hyperium_headers_to_headers(
|
|||
Ok(())
|
||||
}
|
||||
|
||||
fn headers_to_hyperium_headers(headers: &mut Headers, hyperium_headers: &mut http::HeaderMap) {
|
||||
fn headers_to_hyperium_headers(headers: &mut Fields, hyperium_headers: &mut http::HeaderMap) {
|
||||
for (name, values) in headers {
|
||||
let name = format!("{}", name).into_bytes();
|
||||
let name = http::header::HeaderName::from_bytes(&name).unwrap();
|
||||
|
|
|
@ -156,7 +156,7 @@ pub use version::Version;
|
|||
pub use crate::url::Url;
|
||||
|
||||
#[doc(inline)]
|
||||
pub use crate::headers::Header;
|
||||
pub use crate::headers::Field;
|
||||
|
||||
pub mod security;
|
||||
pub mod trailers;
|
||||
|
|
|
@ -12,7 +12,7 @@ use std::fmt::{self, Debug, Display};
|
|||
use std::option;
|
||||
use std::str::FromStr;
|
||||
|
||||
use crate::headers::{HeaderValue, ToHeaderValues};
|
||||
use crate::headers::{FieldValue, ToFieldValues};
|
||||
|
||||
use infer::Infer;
|
||||
|
||||
|
@ -195,15 +195,15 @@ impl<'a> From<&'a str> for Mime {
|
|||
}
|
||||
}
|
||||
|
||||
impl ToHeaderValues for Mime {
|
||||
type Iter = option::IntoIter<HeaderValue>;
|
||||
impl ToFieldValues for Mime {
|
||||
type Iter = option::IntoIter<FieldValue>;
|
||||
|
||||
fn to_header_values(&self) -> crate::Result<Self::Iter> {
|
||||
fn to_field_values(&self) -> crate::Result<Self::Iter> {
|
||||
let mime = self.clone();
|
||||
let header: HeaderValue = mime.into();
|
||||
let header: FieldValue = mime.into();
|
||||
|
||||
// A HeaderValue will always convert into itself.
|
||||
Ok(header.to_header_values().unwrap())
|
||||
Ok(header.to_field_values().unwrap())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use crate::headers::{Header, HeaderName, HeaderValue, Headers, DATE};
|
||||
use crate::headers::{Field, FieldName, FieldValue, Fields, DATE};
|
||||
use crate::utils::HttpDate;
|
||||
|
||||
use std::time::SystemTime;
|
||||
|
@ -51,7 +51,7 @@ impl Date {
|
|||
}
|
||||
|
||||
/// Create a new instance from headers.
|
||||
pub fn from_headers(headers: impl AsRef<Headers>) -> crate::Result<Option<Self>> {
|
||||
pub fn from_headers(headers: impl AsRef<Fields>) -> crate::Result<Option<Self>> {
|
||||
let headers = match headers.as_ref().get(DATE) {
|
||||
Some(headers) => headers,
|
||||
None => return Ok(None),
|
||||
|
@ -73,17 +73,15 @@ impl Date {
|
|||
}
|
||||
}
|
||||
|
||||
impl Header for Date {
|
||||
fn header_name(&self) -> HeaderName {
|
||||
DATE
|
||||
}
|
||||
impl Field for Date {
|
||||
const FIELD_NAME: FieldName = DATE;
|
||||
|
||||
fn header_value(&self) -> HeaderValue {
|
||||
fn field_value(&self) -> FieldValue {
|
||||
let date: HttpDate = self.at.into();
|
||||
let output = format!("{}", date);
|
||||
|
||||
// SAFETY: the internal string is validated to be ASCII.
|
||||
unsafe { HeaderValue::from_bytes_unchecked(output.into()) }
|
||||
unsafe { FieldValue::from_bytes_unchecked(output.into()) }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -108,7 +106,7 @@ impl PartialEq<SystemTime> for Date {
|
|||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use crate::headers::Headers;
|
||||
use crate::headers::Fields;
|
||||
use std::time::Duration;
|
||||
|
||||
#[test]
|
||||
|
@ -116,8 +114,8 @@ mod test {
|
|||
let now = SystemTime::now();
|
||||
let date = Date::new(now);
|
||||
|
||||
let mut headers = Headers::new();
|
||||
headers.insert(date);
|
||||
let mut headers = Fields::new();
|
||||
headers.insert_typed(date);
|
||||
|
||||
let date = Date::from_headers(headers)?.unwrap();
|
||||
|
||||
|
@ -128,7 +126,7 @@ mod test {
|
|||
|
||||
#[test]
|
||||
fn bad_request_on_parse_error() {
|
||||
let mut headers = Headers::new();
|
||||
let mut headers = Fields::new();
|
||||
headers.insert(DATE, "<nori ate the tag. yum.>").unwrap();
|
||||
let err = Date::from_headers(headers).unwrap_err();
|
||||
assert_eq!(err.status(), 400);
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use crate::headers::{HeaderName, HeaderValue, Headers, EXPECT};
|
||||
use crate::{ensure_eq_status, headers::Header};
|
||||
use crate::headers::{FieldName, FieldValue, Fields, EXPECT};
|
||||
use crate::{ensure_eq_status, headers::Field};
|
||||
|
||||
use std::fmt::Debug;
|
||||
|
||||
|
@ -41,7 +41,7 @@ impl Expect {
|
|||
}
|
||||
|
||||
/// Create an instance of `Expect` from a `Headers` instance.
|
||||
pub fn from_headers(headers: impl AsRef<Headers>) -> crate::Result<Option<Self>> {
|
||||
pub fn from_headers(headers: impl AsRef<Fields>) -> crate::Result<Option<Self>> {
|
||||
let headers = match headers.as_ref().get(EXPECT) {
|
||||
Some(headers) => headers,
|
||||
None => return Ok(None),
|
||||
|
@ -56,28 +56,26 @@ impl Expect {
|
|||
}
|
||||
}
|
||||
|
||||
impl Header for Expect {
|
||||
fn header_name(&self) -> HeaderName {
|
||||
EXPECT
|
||||
}
|
||||
fn header_value(&self) -> HeaderValue {
|
||||
impl Field for Expect {
|
||||
const FIELD_NAME: FieldName = EXPECT;
|
||||
fn field_value(&self) -> FieldValue {
|
||||
let value = "100-continue";
|
||||
// SAFETY: the internal string is validated to be ASCII.
|
||||
unsafe { HeaderValue::from_bytes_unchecked(value.into()) }
|
||||
unsafe { FieldValue::from_bytes_unchecked(value.into()) }
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use crate::headers::Headers;
|
||||
use crate::headers::Fields;
|
||||
|
||||
#[test]
|
||||
fn smoke() -> crate::Result<()> {
|
||||
let expect = Expect::new();
|
||||
|
||||
let mut headers = Headers::new();
|
||||
headers.insert(expect);
|
||||
let mut headers = Fields::new();
|
||||
headers.insert_typed(expect);
|
||||
|
||||
let expect = Expect::from_headers(headers)?.unwrap();
|
||||
assert_eq!(expect, Expect::new());
|
||||
|
@ -86,7 +84,7 @@ mod test {
|
|||
|
||||
#[test]
|
||||
fn bad_request_on_parse_error() {
|
||||
let mut headers = Headers::new();
|
||||
let mut headers = Fields::new();
|
||||
headers.insert(EXPECT, "<nori ate the tag. yum.>").unwrap();
|
||||
let err = Expect::from_headers(headers).unwrap_err();
|
||||
assert_eq!(err.status(), 400);
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use crate::headers::{Header, HeaderName, HeaderValue, Headers, REFERER};
|
||||
use crate::headers::{Field, FieldName, FieldValue, Fields, REFERER};
|
||||
use crate::{bail_status as bail, Status, Url};
|
||||
|
||||
use std::convert::TryInto;
|
||||
|
@ -45,7 +45,7 @@ impl Referer {
|
|||
}
|
||||
|
||||
/// Create a new instance from headers.
|
||||
pub fn from_headers<U>(base_url: U, headers: impl AsRef<Headers>) -> crate::Result<Option<Self>>
|
||||
pub fn from_headers<U>(base_url: U, headers: impl AsRef<Fields>) -> crate::Result<Option<Self>>
|
||||
where
|
||||
U: TryInto<Url>,
|
||||
U::Error: std::fmt::Debug,
|
||||
|
@ -86,30 +86,28 @@ impl Referer {
|
|||
}
|
||||
}
|
||||
|
||||
impl Header for Referer {
|
||||
fn header_name(&self) -> HeaderName {
|
||||
REFERER
|
||||
}
|
||||
impl Field for Referer {
|
||||
const FIELD_NAME: FieldName = REFERER;
|
||||
|
||||
fn header_value(&self) -> HeaderValue {
|
||||
fn field_value(&self) -> FieldValue {
|
||||
let output = self.location.to_string();
|
||||
|
||||
// SAFETY: the internal string is validated to be ASCII.
|
||||
unsafe { HeaderValue::from_bytes_unchecked(output.into()) }
|
||||
unsafe { FieldValue::from_bytes_unchecked(output.into()) }
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use crate::headers::Headers;
|
||||
use crate::headers::Fields;
|
||||
|
||||
#[test]
|
||||
fn smoke() -> crate::Result<()> {
|
||||
let referer = Referer::new(Url::parse("https://example.net/test.json")?);
|
||||
|
||||
let mut headers = Headers::new();
|
||||
headers.insert(referer);
|
||||
let mut headers = Fields::new();
|
||||
headers.insert_typed(referer);
|
||||
|
||||
let base_url = Url::parse("https://example.net/")?;
|
||||
let referer = Referer::from_headers(base_url, headers)?.unwrap();
|
||||
|
@ -122,7 +120,7 @@ mod test {
|
|||
|
||||
#[test]
|
||||
fn bad_request_on_parse_error() {
|
||||
let mut headers = Headers::new();
|
||||
let mut headers = Fields::new();
|
||||
headers
|
||||
.insert(REFERER, "htt://<nori ate the tag. yum.>")
|
||||
.unwrap();
|
||||
|
@ -133,7 +131,7 @@ mod test {
|
|||
|
||||
#[test]
|
||||
fn fallback_works() -> crate::Result<()> {
|
||||
let mut headers = Headers::new();
|
||||
let mut headers = Fields::new();
|
||||
headers.insert(REFERER, "/test.json").unwrap();
|
||||
|
||||
let base_url = Url::parse("https://fallback.net/")?;
|
||||
|
@ -143,7 +141,7 @@ mod test {
|
|||
&Url::parse("https://fallback.net/test.json")?
|
||||
);
|
||||
|
||||
let mut headers = Headers::new();
|
||||
let mut headers = Fields::new();
|
||||
headers
|
||||
.insert(REFERER, "https://example.com/test.json")
|
||||
.unwrap();
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use std::time::{Duration, SystemTime, SystemTimeError};
|
||||
|
||||
use crate::headers::{Header, HeaderName, HeaderValue, Headers, RETRY_AFTER};
|
||||
use crate::headers::{Field, FieldName, FieldValue, Fields, RETRY_AFTER};
|
||||
use crate::utils::{fmt_http_date, parse_http_date};
|
||||
|
||||
/// Indicate how long the user agent should wait before making a follow-up request.
|
||||
|
@ -58,7 +58,7 @@ impl RetryAfter {
|
|||
}
|
||||
|
||||
/// Create a new instance from headers.
|
||||
pub fn from_headers(headers: impl AsRef<Headers>) -> crate::Result<Option<Self>> {
|
||||
pub fn from_headers(headers: impl AsRef<Fields>) -> crate::Result<Option<Self>> {
|
||||
let header = match headers.as_ref().get(RETRY_AFTER) {
|
||||
Some(headers) => headers.last(),
|
||||
None => return Ok(None),
|
||||
|
@ -89,18 +89,16 @@ impl RetryAfter {
|
|||
}
|
||||
}
|
||||
|
||||
impl Header for RetryAfter {
|
||||
fn header_name(&self) -> HeaderName {
|
||||
RETRY_AFTER
|
||||
}
|
||||
impl Field for RetryAfter {
|
||||
const FIELD_NAME: FieldName = RETRY_AFTER;
|
||||
|
||||
fn header_value(&self) -> HeaderValue {
|
||||
fn field_value(&self) -> FieldValue {
|
||||
let output = match self.inner {
|
||||
RetryDirective::Duration(dur) => format!("{}", dur.as_secs()),
|
||||
RetryDirective::SystemTime(at) => fmt_http_date(at),
|
||||
};
|
||||
// SAFETY: the internal string is validated to be ASCII.
|
||||
unsafe { HeaderValue::from_bytes_unchecked(output.into()) }
|
||||
unsafe { FieldValue::from_bytes_unchecked(output.into()) }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -126,14 +124,14 @@ enum RetryDirective {
|
|||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use crate::headers::Headers;
|
||||
use crate::headers::Fields;
|
||||
|
||||
#[test]
|
||||
fn smoke() -> crate::Result<()> {
|
||||
let retry = RetryAfter::new(Duration::from_secs(10));
|
||||
|
||||
let mut headers = Headers::new();
|
||||
headers.insert(retry);
|
||||
let mut headers = Fields::new();
|
||||
headers.insert_typed(retry);
|
||||
|
||||
// `SystemTime::now` uses sub-second precision which means there's some
|
||||
// offset that's not encoded.
|
||||
|
@ -151,8 +149,8 @@ mod test {
|
|||
let now = SystemTime::now();
|
||||
let retry = RetryAfter::new_at(now + Duration::from_secs(10));
|
||||
|
||||
let mut headers = Headers::new();
|
||||
headers.insert(retry);
|
||||
let mut headers = Fields::new();
|
||||
headers.insert_typed(retry);
|
||||
|
||||
// `SystemTime::now` uses sub-second precision which means there's some
|
||||
// offset that's not encoded.
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use crate::headers::{Header, HeaderName, HeaderValue, Headers, SOURCE_MAP};
|
||||
use crate::headers::{Field, FieldName, FieldValue, Fields, SOURCE_MAP};
|
||||
use crate::{bail_status as bail, Status, Url};
|
||||
|
||||
use std::convert::TryInto;
|
||||
|
@ -42,7 +42,7 @@ impl SourceMap {
|
|||
}
|
||||
|
||||
/// Create a new instance from headers.
|
||||
pub fn from_headers<U>(base_url: U, headers: impl AsRef<Headers>) -> crate::Result<Option<Self>>
|
||||
pub fn from_headers<U>(base_url: U, headers: impl AsRef<Fields>) -> crate::Result<Option<Self>>
|
||||
where
|
||||
U: TryInto<Url>,
|
||||
U::Error: std::fmt::Debug,
|
||||
|
@ -83,30 +83,28 @@ impl SourceMap {
|
|||
}
|
||||
}
|
||||
|
||||
impl Header for SourceMap {
|
||||
fn header_name(&self) -> HeaderName {
|
||||
SOURCE_MAP
|
||||
}
|
||||
impl Field for SourceMap {
|
||||
const FIELD_NAME: FieldName = SOURCE_MAP;
|
||||
|
||||
fn header_value(&self) -> HeaderValue {
|
||||
fn field_value(&self) -> FieldValue {
|
||||
let output = self.location.to_string();
|
||||
|
||||
// SAFETY: the internal string is validated to be ASCII.
|
||||
unsafe { HeaderValue::from_bytes_unchecked(output.into()) }
|
||||
unsafe { FieldValue::from_bytes_unchecked(output.into()) }
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use crate::headers::Headers;
|
||||
use crate::headers::Fields;
|
||||
|
||||
#[test]
|
||||
fn smoke() -> crate::Result<()> {
|
||||
let source_map = SourceMap::new(Url::parse("https://example.net/test.json")?);
|
||||
|
||||
let mut headers = Headers::new();
|
||||
source_headers.insert(map);
|
||||
let mut headers = Fields::new();
|
||||
headers.insert_typed(source_map);
|
||||
|
||||
let base_url = Url::parse("https://example.net/")?;
|
||||
let source_map = SourceMap::from_headers(base_url, headers)?.unwrap();
|
||||
|
@ -119,7 +117,7 @@ mod test {
|
|||
|
||||
#[test]
|
||||
fn bad_request_on_parse_error() {
|
||||
let mut headers = Headers::new();
|
||||
let mut headers = Fields::new();
|
||||
headers
|
||||
.insert(SOURCE_MAP, "htt://<nori ate the tag. yum.>")
|
||||
.unwrap();
|
||||
|
@ -130,7 +128,7 @@ mod test {
|
|||
|
||||
#[test]
|
||||
fn fallback_works() -> crate::Result<()> {
|
||||
let mut headers = Headers::new();
|
||||
let mut headers = Fields::new();
|
||||
headers.insert(SOURCE_MAP, "/test.json").unwrap();
|
||||
|
||||
let base_url = Url::parse("https://fallback.net/")?;
|
||||
|
@ -140,7 +138,7 @@ mod test {
|
|||
&Url::parse("https://fallback.net/test.json")?
|
||||
);
|
||||
|
||||
let mut headers = Headers::new();
|
||||
let mut headers = Fields::new();
|
||||
headers
|
||||
.insert(SOURCE_MAP, "https://example.com/test.json")
|
||||
.unwrap();
|
||||
|
|
|
@ -1,14 +1,14 @@
|
|||
use crate::{
|
||||
headers::{Header, HeaderName, HeaderValue, Headers, FORWARDED},
|
||||
headers::{Field, FieldName, FieldValue, Fields, FORWARDED},
|
||||
parse_utils::{parse_quoted_string, parse_token},
|
||||
};
|
||||
use std::{borrow::Cow, convert::TryFrom, fmt::Write, net::IpAddr};
|
||||
|
||||
// these constants are private because they are nonstandard
|
||||
const X_FORWARDED_FOR: HeaderName = HeaderName::from_lowercase_str("x-forwarded-for");
|
||||
const X_FORWARDED_PROTO: HeaderName = HeaderName::from_lowercase_str("x-forwarded-proto");
|
||||
const X_FORWARDED_BY: HeaderName = HeaderName::from_lowercase_str("x-forwarded-by");
|
||||
const X_FORWARDED_HOST: HeaderName = HeaderName::from_lowercase_str("x-forwarded-host");
|
||||
const X_FORWARDED_FOR: FieldName = FieldName::from_lowercase_str("x-forwarded-for");
|
||||
const X_FORWARDED_PROTO: FieldName = FieldName::from_lowercase_str("x-forwarded-proto");
|
||||
const X_FORWARDED_BY: FieldName = FieldName::from_lowercase_str("x-forwarded-by");
|
||||
const X_FORWARDED_HOST: FieldName = FieldName::from_lowercase_str("x-forwarded-host");
|
||||
|
||||
/// A rust representation of the [forwarded
|
||||
/// header](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Forwarded).
|
||||
|
@ -76,7 +76,7 @@ impl<'a> Forwarded<'a> {
|
|||
/// # Ok(()) }
|
||||
/// ```
|
||||
|
||||
pub fn from_headers(headers: &'a impl AsRef<Headers>) -> Result<Option<Self>, ParseError> {
|
||||
pub fn from_headers(headers: &'a impl AsRef<Fields>) -> Result<Option<Self>, ParseError> {
|
||||
if let Some(forwarded) = Self::from_forwarded_header(headers)? {
|
||||
Ok(Some(forwarded))
|
||||
} else {
|
||||
|
@ -109,7 +109,7 @@ impl<'a> Forwarded<'a> {
|
|||
/// # Ok(()) }
|
||||
/// ```
|
||||
pub fn from_forwarded_header(
|
||||
headers: &'a impl AsRef<Headers>,
|
||||
headers: &'a impl AsRef<Fields>,
|
||||
) -> Result<Option<Self>, ParseError> {
|
||||
if let Some(headers) = headers.as_ref().get(FORWARDED) {
|
||||
Ok(Some(Self::parse(headers.as_ref().as_str())?))
|
||||
|
@ -143,7 +143,7 @@ impl<'a> Forwarded<'a> {
|
|||
/// assert!(Forwarded::from_x_headers(&request)?.is_none());
|
||||
/// # Ok(()) }
|
||||
/// ```
|
||||
pub fn from_x_headers(headers: &'a impl AsRef<Headers>) -> Result<Option<Self>, ParseError> {
|
||||
pub fn from_x_headers(headers: &'a impl AsRef<Fields>) -> Result<Option<Self>, ParseError> {
|
||||
let headers = headers.as_ref();
|
||||
|
||||
let forwarded_for: Vec<Cow<'a, str>> = headers
|
||||
|
@ -358,11 +358,9 @@ impl<'a> Forwarded<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
impl<'a> Header for Forwarded<'a> {
|
||||
fn header_name(&self) -> HeaderName {
|
||||
FORWARDED
|
||||
}
|
||||
fn header_value(&self) -> HeaderValue {
|
||||
impl<'a> Field for Forwarded<'a> {
|
||||
const FIELD_NAME: FieldName = FORWARDED;
|
||||
fn field_value(&self) -> FieldValue {
|
||||
let mut output = String::new();
|
||||
if let Some(by) = self.by() {
|
||||
write!(&mut output, "by={};", by).unwrap();
|
||||
|
@ -391,7 +389,7 @@ impl<'a> Header for Forwarded<'a> {
|
|||
output.pop();
|
||||
|
||||
// SAFETY: the internal string is validated to be ASCII.
|
||||
unsafe { HeaderValue::from_bytes_unchecked(output.into()) }
|
||||
unsafe { FieldValue::from_bytes_unchecked(output.into()) }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -439,7 +437,7 @@ fn starts_with_ignore_case(start: &'static str, input: &str) -> bool {
|
|||
|
||||
impl std::fmt::Display for Forwarded<'_> {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
f.write_str(self.header_value().as_str())
|
||||
f.write_str(self.field_value().as_str())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -665,7 +663,7 @@ mod tests {
|
|||
];
|
||||
for input in inputs {
|
||||
let forwarded = Forwarded::parse(input).map_err(|_| crate::Error::new_adhoc(input))?;
|
||||
let header = forwarded.header_value();
|
||||
let header = forwarded.field_value();
|
||||
let parsed = Forwarded::parse(header.as_str())?;
|
||||
assert_eq!(forwarded, parsed);
|
||||
}
|
||||
|
|
|
@ -9,12 +9,11 @@ use std::task::{Context, Poll};
|
|||
#[cfg(feature = "serde")]
|
||||
use crate::convert::{DeserializeOwned, Serialize};
|
||||
use crate::headers::{
|
||||
self, HeaderName, HeaderValue, HeaderValues, Headers, Names, ToHeaderValues, Values,
|
||||
CONTENT_TYPE,
|
||||
self, FieldName, FieldValue, FieldValues, Fields, Names, ToFieldValues, Values, CONTENT_TYPE,
|
||||
};
|
||||
use crate::mime::Mime;
|
||||
use crate::trailers::{self, Trailers};
|
||||
use crate::{Body, Extensions, Method, Url, Version};
|
||||
use crate::{Body, Extensions, Field, Method, Url, Version};
|
||||
|
||||
pin_project_lite::pin_project! {
|
||||
/// An HTTP request.
|
||||
|
@ -31,7 +30,7 @@ pin_project_lite::pin_project! {
|
|||
pub struct Request {
|
||||
method: Method,
|
||||
url: Url,
|
||||
headers: Headers,
|
||||
headers: Fields,
|
||||
version: Option<Version>,
|
||||
#[pin]
|
||||
body: Body,
|
||||
|
@ -56,7 +55,7 @@ impl Request {
|
|||
Self {
|
||||
method,
|
||||
url,
|
||||
headers: Headers::new(),
|
||||
headers: Fields::new(),
|
||||
version: None,
|
||||
body: Body::empty(),
|
||||
ext: Extensions::new(),
|
||||
|
@ -408,17 +407,17 @@ impl Request {
|
|||
}
|
||||
|
||||
/// Get an HTTP header.
|
||||
pub fn header(&self, name: impl Into<HeaderName>) -> Option<&HeaderValues> {
|
||||
self.headers.get(name)
|
||||
pub fn header(&self, name: impl Into<FieldName>) -> Option<&FieldValues> {
|
||||
self.headers.get(name.into())
|
||||
}
|
||||
|
||||
/// Get a mutable reference to a header.
|
||||
pub fn header_mut(&mut self, name: impl Into<HeaderName>) -> Option<&mut HeaderValues> {
|
||||
pub fn header_mut(&mut self, name: impl Into<FieldName>) -> Option<&mut FieldValues> {
|
||||
self.headers.get_mut(name.into())
|
||||
}
|
||||
|
||||
/// Remove a header.
|
||||
pub fn remove_header(&mut self, name: impl Into<HeaderName>) -> Option<HeaderValues> {
|
||||
pub fn remove_header(&mut self, name: impl Into<FieldName>) -> Option<FieldValues> {
|
||||
self.headers.remove(name.into())
|
||||
}
|
||||
|
||||
|
@ -438,12 +437,17 @@ impl Request {
|
|||
/// ```
|
||||
pub fn insert_header(
|
||||
&mut self,
|
||||
name: impl Into<HeaderName>,
|
||||
values: impl ToHeaderValues,
|
||||
) -> crate::Result<Option<HeaderValues>> {
|
||||
name: impl Into<FieldName>,
|
||||
values: impl ToFieldValues,
|
||||
) -> crate::Result<Option<FieldValues>> {
|
||||
self.headers.insert(name, values)
|
||||
}
|
||||
|
||||
/// Set a typed HTTP header.
|
||||
pub fn insert_typed_header<F: Field>(&mut self, field: F) -> Option<FieldValues> {
|
||||
self.headers.insert_typed(field)
|
||||
}
|
||||
|
||||
/// Append a header to the headers.
|
||||
///
|
||||
/// Unlike `insert` this function will not override the contents of a
|
||||
|
@ -464,16 +468,16 @@ impl Request {
|
|||
/// ```
|
||||
pub fn append_header(
|
||||
&mut self,
|
||||
name: impl Into<HeaderName>,
|
||||
values: impl ToHeaderValues,
|
||||
name: impl Into<FieldName>,
|
||||
values: impl ToFieldValues,
|
||||
) -> crate::Result<()> {
|
||||
self.headers.append(name, values)
|
||||
}
|
||||
|
||||
/// Set the response MIME.
|
||||
// TODO: return a parsed MIME
|
||||
pub fn set_content_type(&mut self, mime: Mime) -> Option<HeaderValues> {
|
||||
let value: HeaderValue = mime.into();
|
||||
pub fn set_content_type(&mut self, mime: Mime) -> Option<FieldValues> {
|
||||
let value: FieldValue = mime.into();
|
||||
|
||||
// A Mime instance is guaranteed to be valid header name.
|
||||
self.insert_header(CONTENT_TYPE, value).unwrap()
|
||||
|
@ -927,14 +931,14 @@ impl AsyncBufRead for Request {
|
|||
}
|
||||
}
|
||||
|
||||
impl AsRef<Headers> for Request {
|
||||
fn as_ref(&self) -> &Headers {
|
||||
impl AsRef<Fields> for Request {
|
||||
fn as_ref(&self) -> &Fields {
|
||||
&self.headers
|
||||
}
|
||||
}
|
||||
|
||||
impl AsMut<Headers> for Request {
|
||||
fn as_mut(&mut self) -> &mut Headers {
|
||||
impl AsMut<Fields> for Request {
|
||||
fn as_mut(&mut self) -> &mut Fields {
|
||||
&mut self.headers
|
||||
}
|
||||
}
|
||||
|
@ -945,8 +949,8 @@ impl From<Request> for Body {
|
|||
}
|
||||
}
|
||||
|
||||
impl Index<HeaderName> for Request {
|
||||
type Output = HeaderValues;
|
||||
impl Index<FieldName> for Request {
|
||||
type Output = FieldValues;
|
||||
|
||||
/// Returns a reference to the value corresponding to the supplied name.
|
||||
///
|
||||
|
@ -954,13 +958,13 @@ impl Index<HeaderName> for Request {
|
|||
///
|
||||
/// Panics if the name is not present in `Request`.
|
||||
#[inline]
|
||||
fn index(&self, name: HeaderName) -> &HeaderValues {
|
||||
fn index(&self, name: FieldName) -> &FieldValues {
|
||||
self.headers.index(name)
|
||||
}
|
||||
}
|
||||
|
||||
impl Index<&str> for Request {
|
||||
type Output = HeaderValues;
|
||||
type Output = FieldValues;
|
||||
|
||||
/// Returns a reference to the value corresponding to the supplied name.
|
||||
///
|
||||
|
@ -968,13 +972,13 @@ impl Index<&str> for Request {
|
|||
///
|
||||
/// Panics if the name is not present in `Request`.
|
||||
#[inline]
|
||||
fn index(&self, name: &str) -> &HeaderValues {
|
||||
fn index(&self, name: &str) -> &FieldValues {
|
||||
self.headers.index(name)
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoIterator for Request {
|
||||
type Item = (HeaderName, HeaderValues);
|
||||
type Item = (FieldName, FieldValues);
|
||||
type IntoIter = headers::IntoIter;
|
||||
|
||||
/// Returns a iterator of references over the remaining items.
|
||||
|
@ -985,7 +989,7 @@ impl IntoIterator for Request {
|
|||
}
|
||||
|
||||
impl<'a> IntoIterator for &'a Request {
|
||||
type Item = (&'a HeaderName, &'a HeaderValues);
|
||||
type Item = (&'a FieldName, &'a FieldValues);
|
||||
type IntoIter = headers::Iter<'a>;
|
||||
|
||||
#[inline]
|
||||
|
@ -995,7 +999,7 @@ impl<'a> IntoIterator for &'a Request {
|
|||
}
|
||||
|
||||
impl<'a> IntoIterator for &'a mut Request {
|
||||
type Item = (&'a HeaderName, &'a mut HeaderValues);
|
||||
type Item = (&'a FieldName, &'a mut FieldValues);
|
||||
type IntoIter = headers::IterMut<'a>;
|
||||
|
||||
#[inline]
|
||||
|
|
|
@ -10,12 +10,11 @@ use std::task::{Context, Poll};
|
|||
#[cfg(feature = "serde")]
|
||||
use crate::convert::DeserializeOwned;
|
||||
use crate::headers::{
|
||||
self, HeaderName, HeaderValue, HeaderValues, Headers, Names, ToHeaderValues, Values,
|
||||
CONTENT_TYPE,
|
||||
self, FieldName, FieldValue, FieldValues, Fields, Names, ToFieldValues, Values, CONTENT_TYPE,
|
||||
};
|
||||
use crate::mime::Mime;
|
||||
use crate::trailers::{self, Trailers};
|
||||
use crate::upgrade;
|
||||
use crate::{upgrade, Field};
|
||||
use crate::{Body, Extensions, StatusCode, Version};
|
||||
|
||||
pin_project_lite::pin_project! {
|
||||
|
@ -36,7 +35,7 @@ pin_project_lite::pin_project! {
|
|||
#[derive(Debug)]
|
||||
pub struct Response {
|
||||
status: StatusCode,
|
||||
headers: Headers,
|
||||
headers: Fields,
|
||||
version: Option<Version>,
|
||||
has_trailers: bool,
|
||||
trailers_sender: Option<async_channel::Sender<Trailers>>,
|
||||
|
@ -66,7 +65,7 @@ impl Response {
|
|||
let (upgrade_sender, upgrade_receiver) = async_channel::bounded(1);
|
||||
Self {
|
||||
status,
|
||||
headers: Headers::new(),
|
||||
headers: Fields::new(),
|
||||
version: None,
|
||||
body: Body::empty(),
|
||||
trailers_sender: Some(trailers_sender),
|
||||
|
@ -87,17 +86,17 @@ impl Response {
|
|||
}
|
||||
|
||||
/// Get a mutable reference to a header.
|
||||
pub fn header_mut(&mut self, name: impl Into<HeaderName>) -> Option<&mut HeaderValues> {
|
||||
pub fn header_mut(&mut self, name: impl Into<FieldName>) -> Option<&mut FieldValues> {
|
||||
self.headers.get_mut(name.into())
|
||||
}
|
||||
|
||||
/// Get an HTTP header.
|
||||
pub fn header(&self, name: impl Into<HeaderName>) -> Option<&HeaderValues> {
|
||||
pub fn header(&self, name: impl Into<FieldName>) -> Option<&FieldValues> {
|
||||
self.headers.get(name.into())
|
||||
}
|
||||
|
||||
/// Remove a header.
|
||||
pub fn remove_header(&mut self, name: impl Into<HeaderName>) -> Option<HeaderValues> {
|
||||
pub fn remove_header(&mut self, name: impl Into<FieldName>) -> Option<FieldValues> {
|
||||
self.headers.remove(name.into())
|
||||
}
|
||||
|
||||
|
@ -117,12 +116,17 @@ impl Response {
|
|||
/// ```
|
||||
pub fn insert_header(
|
||||
&mut self,
|
||||
name: impl Into<HeaderName>,
|
||||
values: impl ToHeaderValues,
|
||||
) -> crate::Result<Option<HeaderValues>> {
|
||||
name: impl Into<FieldName>,
|
||||
values: impl ToFieldValues,
|
||||
) -> crate::Result<Option<FieldValues>> {
|
||||
self.headers.insert(name, values)
|
||||
}
|
||||
|
||||
/// Set a typed HTTP header.
|
||||
pub fn insert_typed_header<F: Field>(&mut self, field: F) -> Option<FieldValues> {
|
||||
self.headers.insert_typed(field)
|
||||
}
|
||||
|
||||
/// Append a header to the headers.
|
||||
///
|
||||
/// Unlike `insert` this function will not override the contents of a
|
||||
|
@ -143,8 +147,8 @@ impl Response {
|
|||
/// ```
|
||||
pub fn append_header(
|
||||
&mut self,
|
||||
name: impl Into<HeaderName>,
|
||||
values: impl ToHeaderValues,
|
||||
name: impl Into<FieldName>,
|
||||
values: impl ToFieldValues,
|
||||
) -> crate::Result<()> {
|
||||
self.headers.append(name, values)
|
||||
}
|
||||
|
@ -377,8 +381,8 @@ impl Response {
|
|||
}
|
||||
|
||||
/// Set the response MIME.
|
||||
pub fn set_content_type(&mut self, mime: Mime) -> Option<HeaderValues> {
|
||||
let value: HeaderValue = mime.into();
|
||||
pub fn set_content_type(&mut self, mime: Mime) -> Option<FieldValues> {
|
||||
let value: FieldValue = mime.into();
|
||||
|
||||
// A Mime instance is guaranteed to be valid header name.
|
||||
self.insert_header(CONTENT_TYPE, value).unwrap()
|
||||
|
@ -627,14 +631,14 @@ impl AsyncBufRead for Response {
|
|||
}
|
||||
}
|
||||
|
||||
impl AsRef<Headers> for Response {
|
||||
fn as_ref(&self) -> &Headers {
|
||||
impl AsRef<Fields> for Response {
|
||||
fn as_ref(&self) -> &Fields {
|
||||
&self.headers
|
||||
}
|
||||
}
|
||||
|
||||
impl AsMut<Headers> for Response {
|
||||
fn as_mut(&mut self) -> &mut Headers {
|
||||
impl AsMut<Fields> for Response {
|
||||
fn as_mut(&mut self) -> &mut Fields {
|
||||
&mut self.headers
|
||||
}
|
||||
}
|
||||
|
@ -644,8 +648,8 @@ impl From<()> for Response {
|
|||
Response::new(StatusCode::NoContent)
|
||||
}
|
||||
}
|
||||
impl Index<HeaderName> for Response {
|
||||
type Output = HeaderValues;
|
||||
impl Index<FieldName> for Response {
|
||||
type Output = FieldValues;
|
||||
|
||||
/// Returns a reference to the value corresponding to the supplied name.
|
||||
///
|
||||
|
@ -653,13 +657,13 @@ impl Index<HeaderName> for Response {
|
|||
///
|
||||
/// Panics if the name is not present in `Response`.
|
||||
#[inline]
|
||||
fn index(&self, name: HeaderName) -> &HeaderValues {
|
||||
fn index(&self, name: FieldName) -> &FieldValues {
|
||||
self.headers.index(name)
|
||||
}
|
||||
}
|
||||
|
||||
impl Index<&str> for Response {
|
||||
type Output = HeaderValues;
|
||||
type Output = FieldValues;
|
||||
|
||||
/// Returns a reference to the value corresponding to the supplied name.
|
||||
///
|
||||
|
@ -667,7 +671,7 @@ impl Index<&str> for Response {
|
|||
///
|
||||
/// Panics if the name is not present in `Response`.
|
||||
#[inline]
|
||||
fn index(&self, name: &str) -> &HeaderValues {
|
||||
fn index(&self, name: &str) -> &FieldValues {
|
||||
self.headers.index(name)
|
||||
}
|
||||
}
|
||||
|
@ -691,7 +695,7 @@ where
|
|||
}
|
||||
|
||||
impl IntoIterator for Response {
|
||||
type Item = (HeaderName, HeaderValues);
|
||||
type Item = (FieldName, FieldValues);
|
||||
type IntoIter = headers::IntoIter;
|
||||
|
||||
/// Returns a iterator of references over the remaining items.
|
||||
|
@ -702,7 +706,7 @@ impl IntoIterator for Response {
|
|||
}
|
||||
|
||||
impl<'a> IntoIterator for &'a Response {
|
||||
type Item = (&'a HeaderName, &'a HeaderValues);
|
||||
type Item = (&'a FieldName, &'a FieldValues);
|
||||
type IntoIter = headers::Iter<'a>;
|
||||
|
||||
#[inline]
|
||||
|
@ -712,7 +716,7 @@ impl<'a> IntoIterator for &'a Response {
|
|||
}
|
||||
|
||||
impl<'a> IntoIterator for &'a mut Response {
|
||||
type Item = (&'a HeaderName, &'a mut HeaderValues);
|
||||
type Item = (&'a FieldName, &'a mut FieldValues);
|
||||
type IntoIter = headers::IterMut<'a>;
|
||||
|
||||
#[inline]
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use crate::headers::Headers;
|
||||
use crate::headers::Fields;
|
||||
use std::collections::HashMap;
|
||||
use std::fmt;
|
||||
|
||||
|
@ -355,7 +355,7 @@ impl ContentSecurityPolicy {
|
|||
}
|
||||
|
||||
/// Sets the `Content-Security-Policy` (CSP) HTTP header to prevent cross-site injections
|
||||
pub fn apply(&mut self, mut headers: impl AsMut<Headers>) {
|
||||
pub fn apply(&mut self, mut headers: impl AsMut<Fields>) {
|
||||
let name = if self.report_only_flag {
|
||||
"Content-Security-Policy-Report-Only"
|
||||
} else {
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
// //! assert_eq!(res["X-XSS-Protection"], "1; mode=block");
|
||||
//! ```
|
||||
|
||||
use crate::headers::{HeaderName, HeaderValue, Headers};
|
||||
use crate::headers::{FieldName, FieldValue, Fields};
|
||||
|
||||
mod csp;
|
||||
mod strict_transport_security;
|
||||
|
@ -41,7 +41,7 @@ pub use timing_allow_origin::TimingAllowOrigin;
|
|||
// /// assert_eq!(headers["X-Content-Type-Options"], "nosniff");
|
||||
// /// assert_eq!(headers["X-XSS-Protection"], "1; mode=block");
|
||||
// /// ```
|
||||
pub fn default(mut headers: impl AsMut<Headers>) {
|
||||
pub fn default(mut headers: impl AsMut<Fields>) {
|
||||
dns_prefetch_control(&mut headers);
|
||||
nosniff(&mut headers);
|
||||
frameguard(&mut headers, None);
|
||||
|
@ -63,7 +63,7 @@ pub fn default(mut headers: impl AsMut<Headers>) {
|
|||
// /// assert_eq!(headers["X-DNS-Prefetch-Control"], "on");
|
||||
// /// ```
|
||||
#[inline]
|
||||
pub fn dns_prefetch_control(mut headers: impl AsMut<Headers>) {
|
||||
pub fn dns_prefetch_control(mut headers: impl AsMut<Fields>) {
|
||||
// This will never fail, could use an unsafe version of insert.
|
||||
headers
|
||||
.as_mut()
|
||||
|
@ -93,7 +93,7 @@ pub enum FrameOptions {
|
|||
// /// assert_eq!(headers["X-Frame-Options"], "sameorigin");
|
||||
// /// ```
|
||||
#[inline]
|
||||
pub fn frameguard(mut headers: impl AsMut<Headers>, guard: Option<FrameOptions>) {
|
||||
pub fn frameguard(mut headers: impl AsMut<Fields>, guard: Option<FrameOptions>) {
|
||||
let kind = match guard {
|
||||
None | Some(FrameOptions::SameOrigin) => "sameorigin",
|
||||
Some(FrameOptions::Deny) => "deny",
|
||||
|
@ -117,8 +117,8 @@ pub fn frameguard(mut headers: impl AsMut<Headers>, guard: Option<FrameOptions>)
|
|||
// /// assert_eq!(headers.get("X-Powered-By"), None);
|
||||
// /// ```
|
||||
#[inline]
|
||||
pub fn powered_by(mut headers: impl AsMut<Headers>, value: Option<HeaderValue>) {
|
||||
let name = HeaderName::from_lowercase_str("X-Powered-By");
|
||||
pub fn powered_by(mut headers: impl AsMut<Fields>, value: Option<FieldValue>) {
|
||||
let name = FieldName::from_lowercase_str("X-Powered-By");
|
||||
match value {
|
||||
Some(value) => {
|
||||
// Can never fail as value is already a HeaderValue, could use unsafe version of insert
|
||||
|
@ -146,7 +146,7 @@ pub fn powered_by(mut headers: impl AsMut<Headers>, value: Option<HeaderValue>)
|
|||
// /// assert_eq!(headers["Strict-Transport-Security"], "max-age=5184000");
|
||||
// /// ```
|
||||
#[inline]
|
||||
pub fn hsts(mut headers: impl AsMut<Headers>) {
|
||||
pub fn hsts(mut headers: impl AsMut<Fields>) {
|
||||
// Never fails, could use unsafe version of insert
|
||||
headers
|
||||
.as_mut()
|
||||
|
@ -168,7 +168,7 @@ pub fn hsts(mut headers: impl AsMut<Headers>) {
|
|||
// /// assert_eq!(headers["X-Content-Type-Options"], "nosniff");
|
||||
// /// ```
|
||||
#[inline]
|
||||
pub fn nosniff(mut headers: impl AsMut<Headers>) {
|
||||
pub fn nosniff(mut headers: impl AsMut<Fields>) {
|
||||
// Never fails, could use unsafe verison of insert.
|
||||
headers
|
||||
.as_mut()
|
||||
|
@ -189,7 +189,7 @@ pub fn nosniff(mut headers: impl AsMut<Headers>) {
|
|||
// /// assert_eq!(headers["X-XSS-Protection"], "1; mode=block");
|
||||
// /// ```
|
||||
#[inline]
|
||||
pub fn xss_filter(mut headers: impl AsMut<Headers>) {
|
||||
pub fn xss_filter(mut headers: impl AsMut<Fields>) {
|
||||
// Never fails, could use unsafe version of insert.
|
||||
headers
|
||||
.as_mut()
|
||||
|
@ -236,7 +236,7 @@ pub enum ReferrerOptions {
|
|||
// /// assert_eq!(referrerValues.sort(), vec!("unsafe-url", "no-referrer").sort());
|
||||
// /// ```
|
||||
#[inline]
|
||||
pub fn referrer_policy(mut headers: impl AsMut<Headers>, referrer: Option<ReferrerOptions>) {
|
||||
pub fn referrer_policy(mut headers: impl AsMut<Fields>, referrer: Option<ReferrerOptions>) {
|
||||
let policy = match referrer {
|
||||
None | Some(ReferrerOptions::NoReferrer) => "no-referrer",
|
||||
Some(ReferrerOptions::NoReferrerDowngrade) => "no-referrer-when-downgrade",
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use crate::headers::{Header, HeaderName, HeaderValue, Headers};
|
||||
use crate::headers::{Field, FieldName, FieldValue, Fields};
|
||||
use crate::Status;
|
||||
|
||||
use crate::headers::STRICT_TRANSPORT_SECURITY;
|
||||
|
@ -70,12 +70,10 @@ impl StrictTransportSecurity {
|
|||
}
|
||||
}
|
||||
|
||||
impl Header for StrictTransportSecurity {
|
||||
fn header_name(&self) -> HeaderName {
|
||||
STRICT_TRANSPORT_SECURITY
|
||||
}
|
||||
impl Field for StrictTransportSecurity {
|
||||
const FIELD_NAME: FieldName = STRICT_TRANSPORT_SECURITY;
|
||||
|
||||
fn header_value(&self) -> HeaderValue {
|
||||
fn field_value(&self) -> FieldValue {
|
||||
let max_age = self.max_age.as_secs();
|
||||
let mut output = format!("max-age={}", max_age);
|
||||
if self.include_subdomains {
|
||||
|
@ -86,14 +84,14 @@ impl Header for StrictTransportSecurity {
|
|||
}
|
||||
|
||||
// SAFETY: the internal string is validated to be ASCII.
|
||||
unsafe { HeaderValue::from_bytes_unchecked(output.into()) }
|
||||
unsafe { FieldValue::from_bytes_unchecked(output.into()) }
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: move to new header traits
|
||||
impl StrictTransportSecurity {
|
||||
/// Create a new instance from headers.
|
||||
pub fn from_headers(headers: impl AsRef<Headers>) -> crate::Result<Option<Self>> {
|
||||
pub fn from_headers(headers: impl AsRef<Fields>) -> crate::Result<Option<Self>> {
|
||||
let headers = match headers.as_ref().get(STRICT_TRANSPORT_SECURITY) {
|
||||
Some(headers) => headers,
|
||||
None => return Ok(None),
|
||||
|
@ -170,7 +168,7 @@ mod test {
|
|||
let stc = StrictTransportSecurity::new(duration);
|
||||
|
||||
let mut headers = Response::new(200);
|
||||
headers.insert(stc);
|
||||
headers.insert_typed_header(stc);
|
||||
|
||||
let stc = StrictTransportSecurity::from_headers(headers)?.unwrap();
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
//! origins.push(Url::parse("https://example.com")?);
|
||||
//!
|
||||
//! let mut res = Response::new(200);
|
||||
//! origins.apply_header(&mut res);
|
||||
//! res.insert_typed_header(origins);
|
||||
//!
|
||||
//! let origins = TimingAllowOrigin::from_headers(res)?.unwrap();
|
||||
//! let origin = origins.iter().next().unwrap();
|
||||
|
@ -26,7 +26,7 @@
|
|||
//! # Ok(()) }
|
||||
//! ```
|
||||
|
||||
use crate::headers::{Header, HeaderName, HeaderValue, Headers, TIMING_ALLOW_ORIGIN};
|
||||
use crate::headers::{Field, FieldName, FieldValue, Fields, TIMING_ALLOW_ORIGIN};
|
||||
use crate::{Status, Url};
|
||||
|
||||
use std::fmt::Write;
|
||||
|
@ -77,7 +77,7 @@ impl TimingAllowOrigin {
|
|||
/// # Implementation note
|
||||
///
|
||||
/// A header value of `"null"` is treated the same as if no header was sent.
|
||||
pub fn from_headers(headers: impl AsRef<Headers>) -> crate::Result<Option<Self>> {
|
||||
pub fn from_headers(headers: impl AsRef<Fields>) -> crate::Result<Option<Self>> {
|
||||
let headers = match headers.as_ref().get(TIMING_ALLOW_ORIGIN) {
|
||||
Some(headers) => headers,
|
||||
None => return Ok(None),
|
||||
|
@ -131,11 +131,9 @@ impl TimingAllowOrigin {
|
|||
}
|
||||
}
|
||||
|
||||
impl Header for TimingAllowOrigin {
|
||||
fn header_name(&self) -> HeaderName {
|
||||
TIMING_ALLOW_ORIGIN
|
||||
}
|
||||
fn header_value(&self) -> HeaderValue {
|
||||
impl Field for TimingAllowOrigin {
|
||||
const FIELD_NAME: FieldName = TIMING_ALLOW_ORIGIN;
|
||||
fn field_value(&self) -> FieldValue {
|
||||
let mut output = String::new();
|
||||
for (n, origin) in self.origins.iter().enumerate() {
|
||||
match n {
|
||||
|
@ -152,7 +150,7 @@ impl Header for TimingAllowOrigin {
|
|||
}
|
||||
|
||||
// SAFETY: the internal string is validated to be ASCII.
|
||||
unsafe { HeaderValue::from_bytes_unchecked(output.into()) }
|
||||
unsafe { FieldValue::from_bytes_unchecked(output.into()) }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -258,15 +256,15 @@ impl Debug for TimingAllowOrigin {
|
|||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use crate::headers::Headers;
|
||||
use crate::headers::Fields;
|
||||
|
||||
#[test]
|
||||
fn smoke() -> crate::Result<()> {
|
||||
let mut origins = TimingAllowOrigin::new();
|
||||
origins.push(Url::parse("https://example.com")?);
|
||||
|
||||
let mut headers = Headers::new();
|
||||
headers.insert(origins);
|
||||
let mut headers = Fields::new();
|
||||
headers.insert_typed(origins);
|
||||
|
||||
let origins = TimingAllowOrigin::from_headers(headers)?.unwrap();
|
||||
let origin = origins.iter().next().unwrap();
|
||||
|
@ -280,8 +278,8 @@ mod test {
|
|||
origins.push(Url::parse("https://example.com")?);
|
||||
origins.push(Url::parse("https://mozilla.org/")?);
|
||||
|
||||
let mut headers = Headers::new();
|
||||
headers.insert(origins);
|
||||
let mut headers = Fields::new();
|
||||
headers.insert_typed(origins);
|
||||
|
||||
let origins = TimingAllowOrigin::from_headers(headers)?.unwrap();
|
||||
let mut origins = origins.iter();
|
||||
|
@ -295,7 +293,7 @@ mod test {
|
|||
|
||||
#[test]
|
||||
fn bad_request_on_parse_error() {
|
||||
let mut headers = Headers::new();
|
||||
let mut headers = Fields::new();
|
||||
headers
|
||||
.insert(TIMING_ALLOW_ORIGIN, "server; <nori ate your param omnom>")
|
||||
.unwrap();
|
||||
|
@ -309,8 +307,8 @@ mod test {
|
|||
origins.push(Url::parse("https://example.com")?);
|
||||
origins.set_wildcard(true);
|
||||
|
||||
let mut headers = Headers::new();
|
||||
headers.insert(origins);
|
||||
let mut headers = Fields::new();
|
||||
headers.insert_typed(origins);
|
||||
|
||||
let origins = TimingAllowOrigin::from_headers(headers)?.unwrap();
|
||||
assert!(origins.wildcard());
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
//! List the set of methods supported by a resource.
|
||||
|
||||
use crate::headers::{Header, HeaderName, HeaderValue, Headers, ALLOW};
|
||||
use crate::headers::{Field, FieldName, FieldValue, Fields, ALLOW};
|
||||
use crate::Method;
|
||||
|
||||
use std::collections::{hash_set, HashSet};
|
||||
|
@ -49,7 +49,7 @@ impl Allow {
|
|||
}
|
||||
|
||||
/// Create a new instance from headers.
|
||||
pub fn from_headers(headers: impl AsRef<Headers>) -> crate::Result<Option<Self>> {
|
||||
pub fn from_headers(headers: impl AsRef<Fields>) -> crate::Result<Option<Self>> {
|
||||
let mut entries = HashSet::new();
|
||||
let headers = match headers.as_ref().get(ALLOW) {
|
||||
Some(headers) => headers,
|
||||
|
@ -84,11 +84,9 @@ impl Allow {
|
|||
}
|
||||
}
|
||||
|
||||
impl Header for Allow {
|
||||
fn header_name(&self) -> HeaderName {
|
||||
ALLOW
|
||||
}
|
||||
fn header_value(&self) -> HeaderValue {
|
||||
impl Field for Allow {
|
||||
const FIELD_NAME: FieldName = ALLOW;
|
||||
fn field_value(&self) -> FieldValue {
|
||||
let mut output = String::new();
|
||||
for (n, method) in self.entries.iter().enumerate() {
|
||||
match n {
|
||||
|
@ -98,7 +96,7 @@ impl Header for Allow {
|
|||
}
|
||||
|
||||
// SAFETY: the internal string is validated to be ASCII.
|
||||
unsafe { HeaderValue::from_bytes_unchecked(output.into()) }
|
||||
unsafe { FieldValue::from_bytes_unchecked(output.into()) }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -175,7 +173,7 @@ impl Debug for Allow {
|
|||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use crate::headers::Headers;
|
||||
use crate::headers::Fields;
|
||||
|
||||
#[test]
|
||||
fn smoke() -> crate::Result<()> {
|
||||
|
@ -183,8 +181,8 @@ mod test {
|
|||
allow.insert(Method::Put);
|
||||
allow.insert(Method::Post);
|
||||
|
||||
let mut headers = Headers::new();
|
||||
headers.insert(allow);
|
||||
let mut headers = Fields::new();
|
||||
headers.insert_typed(allow);
|
||||
|
||||
let allow = Allow::from_headers(headers)?.unwrap();
|
||||
assert!(allow.contains(Method::Put));
|
||||
|
|
|
@ -582,7 +582,6 @@ mod serde {
|
|||
where
|
||||
E: DeError,
|
||||
{
|
||||
use std::convert::TryFrom;
|
||||
match StatusCode::try_from(v) {
|
||||
Ok(status_code) => Ok(status_code),
|
||||
Err(_) => Err(DeError::invalid_value(
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use std::time::Duration;
|
||||
|
||||
use crate::headers::HeaderValue;
|
||||
use crate::headers::FieldValue;
|
||||
|
||||
/// An individual entry into `ServerTiming`.
|
||||
//
|
||||
|
@ -52,8 +52,8 @@ impl Metric {
|
|||
}
|
||||
}
|
||||
|
||||
impl From<Metric> for HeaderValue {
|
||||
fn from(entry: Metric) -> HeaderValue {
|
||||
impl From<Metric> for FieldValue {
|
||||
fn from(entry: Metric) -> FieldValue {
|
||||
let mut string = entry.name;
|
||||
|
||||
// Format a `Duration` into the format that the spec expects.
|
||||
|
@ -69,14 +69,14 @@ impl From<Metric> for HeaderValue {
|
|||
};
|
||||
|
||||
// SAFETY: we validate that the values are valid ASCII on creation.
|
||||
unsafe { HeaderValue::from_bytes_unchecked(string.into_bytes()) }
|
||||
unsafe { FieldValue::from_bytes_unchecked(string.into_bytes()) }
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use crate::headers::HeaderValue;
|
||||
use crate::headers::FieldValue;
|
||||
use std::time::Duration;
|
||||
|
||||
#[test]
|
||||
|
@ -86,16 +86,16 @@ mod test {
|
|||
let dur = Duration::from_secs(1);
|
||||
let desc = String::from("A server timing");
|
||||
|
||||
let val: HeaderValue = Metric::new(name.clone(), None, None)?.into();
|
||||
let val: FieldValue = Metric::new(name.clone(), None, None)?.into();
|
||||
assert_eq!(val, "Server");
|
||||
|
||||
let val: HeaderValue = Metric::new(name.clone(), Some(dur), None)?.into();
|
||||
let val: FieldValue = Metric::new(name.clone(), Some(dur), None)?.into();
|
||||
assert_eq!(val, "Server; dur=1000");
|
||||
|
||||
let val: HeaderValue = Metric::new(name.clone(), None, Some(desc.clone()))?.into();
|
||||
let val: FieldValue = Metric::new(name.clone(), None, Some(desc.clone()))?.into();
|
||||
assert_eq!(val, r#"Server; desc="A server timing""#);
|
||||
|
||||
let val: HeaderValue = Metric::new(name.clone(), Some(dur), Some(desc.clone()))?.into();
|
||||
let val: FieldValue = Metric::new(name.clone(), Some(dur), Some(desc.clone()))?.into();
|
||||
assert_eq!(val, r#"Server; dur=1000; desc="A server timing""#);
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -32,7 +32,7 @@ use std::iter::Iterator;
|
|||
|
||||
use std::slice;
|
||||
|
||||
use crate::headers::{Header, HeaderName, HeaderValue, Headers, SERVER_TIMING};
|
||||
use crate::headers::{Field, FieldName, FieldValue, Fields, SERVER_TIMING};
|
||||
|
||||
/// Metrics and descriptions for the given request-response cycle.
|
||||
///
|
||||
|
@ -72,7 +72,7 @@ impl ServerTiming {
|
|||
}
|
||||
|
||||
/// Create a new instance from headers.
|
||||
pub fn from_headers(headers: impl AsRef<Headers>) -> crate::Result<Option<Self>> {
|
||||
pub fn from_headers(headers: impl AsRef<Fields>) -> crate::Result<Option<Self>> {
|
||||
let mut timings = vec![];
|
||||
let headers = match headers.as_ref().get(SERVER_TIMING) {
|
||||
Some(headers) => headers,
|
||||
|
@ -105,15 +105,13 @@ impl ServerTiming {
|
|||
}
|
||||
}
|
||||
|
||||
impl Header for ServerTiming {
|
||||
fn header_name(&self) -> HeaderName {
|
||||
SERVER_TIMING
|
||||
}
|
||||
impl Field for ServerTiming {
|
||||
const FIELD_NAME: FieldName = SERVER_TIMING;
|
||||
|
||||
fn header_value(&self) -> HeaderValue {
|
||||
fn field_value(&self) -> FieldValue {
|
||||
let mut output = String::new();
|
||||
for (n, timing) in self.timings.iter().enumerate() {
|
||||
let timing: HeaderValue = timing.clone().into();
|
||||
let timing: FieldValue = timing.clone().into();
|
||||
match n {
|
||||
0 => write!(output, "{}", timing).unwrap(),
|
||||
_ => write!(output, ", {}", timing).unwrap(),
|
||||
|
@ -121,7 +119,7 @@ impl Header for ServerTiming {
|
|||
}
|
||||
|
||||
// SAFETY: the internal string is validated to be ASCII.
|
||||
unsafe { HeaderValue::from_bytes_unchecked(output.into()) }
|
||||
unsafe { FieldValue::from_bytes_unchecked(output.into()) }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -217,15 +215,15 @@ impl<'a> Iterator for IterMut<'a> {
|
|||
#[cfg(test)]
|
||||
mod test {
|
||||
use super::*;
|
||||
use crate::headers::Headers;
|
||||
use crate::headers::Fields;
|
||||
|
||||
#[test]
|
||||
fn smoke() -> crate::Result<()> {
|
||||
let mut timings = ServerTiming::new();
|
||||
timings.push(Metric::new("server".to_owned(), None, None)?);
|
||||
|
||||
let mut headers = Headers::new();
|
||||
headers.insert(timings);
|
||||
let mut headers = Fields::new();
|
||||
headers.insert_typed(timings);
|
||||
|
||||
let timings = ServerTiming::from_headers(headers)?.unwrap();
|
||||
let entry = timings.iter().next().unwrap();
|
||||
|
@ -238,8 +236,8 @@ mod test {
|
|||
let mut timings = ServerTiming::new();
|
||||
timings.push(Metric::new("server".to_owned(), None, None)?);
|
||||
|
||||
let mut headers = Headers::new();
|
||||
headers.insert(timings);
|
||||
let mut headers = Fields::new();
|
||||
headers.insert_typed(timings);
|
||||
|
||||
let timings = ServerTiming::from_headers(headers)?.unwrap();
|
||||
let entry = timings.iter().next().unwrap();
|
||||
|
@ -249,7 +247,7 @@ mod test {
|
|||
|
||||
#[test]
|
||||
fn bad_request_on_parse_error() {
|
||||
let mut headers = Headers::new();
|
||||
let mut headers = Fields::new();
|
||||
headers
|
||||
.insert(SERVER_TIMING, "server; <nori ate your param omnom>")
|
||||
.unwrap();
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use std::fmt;
|
||||
|
||||
use crate::headers::{Header, HeaderName, HeaderValue, Headers, TRACEPARENT};
|
||||
use crate::headers::{Field, FieldName, FieldValue, Fields, TRACEPARENT};
|
||||
use crate::Status;
|
||||
|
||||
/// Extract and apply [Trace-Context](https://w3c.github.io/trace-context/) headers.
|
||||
|
@ -99,7 +99,7 @@ impl TraceContext {
|
|||
/// #
|
||||
/// # Ok(()) }
|
||||
/// ```
|
||||
pub fn from_headers(headers: impl AsRef<Headers>) -> crate::Result<Option<Self>> {
|
||||
pub fn from_headers(headers: impl AsRef<Fields>) -> crate::Result<Option<Self>> {
|
||||
let headers = headers.as_ref();
|
||||
|
||||
let traceparent = match headers.get(TRACEPARENT) {
|
||||
|
@ -195,14 +195,12 @@ impl TraceContext {
|
|||
}
|
||||
}
|
||||
|
||||
impl Header for TraceContext {
|
||||
fn header_name(&self) -> HeaderName {
|
||||
TRACEPARENT
|
||||
}
|
||||
impl Field for TraceContext {
|
||||
const FIELD_NAME: FieldName = TRACEPARENT;
|
||||
|
||||
fn header_value(&self) -> HeaderValue {
|
||||
fn field_value(&self) -> FieldValue {
|
||||
let output = format!("{}", self);
|
||||
unsafe { HeaderValue::from_bytes_unchecked(output.into()) }
|
||||
unsafe { FieldValue::from_bytes_unchecked(output.into()) }
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -222,7 +220,7 @@ mod test {
|
|||
|
||||
#[test]
|
||||
fn default() -> crate::Result<()> {
|
||||
let mut headers = crate::headers::Headers::new();
|
||||
let mut headers = crate::headers::Fields::new();
|
||||
headers.insert(TRACEPARENT, "00-01-deadbeef-00").unwrap();
|
||||
let context = TraceContext::from_headers(&mut headers)?.unwrap();
|
||||
assert_eq!(context.version(), 0);
|
||||
|
@ -244,7 +242,7 @@ mod test {
|
|||
|
||||
#[test]
|
||||
fn not_sampled() -> crate::Result<()> {
|
||||
let mut headers = crate::headers::Headers::new();
|
||||
let mut headers = crate::headers::Fields::new();
|
||||
headers.insert(TRACEPARENT, "00-01-02-00").unwrap();
|
||||
let context = TraceContext::from_headers(&mut headers)?.unwrap();
|
||||
assert!(!context.sampled());
|
||||
|
@ -253,7 +251,7 @@ mod test {
|
|||
|
||||
#[test]
|
||||
fn sampled() -> crate::Result<()> {
|
||||
let mut headers = crate::headers::Headers::new();
|
||||
let mut headers = crate::headers::Fields::new();
|
||||
headers.insert(TRACEPARENT, "00-01-02-01").unwrap();
|
||||
let context = TraceContext::from_headers(&mut headers)?.unwrap();
|
||||
assert!(context.sampled());
|
||||
|
|
|
@ -48,9 +48,7 @@
|
|||
//! - [MDN HTTP Headers: Trailer](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Trailer)
|
||||
//! - [HTTP/2 spec: HTTP Sequence](https://http2.github.io/http2-spec/#HttpSequence)
|
||||
|
||||
use crate::headers::{
|
||||
HeaderName, HeaderValues, Headers, Iter, IterMut, Names, ToHeaderValues, Values,
|
||||
};
|
||||
use crate::headers::{FieldName, FieldValues, Fields, Iter, IterMut, Names, ToFieldValues, Values};
|
||||
use futures_lite::Stream;
|
||||
|
||||
use std::convert::Into;
|
||||
|
@ -62,14 +60,14 @@ use std::task::{Context, Poll};
|
|||
/// A collection of trailing HTTP headers.
|
||||
#[derive(Debug)]
|
||||
pub struct Trailers {
|
||||
headers: Headers,
|
||||
headers: Fields,
|
||||
}
|
||||
|
||||
impl Trailers {
|
||||
/// Create a new instance of `Trailers`.
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
headers: Headers::new(),
|
||||
headers: Fields::new(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -89,9 +87,9 @@ impl Trailers {
|
|||
/// ```
|
||||
pub fn insert(
|
||||
&mut self,
|
||||
name: impl Into<HeaderName>,
|
||||
values: impl ToHeaderValues,
|
||||
) -> crate::Result<Option<HeaderValues>> {
|
||||
name: impl Into<FieldName>,
|
||||
values: impl ToFieldValues,
|
||||
) -> crate::Result<Option<FieldValues>> {
|
||||
self.headers.insert(name, values)
|
||||
}
|
||||
|
||||
|
@ -114,25 +112,25 @@ impl Trailers {
|
|||
/// ```
|
||||
pub fn append(
|
||||
&mut self,
|
||||
name: impl Into<HeaderName>,
|
||||
values: impl ToHeaderValues,
|
||||
name: impl Into<FieldName>,
|
||||
values: impl ToFieldValues,
|
||||
) -> crate::Result<()> {
|
||||
self.headers.append(name, values)
|
||||
}
|
||||
|
||||
/// Get a reference to a header.
|
||||
pub fn get(&self, name: impl Into<HeaderName>) -> Option<&HeaderValues> {
|
||||
self.headers.get(name)
|
||||
pub fn get(&self, name: impl Into<FieldName>) -> Option<&FieldValues> {
|
||||
self.headers.get(name.into())
|
||||
}
|
||||
|
||||
/// Get a mutable reference to a header.
|
||||
pub fn get_mut(&mut self, name: impl Into<HeaderName>) -> Option<&mut HeaderValues> {
|
||||
self.headers.get_mut(name)
|
||||
pub fn get_mut(&mut self, name: impl Into<FieldName>) -> Option<&mut FieldValues> {
|
||||
self.headers.get_mut(name.into())
|
||||
}
|
||||
|
||||
/// Remove a header.
|
||||
pub fn remove(&mut self, name: impl Into<HeaderName>) -> Option<HeaderValues> {
|
||||
self.headers.remove(name)
|
||||
pub fn remove(&mut self, name: impl Into<FieldName>) -> Option<FieldValues> {
|
||||
self.headers.remove(name.into())
|
||||
}
|
||||
|
||||
/// An iterator visiting all header pairs in arbitrary order.
|
||||
|
@ -160,7 +158,7 @@ impl Trailers {
|
|||
impl Clone for Trailers {
|
||||
fn clone(&self) -> Self {
|
||||
Self {
|
||||
headers: Headers {
|
||||
headers: Fields {
|
||||
headers: self.headers.headers.clone(),
|
||||
},
|
||||
}
|
||||
|
@ -168,7 +166,7 @@ impl Clone for Trailers {
|
|||
}
|
||||
|
||||
impl Deref for Trailers {
|
||||
type Target = Headers;
|
||||
type Target = Fields;
|
||||
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&self.headers
|
||||
|
@ -181,8 +179,8 @@ impl DerefMut for Trailers {
|
|||
}
|
||||
}
|
||||
|
||||
impl Index<HeaderName> for Trailers {
|
||||
type Output = HeaderValues;
|
||||
impl Index<FieldName> for Trailers {
|
||||
type Output = FieldValues;
|
||||
|
||||
/// Returns a reference to the value corresponding to the supplied name.
|
||||
///
|
||||
|
@ -190,13 +188,13 @@ impl Index<HeaderName> for Trailers {
|
|||
///
|
||||
/// Panics if the name is not present in `Trailers`.
|
||||
#[inline]
|
||||
fn index(&self, name: HeaderName) -> &HeaderValues {
|
||||
fn index(&self, name: FieldName) -> &FieldValues {
|
||||
self.headers.index(name)
|
||||
}
|
||||
}
|
||||
|
||||
impl Index<&str> for Trailers {
|
||||
type Output = HeaderValues;
|
||||
type Output = FieldValues;
|
||||
|
||||
/// Returns a reference to the value corresponding to the supplied name.
|
||||
///
|
||||
|
@ -204,7 +202,7 @@ impl Index<&str> for Trailers {
|
|||
///
|
||||
/// Panics if the name is not present in `Trailers`.
|
||||
#[inline]
|
||||
fn index(&self, name: &str) -> &HeaderValues {
|
||||
fn index(&self, name: &str) -> &FieldValues {
|
||||
self.headers.index(name)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use crate::headers::HeaderValue;
|
||||
use crate::headers::FieldValue;
|
||||
use std::fmt::{self, Display};
|
||||
|
||||
/// Available compression algorithms.
|
||||
|
@ -56,9 +56,9 @@ impl Display for Encoding {
|
|||
}
|
||||
}
|
||||
|
||||
impl From<Encoding> for HeaderValue {
|
||||
impl From<Encoding> for FieldValue {
|
||||
fn from(directive: Encoding) -> Self {
|
||||
let s = directive.to_string();
|
||||
unsafe { HeaderValue::from_bytes_unchecked(s.into_bytes()) }
|
||||
unsafe { FieldValue::from_bytes_unchecked(s.into_bytes()) }
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use crate::ensure;
|
||||
use crate::headers::HeaderValue;
|
||||
use crate::headers::FieldValue;
|
||||
use crate::transfer::Encoding;
|
||||
use crate::utils::parse_weight;
|
||||
|
||||
|
@ -110,13 +110,13 @@ impl PartialOrd for EncodingProposal {
|
|||
}
|
||||
}
|
||||
|
||||
impl From<EncodingProposal> for HeaderValue {
|
||||
fn from(entry: EncodingProposal) -> HeaderValue {
|
||||
impl From<EncodingProposal> for FieldValue {
|
||||
fn from(entry: EncodingProposal) -> FieldValue {
|
||||
let s = match entry.weight {
|
||||
Some(weight) => format!("{};q={:.3}", entry.encoding, weight),
|
||||
None => entry.encoding.to_string(),
|
||||
};
|
||||
unsafe { HeaderValue::from_bytes_unchecked(s.into_bytes()) }
|
||||
unsafe { FieldValue::from_bytes_unchecked(s.into_bytes()) }
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use crate::headers::{self, Header, HeaderName, HeaderValue, Headers};
|
||||
use crate::headers::{self, Field, FieldName, FieldValue, Fields};
|
||||
use crate::transfer::{Encoding, EncodingProposal, TransferEncoding};
|
||||
use crate::utils::sort_by_weight;
|
||||
use crate::{Error, StatusCode};
|
||||
|
@ -52,7 +52,7 @@ impl TE {
|
|||
}
|
||||
|
||||
/// Create an instance of `TE` from a `Headers` instance.
|
||||
pub fn from_headers(headers: impl AsRef<Headers>) -> crate::Result<Option<Self>> {
|
||||
pub fn from_headers(headers: impl AsRef<Fields>) -> crate::Result<Option<Self>> {
|
||||
let mut entries = vec![];
|
||||
let headers = match headers.as_ref().get(headers::TE) {
|
||||
Some(headers) => headers,
|
||||
|
@ -151,15 +151,11 @@ impl TE {
|
|||
}
|
||||
}
|
||||
|
||||
impl Header for TE {
|
||||
fn header_name(&self) -> HeaderName {
|
||||
headers::TE
|
||||
}
|
||||
|
||||
fn header_value(&self) -> HeaderValue {
|
||||
impl Field for TE {
|
||||
fn field_value(&self) -> FieldValue {
|
||||
let mut output = String::new();
|
||||
for (n, directive) in self.entries.iter().enumerate() {
|
||||
let directive: HeaderValue = (*directive).into();
|
||||
let directive: FieldValue = (*directive).into();
|
||||
match n {
|
||||
0 => write!(output, "{}", directive).unwrap(),
|
||||
_ => write!(output, ", {}", directive).unwrap(),
|
||||
|
@ -174,8 +170,10 @@ impl Header for TE {
|
|||
}
|
||||
|
||||
// SAFETY: the internal string is validated to be ASCII.
|
||||
unsafe { HeaderValue::from_bytes_unchecked(output.into()) }
|
||||
unsafe { FieldValue::from_bytes_unchecked(output.into()) }
|
||||
}
|
||||
|
||||
const FIELD_NAME: FieldName = headers::TE;
|
||||
}
|
||||
|
||||
impl IntoIterator for TE {
|
||||
|
@ -289,7 +287,7 @@ mod test {
|
|||
accept.push(Encoding::Gzip);
|
||||
|
||||
let mut headers = Response::new(200);
|
||||
headers.insert(accept);
|
||||
headers.insert_typed_header(accept);
|
||||
|
||||
let accept = TE::from_headers(headers)?.unwrap();
|
||||
assert_eq!(accept.iter().next().unwrap(), Encoding::Gzip);
|
||||
|
@ -302,7 +300,7 @@ mod test {
|
|||
accept.set_wildcard(true);
|
||||
|
||||
let mut headers = Response::new(200);
|
||||
headers.insert(accept);
|
||||
headers.insert_typed_header(accept);
|
||||
|
||||
let accept = TE::from_headers(headers)?.unwrap();
|
||||
assert!(accept.wildcard());
|
||||
|
@ -316,7 +314,7 @@ mod test {
|
|||
accept.set_wildcard(true);
|
||||
|
||||
let mut headers = Response::new(200);
|
||||
headers.insert(accept);
|
||||
headers.insert_typed_header(accept);
|
||||
|
||||
let accept = TE::from_headers(headers)?.unwrap();
|
||||
assert!(accept.wildcard());
|
||||
|
@ -331,7 +329,7 @@ mod test {
|
|||
accept.push(Encoding::Brotli);
|
||||
|
||||
let mut headers = Response::new(200);
|
||||
headers.insert(accept);
|
||||
headers.insert_typed_header(accept);
|
||||
|
||||
let accept = TE::from_headers(headers)?.unwrap();
|
||||
let mut accept = accept.iter();
|
||||
|
@ -348,7 +346,7 @@ mod test {
|
|||
accept.push(EncodingProposal::new(Encoding::Brotli, Some(0.8))?);
|
||||
|
||||
let mut headers = Response::new(200);
|
||||
headers.insert(accept);
|
||||
headers.insert_typed_header(accept);
|
||||
|
||||
let mut accept = TE::from_headers(headers)?.unwrap();
|
||||
accept.sort();
|
||||
|
@ -367,7 +365,7 @@ mod test {
|
|||
accept.push(EncodingProposal::new(Encoding::Brotli, Some(0.8))?);
|
||||
|
||||
let mut res = Response::new(200);
|
||||
accept.apply_header(&mut res);
|
||||
res.insert_typed_header(accept);
|
||||
|
||||
let mut accept = TE::from_headers(res)?.unwrap();
|
||||
accept.sort();
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use crate::headers::{Header, HeaderName, HeaderValue, Headers, TRANSFER_ENCODING};
|
||||
use crate::headers::{Field, FieldName, FieldValue, Fields, TRANSFER_ENCODING};
|
||||
use crate::transfer::{Encoding, EncodingProposal};
|
||||
|
||||
use std::fmt::{self, Debug};
|
||||
|
@ -40,7 +40,7 @@ impl TransferEncoding {
|
|||
}
|
||||
|
||||
/// Create a new instance from headers.
|
||||
pub fn from_headers(headers: impl AsRef<Headers>) -> crate::Result<Option<Self>> {
|
||||
pub fn from_headers(headers: impl AsRef<Fields>) -> crate::Result<Option<Self>> {
|
||||
let headers = match headers.as_ref().get(TRANSFER_ENCODING) {
|
||||
Some(headers) => headers,
|
||||
None => return Ok(None),
|
||||
|
@ -64,11 +64,9 @@ impl TransferEncoding {
|
|||
}
|
||||
}
|
||||
|
||||
impl Header for TransferEncoding {
|
||||
fn header_name(&self) -> HeaderName {
|
||||
TRANSFER_ENCODING
|
||||
}
|
||||
fn header_value(&self) -> HeaderValue {
|
||||
impl Field for TransferEncoding {
|
||||
const FIELD_NAME: FieldName = TRANSFER_ENCODING;
|
||||
fn field_value(&self) -> FieldValue {
|
||||
self.inner.into()
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue