use crate::config::service_info::PackageInfo;
use crate::error::Error::ParseError;
use crate::error::{Error, Result};
use crate::http::client::HttpClientConfig;
use http_cache_reqwest::{CACacheManager, Cache, CacheMode, HttpCache, HttpCacheOptions};
use reqwest::Client;
use reqwest_middleware::ClientWithMiddleware;
use serde::{Deserialize, Serialize};
use std::env::temp_dir;
use std::fs::File;
use std::io::Read;
use std::path::PathBuf;
pub mod allow_guard;
pub mod auth;
pub mod cors;
#[cfg(feature = "url")]
pub mod json_path;
pub mod regex_location;
#[cfg(feature = "url")]
pub mod url;
pub const CONTEXT_HEADER_PREFIX: &str = "Htsget-Context-";
#[derive(Debug, Copy, Clone, Serialize, Deserialize, Default)]
#[serde(deny_unknown_fields)]
pub enum FormattingStyle {
#[default]
Full,
Compact,
Pretty,
Json,
}
#[derive(Deserialize, Debug, Clone)]
#[serde(deny_unknown_fields, from = "HttpClientConfig")]
pub struct HttpClient {
config: Option<HttpClientConfig>,
client: Option<ClientWithMiddleware>,
}
impl HttpClient {
pub fn new(client: ClientWithMiddleware) -> Self {
Self {
config: None,
client: Some(client),
}
}
pub fn new_with_config(config: HttpClientConfig) -> Self {
Self {
config: Some(config),
client: None,
}
}
pub fn take_config(&mut self) -> Result<HttpClientConfig> {
self
.config
.take()
.ok_or_else(|| ParseError("client already built".to_string()))
}
pub fn set_config(&mut self, config: HttpClientConfig) {
self.config = Some(config);
}
pub fn as_inner_built(&mut self) -> Result<&ClientWithMiddleware> {
if let Some(ref client) = self.client {
return Ok(client);
}
let config = self.take_config()?;
let mut builder = Client::builder();
let (certs, identity, use_cache, user_agent) = config.into_inner();
if let Some(certs) = certs {
for cert in certs {
builder = builder.add_root_certificate(cert);
}
}
if let Some(identity) = identity {
builder = builder.identity(identity);
}
if let Some(user_agent) = user_agent {
builder = builder.user_agent(user_agent);
}
let inner_client = builder
.build()
.map_err(|err| ParseError(format!("building http client: {err}")))?;
let client = if use_cache {
let client_cache = temp_dir().join("htsget_rs_client_cache");
reqwest_middleware::ClientBuilder::new(inner_client)
.with(Cache(HttpCache {
mode: CacheMode::Default,
manager: CACacheManager::new(client_cache, false),
options: HttpCacheOptions::default(),
}))
.build()
} else {
reqwest_middleware::ClientBuilder::new(inner_client).build()
};
self.client = Some(client);
Ok(self.client.as_ref().expect("expected client"))
}
pub fn set_from_package_info(&mut self, info: &PackageInfo) -> Result<()> {
let builder = self.take_config()?;
self.set_config(builder.with_user_agent(info.id.to_string()));
Ok(())
}
}
impl From<HttpClientConfig> for HttpClient {
fn from(config: HttpClientConfig) -> Self {
Self::new_with_config(config)
}
}
pub struct Bytes(Vec<u8>);
impl Bytes {
pub fn new(data: Vec<u8>) -> Self {
Self(data)
}
pub fn into_inner(self) -> Vec<u8> {
self.0
}
}
impl TryFrom<PathBuf> for Bytes {
type Error = Error;
fn try_from(path: PathBuf) -> Result<Self> {
let mut bytes = vec![];
File::open(path)?.read_to_end(&mut bytes)?;
Ok(Self(bytes))
}
}