grafbase_sdk/host/
headers.rs

1use crate::wit;
2
3/// HTTP headers.
4pub struct HttpHeaders(wit::Headers);
5
6/// HTTP headers for the gateway request.
7pub struct GatewayHeaders(HttpHeaders);
8
9impl From<wit::Headers> for GatewayHeaders {
10    fn from(headers: wit::Headers) -> Self {
11        Self(HttpHeaders(headers))
12    }
13}
14
15impl std::ops::Deref for GatewayHeaders {
16    type Target = HttpHeaders;
17    fn deref(&self) -> &Self::Target {
18        &self.0
19    }
20}
21
22impl std::ops::DerefMut for GatewayHeaders {
23    fn deref_mut(&mut self) -> &mut Self::Target {
24        &mut self.0
25    }
26}
27
28/// HTTP headers for the subgraph request.
29pub struct SubgraphHeaders(HttpHeaders);
30
31impl From<wit::Headers> for SubgraphHeaders {
32    fn from(headers: wit::Headers) -> Self {
33        Self(HttpHeaders(headers))
34    }
35}
36
37impl std::ops::Deref for SubgraphHeaders {
38    type Target = HttpHeaders;
39    fn deref(&self) -> &Self::Target {
40        &self.0
41    }
42}
43
44impl std::ops::DerefMut for SubgraphHeaders {
45    fn deref_mut(&mut self) -> &mut Self::Target {
46        &mut self.0
47    }
48}
49
50// Imitates as much as possible the http::HeaderMap API
51impl HttpHeaders {
52    /// Get the value associated with the given name. If there are multiple values associated with
53    /// the name, then the first one is returned. Use `get_all` to get all values associated with
54    /// a given name. Returns None if there are no values associated with the name.
55    pub fn get(&self, name: &str) -> Option<http::HeaderValue> {
56        self.0
57            .get(name)
58            .into_iter()
59            .next()
60            .map(|value| value.try_into().unwrap())
61    }
62
63    /// Get all of the values corresponding to a name. If the name is not present,
64    /// an empty list is returned. However, if the name is present but empty, this
65    /// is represented by a list with one or more empty values present.
66    pub fn get_all(&self, name: &str) -> impl Iterator<Item = http::HeaderValue> {
67        self.0.get(name).into_iter().map(|value| value.try_into().unwrap())
68    }
69
70    /// Returns true if the map contains a value for the specified name.
71    pub fn has(&self, name: &str) -> bool {
72        self.0.has(name)
73    }
74
75    /// Set all of the values for a name. Clears any existing values for that
76    /// name, if they have been set.
77    pub fn set(&mut self, name: impl Into<http::HeaderName>, values: impl Iterator<Item: Into<http::HeaderValue>>) {
78        let name = Into::<http::HeaderName>::into(name);
79        let values = values
80            .into_iter()
81            .map(|value| Into::<http::HeaderValue>::into(value).as_bytes().to_vec())
82            .collect::<Vec<_>>();
83        self.0
84            .set(name.as_str(), &values)
85            .expect("We have a mut ref & validated name and values.");
86    }
87
88    /// Removes a name from the map, returning the value associated with the name.
89    /// Returns None if the map does not contain the name. If there are multiple values associated with the name, then the first one is returned.
90    pub fn remove(&mut self, name: &str) -> Option<http::HeaderValue> {
91        self.0
92            .get_and_delete(name)
93            .map(|values| values.into_iter().next().map(|value| value.try_into().unwrap()))
94            .expect("We have a mut ref & validated name and values.")
95    }
96
97    /// Append a value for a name. Does not change or delete any existing
98    /// values for that name.
99    pub fn append(&mut self, name: impl Into<http::HeaderName>, value: impl Into<http::HeaderValue>) {
100        let name: http::HeaderName = name.into();
101        let value: http::HeaderValue = value.into();
102        self.0
103            .append(name.as_str(), value.as_bytes())
104            .expect("We have a mut ref & validated name and values.");
105    }
106
107    /// An iterator visiting all name-value pairs.
108    /// The iteration order is arbitrary, but consistent across platforms for the same crate version. Each name will be yielded once per associated value. So, if a name has 3 associated values, it will be yielded 3 times.
109    pub fn iter(&self) -> impl Iterator<Item = (http::HeaderName, http::HeaderValue)> {
110        self.0
111            .entries()
112            .into_iter()
113            .map(|(name, value)| (name.try_into().unwrap(), value.try_into().unwrap()))
114    }
115}
116
117impl From<&GatewayHeaders> for http::HeaderMap {
118    fn from(headers: &GatewayHeaders) -> Self {
119        headers.iter().collect()
120    }
121}
122
123impl From<&SubgraphHeaders> for http::HeaderMap {
124    fn from(headers: &SubgraphHeaders) -> Self {
125        headers.iter().collect()
126    }
127}
128
129impl From<SubgraphHeaders> for http::HeaderMap {
130    fn from(headers: SubgraphHeaders) -> Self {
131        headers.iter().collect()
132    }
133}