htsget_config/config/advanced/
mod.rs1use crate::config::service_info::PackageInfo;
5use crate::error::Error::ParseError;
6use crate::error::{Error, Result};
7use crate::http::client::HttpClientConfig;
8use http_cache_reqwest::{CACacheManager, Cache, CacheMode, HttpCache, HttpCacheOptions};
9use reqwest::Client;
10use reqwest_middleware::ClientWithMiddleware;
11use serde::{Deserialize, Serialize};
12use std::env::temp_dir;
13use std::fs::File;
14use std::io::Read;
15use std::path::PathBuf;
16
17pub mod allow_guard;
18pub mod auth;
19pub mod cors;
20pub mod regex_location;
21#[cfg(feature = "url")]
22pub mod url;
23
24pub const CONTEXT_HEADER_PREFIX: &str = "Htsget-Context-";
26
27#[derive(Debug, Copy, Clone, Serialize, Deserialize, Default)]
29#[serde(deny_unknown_fields)]
30pub enum FormattingStyle {
31 #[default]
32 Full,
33 Compact,
34 Pretty,
35 Json,
36}
37
38#[derive(Deserialize, Debug, Clone)]
40#[serde(deny_unknown_fields, from = "HttpClientConfig")]
41pub struct HttpClient {
42 config: Option<HttpClientConfig>,
43 client: Option<ClientWithMiddleware>,
44}
45
46impl HttpClient {
47 pub fn new(client: ClientWithMiddleware) -> Self {
49 Self {
50 config: None,
51 client: Some(client),
52 }
53 }
54
55 pub fn new_with_config(config: HttpClientConfig) -> Self {
57 Self {
58 config: Some(config),
59 client: None,
60 }
61 }
62
63 pub fn take_config(&mut self) -> Result<HttpClientConfig> {
65 self
66 .config
67 .take()
68 .ok_or_else(|| ParseError("client already built".to_string()))
69 }
70
71 pub fn set_config(&mut self, config: HttpClientConfig) {
73 self.config = Some(config);
74 }
75
76 pub fn as_inner_built(&mut self) -> Result<&ClientWithMiddleware> {
78 if let Some(ref client) = self.client {
79 return Ok(client);
80 }
81
82 let config = self.take_config()?;
83 let mut builder = Client::builder();
84
85 let (certs, identity, use_cache, user_agent) = config.into_inner();
86
87 if let Some(certs) = certs {
88 for cert in certs {
89 builder = builder.add_root_certificate(cert);
90 }
91 }
92 if let Some(identity) = identity {
93 builder = builder.identity(identity);
94 }
95 if let Some(user_agent) = user_agent {
96 builder = builder.user_agent(user_agent);
97 }
98
99 let inner_client = builder
100 .build()
101 .map_err(|err| ParseError(format!("building http client: {err}")))?;
102 let client = if use_cache {
103 let client_cache = temp_dir().join("htsget_rs_client_cache");
104 reqwest_middleware::ClientBuilder::new(inner_client)
105 .with(Cache(HttpCache {
106 mode: CacheMode::Default,
107 manager: CACacheManager::new(client_cache, false),
108 options: HttpCacheOptions::default(),
109 }))
110 .build()
111 } else {
112 reqwest_middleware::ClientBuilder::new(inner_client).build()
113 };
114
115 self.client = Some(client);
116 Ok(self.client.as_ref().expect("expected client"))
117 }
118
119 pub fn set_from_package_info(&mut self, info: &PackageInfo) -> Result<()> {
121 let builder = self.take_config()?;
122 self.set_config(builder.with_user_agent(info.id.to_string()));
123
124 Ok(())
125 }
126}
127
128impl From<HttpClientConfig> for HttpClient {
129 fn from(config: HttpClientConfig) -> Self {
130 Self::new_with_config(config)
131 }
132}
133
134pub struct Bytes(Vec<u8>);
136
137impl Bytes {
138 pub fn new(data: Vec<u8>) -> Self {
140 Self(data)
141 }
142
143 pub fn into_inner(self) -> Vec<u8> {
145 self.0
146 }
147}
148
149impl TryFrom<PathBuf> for Bytes {
150 type Error = Error;
151
152 fn try_from(path: PathBuf) -> Result<Self> {
153 let mut bytes = vec![];
154 File::open(path)?.read_to_end(&mut bytes)?;
155 Ok(Self(bytes))
156 }
157}