Coverage Report

Created: 2026-03-23 07:13

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/headers-0.4.1/src/common/connection.rs
Line
Count
Source
1
use std::iter::FromIterator;
2
3
use http::{HeaderName, HeaderValue};
4
5
use self::sealed::AsConnectionOption;
6
use crate::util::FlatCsv;
7
8
/// `Connection` header, defined in
9
/// [RFC7230](https://datatracker.ietf.org/doc/html/rfc7230#section-6.1)
10
///
11
/// The `Connection` header field allows the sender to indicate desired
12
/// control options for the current connection.  In order to avoid
13
/// confusing downstream recipients, a proxy or gateway MUST remove or
14
/// replace any received connection options before forwarding the
15
/// message.
16
///
17
/// # ABNF
18
///
19
/// ```text
20
/// Connection        = 1#connection-option
21
/// connection-option = token
22
///
23
/// # Example values
24
/// * `close`
25
/// * `keep-alive`
26
/// * `upgrade`
27
/// ```
28
///
29
/// # Examples
30
///
31
/// ```
32
/// use headers::Connection;
33
///
34
/// let keep_alive = Connection::keep_alive();
35
/// ```
36
// This is frequently just 1 or 2 values, so optimize for that case.
37
#[derive(Clone, Debug)]
38
pub struct Connection(FlatCsv);
39
40
derive_header! {
41
    Connection(_),
42
    name: CONNECTION
43
}
44
45
impl Connection {
46
    /// A constructor to easily create a `Connection: close` header.
47
    #[inline]
48
0
    pub fn close() -> Connection {
49
0
        Connection(HeaderValue::from_static("close").into())
50
0
    }
51
52
    /// A constructor to easily create a `Connection: keep-alive` header.
53
    #[inline]
54
0
    pub fn keep_alive() -> Connection {
55
0
        Connection(HeaderValue::from_static("keep-alive").into())
56
0
    }
57
58
    /// A constructor to easily create a `Connection: Upgrade` header.
59
    #[inline]
60
0
    pub fn upgrade() -> Connection {
61
0
        Connection(HeaderValue::from_static("upgrade").into())
62
0
    }
63
64
    /// Check if this header contains a given "connection option".
65
    ///
66
    /// This can be used with various argument types:
67
    ///
68
    /// - `&str`
69
    /// - `&HeaderName`
70
    /// - `HeaderName`
71
    ///
72
    /// # Example
73
    ///
74
    /// ```
75
    /// extern crate http;
76
    ///
77
    /// use http::header::UPGRADE;
78
    /// use headers::Connection;
79
    ///
80
    /// let conn = Connection::keep_alive();
81
    ///
82
    /// assert!(!conn.contains("close"));
83
    /// assert!(!conn.contains(UPGRADE));
84
    /// assert!(conn.contains("keep-alive"));
85
    /// assert!(conn.contains("Keep-Alive"));
86
    /// ```
87
0
    pub fn contains(&self, name: impl AsConnectionOption) -> bool {
88
0
        let s = name.as_connection_option();
89
0
        self.0.iter().any(|opt| opt.eq_ignore_ascii_case(s))
90
0
    }
91
}
92
93
impl FromIterator<HeaderName> for Connection {
94
0
    fn from_iter<I>(iter: I) -> Self
95
0
    where
96
0
        I: IntoIterator<Item = HeaderName>,
97
    {
98
0
        let flat = iter.into_iter().map(HeaderValue::from).collect();
99
0
        Connection(flat)
100
0
    }
101
}
102
103
mod sealed {
104
    use http::HeaderName;
105
106
    pub trait AsConnectionOption: Sealed {
107
        fn as_connection_option(&self) -> &str;
108
    }
109
    pub trait Sealed {}
110
111
    impl AsConnectionOption for &str {
112
0
        fn as_connection_option(&self) -> &str {
113
0
            self
114
0
        }
115
    }
116
117
    impl Sealed for &str {}
118
119
    impl AsConnectionOption for &HeaderName {
120
0
        fn as_connection_option(&self) -> &str {
121
0
            self.as_ref()
122
0
        }
123
    }
124
125
    impl Sealed for &HeaderName {}
126
127
    impl AsConnectionOption for HeaderName {
128
0
        fn as_connection_option(&self) -> &str {
129
0
            self.as_ref()
130
0
        }
131
    }
132
133
    impl Sealed for HeaderName {}
134
}