eduboardapi/services/
client.rs1use crate::config::{AppConfig, BASE_URL, RESULT_ENDPOINT};
2use crate::exceptions::{AppError, AppResult};
3use reqwest::cookie::Jar;
4use reqwest::header::{ACCEPT, ACCEPT_LANGUAGE, HeaderMap, HeaderValue, USER_AGENT};
5use reqwest::{Client, Url};
6use std::sync::Arc;
7use std::time::Duration;
8
9pub struct HttpClient {
10 config: AppConfig,
11 default_headers: HeaderMap,
12}
13
14impl HttpClient {
15 pub fn new(config: AppConfig) -> Self {
16 let mut default_headers = HeaderMap::new();
17 default_headers.insert(
18 ACCEPT,
19 HeaderValue::from_static("text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"),
20 );
21 default_headers.insert(ACCEPT_LANGUAGE, HeaderValue::from_static("en-US,en;q=0.9"));
22 default_headers.insert(
23 USER_AGENT,
24 HeaderValue::from_static("Mozilla/5.0 (X11; Linux x86_64) EduBoardAPI/1.1"),
25 );
26
27 Self { config, default_headers }
28 }
29
30 fn build_session_client(&self) -> AppResult<Client> {
31 let cookie_jar = Jar::default();
32 Client::builder()
33 .cookie_provider(Arc::new(cookie_jar))
34 .default_headers(self.default_headers.clone())
35 .connect_timeout(Duration::from_secs(5))
36 .timeout(Duration::from_secs(self.config.timeout_seconds))
37 .pool_idle_timeout(Duration::from_secs(30))
38 .tcp_keepalive(Duration::from_secs(30))
39 .build()
40 .map_err(|e| AppError::Network(e.to_string()))
41 }
42
43 pub async fn get_homepage(&self) -> AppResult<(Client, String)> {
44 let client = self.build_session_client()?;
45 let url = Url::parse(BASE_URL).expect("Invalid BASE_URL");
46 let resp = client
47 .get(url)
48 .send()
49 .await
50 .map_err(|e| AppError::Network(e.to_string()))?;
51 let body = resp
52 .text()
53 .await
54 .map_err(|e| AppError::Network(e.to_string()))?;
55 Ok((client, body))
56 }
57
58 pub async fn submit_result_form<T: serde::Serialize>(&self, client: &Client, form_data: &T) -> AppResult<String> {
59 let url =
60 Url::parse(&format!("{BASE_URL}/{RESULT_ENDPOINT}")).expect("Invalid RESULT_ENDPOINT");
61 let resp = client
62 .post(url)
63 .form(form_data)
64 .send()
65 .await
66 .map_err(|e| AppError::Network(e.to_string()))?;
67 resp.text()
68 .await
69 .map_err(|e| AppError::Network(e.to_string()))
70 }
71}