anttp 0.26.0

AntTP is an HTTP server for the Autonomi Network
use std::time::{Duration, SystemTime};
use actix_files::file_extension_to_mime;
use actix_http::header;
use actix_web::http::header::{CacheControl, CacheDirective, ContentLength, ContentRange, ContentRangeSpec, ContentType, ETag, EntityTag, Expires, HeaderName};
use ant_core::data::XorName;
use chrono::DateTime;
use hex::ToHex;
use mime::Mime;

pub struct HeaderBuilder {
    cached_mutable_ttl: u64
}

impl HeaderBuilder {
    
    pub fn new(cached_mutable_ttl: u64) -> Self {
        Self { cached_mutable_ttl }
    }
    
    pub fn build_cache_control_header(&self, is_resolved_from_mutable: bool) -> CacheControl {
        if !is_resolved_from_mutable {
            CacheControl(vec![CacheDirective::MaxAge(u32::MAX), CacheDirective::Public]) // immutable
        } else {
            CacheControl(vec![CacheDirective::MaxAge(u32::try_from(self.cached_mutable_ttl).unwrap_or(0)), CacheDirective::Public]) // mutable
        }
    }

    pub fn build_expires_header(&self, is_resolved_from_mutable: bool) -> Expires {
        if !is_resolved_from_mutable {
            Expires((SystemTime::now() + Duration::from_secs(u64::from(u32::MAX))).into()) // immutable
        } else {
            Expires((SystemTime::now() + Duration::from_secs(self.cached_mutable_ttl)).into()) // mutable
        }
    }

    pub fn build_content_type_header(&self, extension: &str) -> ContentType {
        if extension != "" {
            ContentType(file_extension_to_mime(extension))
        } else {
            ContentType(mime::TEXT_HTML) // default to text/html
        }
    }

    pub fn build_last_modified_header(&self, time: u64) -> (HeaderName, String) {
        let mtime_datetime = DateTime::from_timestamp_millis( i64::try_from(time)
            .unwrap_or(0) * 1000)
            .unwrap_or(DateTime::default());
        let mtime_iso = mtime_datetime.format("%a, %d %b %Y %H:%M:%S GMT");
        (header::LAST_MODIFIED, mtime_iso.to_string())
    }

    pub fn build_content_type_header_from_mime(&self, mime: &Mime) -> ContentType {
        ContentType(mime.clone())
    }
    
    pub fn build_etag_header(&self, xor_name: &XorName) -> ETag {
        ETag(EntityTag::new_strong(xor_name.encode_hex()).to_owned())
    }

    pub fn build_cors_header(&self) -> (HeaderName, &str) {
        (header::ACCESS_CONTROL_ALLOW_ORIGIN, "*")
    }

    pub fn build_server_header(&self) -> (HeaderName, String) {
        (header::SERVER, format!("{}/{}", env!("CARGO_PKG_NAME"), env!("CARGO_PKG_VERSION")))
    }
    
    pub fn build_content_range_header(&self, range_from: u64, range_to: u64, content_length: u64) -> ContentRange {
        ContentRange(ContentRangeSpec::Bytes { range: Some((range_from, range_to)), instance_length: Some(content_length) })
    }
    
    pub fn build_accept_ranges_header(&self) -> (HeaderName, &str) {
        (header::ACCEPT_RANGES, "bytes")
    }
    
    pub fn build_content_length_header(&self, content_length: u64) -> ContentLength {
        ContentLength(usize::try_from(content_length).unwrap_or(0))
    }
    
    pub fn build_location_header(&self, path: String) -> (HeaderName, String) {
        (header::LOCATION, path.to_string())
    }
}