httpclient 0.5.0

HTTP client with middleware. Middleware provides composable support for record/replay, logging, exponential backoff, and more.
Documentation

use std::collections::{BTreeMap};


use std::str::FromStr;
use http::header::HeaderName;
use http::HeaderMap;

use serde::{Serialize, Deserialize};


pub trait AddHeaders {
    fn headers(self, headers: &http::HeaderMap) -> Self;
    fn headers_from_sorted(self, headers: SortedHeaders) -> Self;
}

impl AddHeaders for http::request::Builder {
    fn headers(mut self, headers: &HeaderMap) -> Self {
        for (key, value) in headers.iter() {
            self = self.header(key, value);
        }
        self
    }

    fn headers_from_sorted(mut self, headers: SortedHeaders) -> Self {
        for (key, value) in headers.iter() {
            self = self.header(key, value);
        }
        self
    }
}

impl AddHeaders for http::response::Builder {
    fn headers(mut self, headers: &HeaderMap) -> Self {
        for (key, value) in headers.iter() {
            self = self.header(key, value);
        }
        self
    }

    fn headers_from_sorted(mut self, headers: SortedHeaders) -> Self {
        for (key, value) in headers.iter() {
            self = self.header(key, value);
        }
        self
    }
}

#[derive(Serialize, Deserialize, Default)]
#[serde(transparent)]
pub struct SortedHeaders(BTreeMap<String, String>);

impl SortedHeaders {
    fn iter(&self) -> impl Iterator<Item = (&String, &String)> {
        self.0.iter()
    }
}

impl From<&http::header::HeaderMap> for SortedHeaders {
    fn from(headers: &http::header::HeaderMap) -> Self {
        let mut map = BTreeMap::new();
        for (key, value) in headers.iter() {
            map.insert(key.to_string(), value.to_str().unwrap().to_string());
        }
        SortedHeaders(map)
    }
}


impl Into<http::header::HeaderMap> for SortedHeaders {
    fn into(self) -> http::header::HeaderMap {
        let mut map = http::header::HeaderMap::new();
        for (key, value) in self.0.into_iter() {
            map.insert(HeaderName::from_str(key.as_str()).unwrap(), value.parse().unwrap());
        }
        map
    }
}