httpio 0.2.4

A transport-agnostic, async HTTP/1.1 client library for any runtime.
Documentation
use crate::compression;
use crate::enums::header::http_header::HttpHeader;
use crate::enums::http_body::HttpBody;
use crate::enums::http_request_method::HttpRequestMethod;
use crate::enums::http_version::HttpVersion;
use crate::structures::header::header_list::HttpHeaderList;
use crate::structures::http_message::HttpMessage;
use crate::utils::http_header_field_name::{self, USER_AGENT};
use std::fmt::Write;

pub struct HttpRequestBuilder {
    pub headers: HttpHeaderList,
    pub http_version: HttpVersion,
    pub host: String,
}

impl HttpRequestBuilder {
    pub fn new(
        http_version: HttpVersion,
        headers: HttpHeaderList,
        host: impl Into<String>,
    ) -> HttpRequestBuilder {
        let host: String = host.into();

        let supported = compression::supported_encodings();
        let mut encoding_str = String::with_capacity(64);
        let mut first = true;
        for enc in &supported {
            if !first {
                encoding_str.push_str(", ");
            }
            let _ = write!(encoding_str, "{}", enc);
            first = false;
        }

        let mut default_headers: HttpHeaderList = vec![
            HttpHeader::new(http_header_field_name::HOST, &host),
            HttpHeader::new(http_header_field_name::USER_AGENT, USER_AGENT),
            HttpHeader::new(http_header_field_name::ACCEPT, "text/html;q=0.9,*/*;q=0.8"),
        ]
        .into();

        if !encoding_str.is_empty() {
            default_headers.add(HttpHeader::new(
                http_header_field_name::ACCEPT_ENCODING,
                &encoding_str,
            ));
            default_headers.add(HttpHeader::new(http_header_field_name::TE, &encoding_str));
        }

        default_headers.merge_items(headers.into_iter().map(|(_, header)| header));

        HttpRequestBuilder {
            headers: default_headers,
            http_version,
            host,
        }
    }

    pub fn build_request<T: Into<HttpHeaderList>>(
        &self,
        method: HttpRequestMethod,
        path_query: &str,
        headers: T,
        body: HttpBody,
    ) -> HttpMessage {
        let start_line = format!(
            "{} {} {}",
            method.to_string(),
            path_query,
            self.http_version.to_string()
        );
        let mut headers: HttpHeaderList = headers.into();
        headers.merge_items(self.headers.iter().map(|(_, header)| header).cloned());
        HttpMessage::new(start_line, headers, body)
    }
}