Source code
Revision control
Copy as Markdown
Other Tools
use std::iter::FromIterator;
use http::{HeaderName, HeaderValue};
use self::sealed::AsConnectionOption;
use crate::util::FlatCsv;
/// `Connection` header, defined in
///
/// The `Connection` header field allows the sender to indicate desired
/// control options for the current connection. In order to avoid
/// confusing downstream recipients, a proxy or gateway MUST remove or
/// replace any received connection options before forwarding the
/// message.
///
/// # ABNF
///
/// ```text
/// Connection = 1#connection-option
/// connection-option = token
///
/// # Example values
/// * `close`
/// * `keep-alive`
/// * `upgrade`
/// ```
///
/// # Examples
///
/// ```
/// use headers::Connection;
///
/// let keep_alive = Connection::keep_alive();
/// ```
// This is frequently just 1 or 2 values, so optimize for that case.
#[derive(Clone, Debug)]
pub struct Connection(FlatCsv);
derive_header! {
Connection(_),
name: CONNECTION
}
impl Connection {
/// A constructor to easily create a `Connection: close` header.
#[inline]
pub fn close() -> Connection {
Connection(HeaderValue::from_static("close").into())
}
/// A constructor to easily create a `Connection: keep-alive` header.
#[inline]
pub fn keep_alive() -> Connection {
Connection(HeaderValue::from_static("keep-alive").into())
}
/// A constructor to easily create a `Connection: Upgrade` header.
#[inline]
pub fn upgrade() -> Connection {
Connection(HeaderValue::from_static("upgrade").into())
}
/// Check if this header contains a given "connection option".
///
/// This can be used with various argument types:
///
/// - `&str`
/// - `&HeaderName`
/// - `HeaderName`
///
/// # Example
///
/// ```
/// extern crate http;
///
/// use http::header::UPGRADE;
/// use headers::Connection;
///
/// let conn = Connection::keep_alive();
///
/// assert!(!conn.contains("close"));
/// assert!(!conn.contains(UPGRADE));
/// assert!(conn.contains("keep-alive"));
/// assert!(conn.contains("Keep-Alive"));
/// ```
pub fn contains(&self, name: impl AsConnectionOption) -> bool {
let s = name.as_connection_option();
self.0.iter().any(|opt| opt.eq_ignore_ascii_case(s))
}
}
impl FromIterator<HeaderName> for Connection {
fn from_iter<I>(iter: I) -> Self
where
I: IntoIterator<Item = HeaderName>,
{
let flat = iter.into_iter().map(HeaderValue::from).collect();
Connection(flat)
}
}
mod sealed {
use http::HeaderName;
pub trait AsConnectionOption: Sealed {
fn as_connection_option(&self) -> &str;
}
pub trait Sealed {}
impl AsConnectionOption for &str {
fn as_connection_option(&self) -> &str {
self
}
}
impl Sealed for &str {}
impl AsConnectionOption for &HeaderName {
fn as_connection_option(&self) -> &str {
self.as_ref()
}
}
impl Sealed for &HeaderName {}
impl AsConnectionOption for HeaderName {
fn as_connection_option(&self) -> &str {
self.as_ref()
}
}
impl Sealed for HeaderName {}
}