use std::borrow::Cow;
#[derive(Clone, Debug, Default)]
pub struct Headers<'a>(Vec<Header<'a>>);
impl<'a> Headers<'a> {
pub fn new() -> Self {
Self::default()
}
pub fn set(&mut self, header: Header<'a>) {
self.0.retain(|old_header| header.name != old_header.name);
self.0.push(header);
}
pub fn add(&mut self, header: Header<'a>) {
self.0.push(header);
}
}
impl<'a, N, V> FromIterator<(N, V)> for Headers<'a>
where
N: Into<Cow<'a, str>>,
V: Into<Cow<'a, str>>,
{
fn from_iter<I: IntoIterator<Item = (N, V)>>(iter: I) -> Self {
let mut headers = Self::default();
for (name, value) in iter {
headers.set(Header::custom(name, value));
}
headers
}
}
impl<'a> IntoIterator for Headers<'a> {
type Item = Header<'a>;
type IntoIter = std::vec::IntoIter<Self::Item>;
fn into_iter(self) -> Self::IntoIter {
self.0.into_iter()
}
}
#[allow(clippy::fallible_impl_from)]
impl<'a, FT: AsRef<web_sys::Headers>> From<FT> for Headers<'a> {
fn from(headers: FT) -> Self {
js_sys::try_iter(headers.as_ref())
.unwrap()
.unwrap()
.map(|entry| js_sys::Array::from(&entry.unwrap()))
.map(|entry| {
(
entry.get(0).as_string().unwrap(),
entry.get(1).as_string().unwrap(),
)
})
.collect()
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Header<'a> {
pub(crate) name: Cow<'a, str>,
pub(crate) value: Cow<'a, str>,
}
impl<'a> Header<'a> {
pub fn name(&'a self) -> &'a str {
&self.name
}
pub fn value(&'a self) -> &'a str {
&self.value
}
pub fn content_type(value: impl Into<Cow<'a, str>>) -> Header<'a> {
Self::custom("Content-Type", value)
}
pub fn authorization(value: impl Into<Cow<'a, str>>) -> Header<'a> {
Self::custom("Authorization", value)
}
pub fn bearer(token: impl Into<Cow<'a, str>>) -> Header<'a> {
Self::custom("Authorization", format!("Bearer {}", token.into()))
}
pub fn custom(name: impl Into<Cow<'a, str>>, value: impl Into<Cow<'a, str>>) -> Header<'a> {
Header {
name: name.into(),
value: value.into(),
}
}
}
#[cfg(test)]
pub mod tests {
use super::*;
use wasm_bindgen_test::*;
wasm_bindgen_test_configure!(run_in_browser);
#[wasm_bindgen_test]
fn test_headers_from_ws_headers() {
let ws_headers = web_sys::Headers::new().unwrap();
ws_headers
.append("a_header_name", "a_header_value")
.unwrap();
let headers = Headers::from(&ws_headers);
assert_eq!(
headers.into_iter().next().unwrap(),
Header::custom("a_header_name", "a_header_value")
);
}
}