1use crate::{
5 contents::Contents,
6 diagnostic::IntoDiagnostic,
7 file::{BinaryFile, SourceFile},
8 path::Path,
9 Cache, Query, Result,
10};
11use std::sync::Arc;
12
13pub use http::response::Parts;
14pub use reqwest::Client;
15
16fn default_headers() -> reqwest::header::HeaderMap {
17 let mut map = reqwest::header::HeaderMap::new();
18
19 map.insert("accept", "text/plain".parse().unwrap());
20
21 map
22}
23
24pub fn client() -> Query<Client> {
25 #[derive(Clone, Copy, Debug, Hash, Eq, PartialEq)]
26 struct Q;
27
28 Cache::current().get_or_init(Q, || {
29 Query::from(
30 Client::builder()
31 .user_agent(concat!(
32 env!("CARGO_PKG_NAME"),
33 "/",
34 env!("CARGO_PKG_VERSION")
35 ))
36 .default_headers(default_headers())
37 .build()
38 .unwrap(),
39 )
40 })
41}
42
43pub fn get_full<U>(url: U) -> Query<Result<(Arc<Parts>, Contents)>>
44where
45 U: 'static + Clone + AsRef<str> + Send + Sync,
46{
47 Cache::current().get_or_init(url.as_ref().to_string(), move || {
48 Query::new(async move {
49 let client = client().await;
50
51 let resp = client.get(url.as_ref()).send().await.into_diagnostic()?;
52 let mut resp = resp.error_for_status().into_diagnostic()?;
53
54 let mut body = vec![];
55
56 while let Some(chunk) = resp.chunk().await.into_diagnostic()? {
57 body.extend_from_slice(&chunk);
58 }
59
60 let resp: http::Response<reqwest::Body> = resp.into();
61
62 let (headers, _) = resp.into_parts();
63
64 let headers = Arc::new(headers);
65 let body = Contents::from(body);
66
67 Ok((headers, body))
68 })
69 })
70}
71
72pub fn get<U>(url: U) -> Query<Result<Contents>>
73where
74 U: 'static + Clone + AsRef<str> + Send + Sync,
75{
76 Query::new(async move {
77 let resp = get_full(url).await?;
78 Ok(resp.1)
79 })
80}
81
82pub fn get_cached<U, P>(url: U, cached_path: P) -> Query<Result<BinaryFile>>
83where
84 U: 'static + Clone + AsRef<str> + Send + Sync,
85 P: Into<Path>,
86{
87 crate::vfs::read_file_or_create(cached_path, get(url))
88}
89
90pub fn get_cached_string<U, P>(url: U, cached_path: P) -> Query<Result<SourceFile>>
91where
92 U: 'static + Clone + AsRef<str> + Send + Sync,
93 P: Into<Path>,
94{
95 crate::vfs::read_string_or_create(cached_path, get(url))
96}