deno.land / x / wasm@wasmer-sdk-v0.6.0 / src / package_loader.rs

package_loader.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
use std::{ collections::HashMap, sync::{Arc, Mutex},};
use anyhow::{Context, Error};use bytes::Bytes;use http::{HeaderMap, HeaderValue, Method, StatusCode};use wasmer_wasix::{ bin_factory::BinaryPackage, http::{HttpClient, HttpRequest, HttpResponse}, runtime::resolver::{DistributionInfo, PackageSummary, Resolution, WebcHash},};use webc::Container;
/// A package loader that uses the browser's native APIs to download packages.////// Downloads will be cached based on the [`default`] caching behaviour.////// [`default`]: https://developer.mozilla.org/en-US/docs/Web/API/Request/cache#[derive(Debug, Clone)]pub struct PackageLoader { client: Arc<dyn HttpClient + Send + Sync>, cache: Arc<Cache>,}
impl PackageLoader { pub fn new(client: Arc<dyn HttpClient + Send + Sync>) -> Self { let cache = Arc::new(Cache::default()); PackageLoader { client, cache } }
async fn download(&self, dist: &DistributionInfo) -> Result<Bytes, Error> { let mut headers = HeaderMap::new(); headers.insert("Accept", HeaderValue::from_static("application/webc"));
let request = HttpRequest { url: dist.webc.clone(), method: Method::GET, headers, body: None, options: Default::default(), };
tracing::debug!(%request.url, %request.method, "Downloading a webc file"); tracing::trace!(?request.headers);
let response = self.client.request(request).await?;
tracing::trace!( %response.status, %response.redirected, ?response.headers, response.len=response.body.as_ref().map(|body| body.len()), "Received a response", );
if !response.is_ok() { let url = &dist.webc; return Err( http_error(&response).context(format!("The GET request to \"{url}\" failed")) ); }
let body = response .body .context("The response didn't contain a body")?;
Ok(body.into()) }
pub(crate) async fn download_cached(&self, dist: &DistributionInfo) -> Result<Bytes, Error> { let webc_hash = dist.webc_sha256;
let body = match self.cache.load(&webc_hash) { Some(body) => { tracing::debug!("Cache Hit!"); body } None => { tracing::debug!("Cache Miss"); let bytes = self.download(dist).await?; self.cache.save(webc_hash, bytes.clone()); bytes } };
Ok(body) }}
#[async_trait::async_trait]impl wasmer_wasix::runtime::package_loader::PackageLoader for PackageLoader { #[tracing::instrument( skip_all, fields( pkg.name=summary.pkg.name.as_str(), pkg.version=%summary.pkg.version, pkg.url=summary.dist.webc.as_str(), ), )] async fn load(&self, summary: &PackageSummary) -> Result<Container, Error> { let body = self.download_cached(&summary.dist).await?; let container = Container::from_bytes(body)?;
Ok(container) }
async fn load_package_tree( &self, root: &Container, resolution: &Resolution, ) -> Result<BinaryPackage, Error> { wasmer_wasix::runtime::package_loader::load_package_tree(root, self, resolution).await }}
pub(crate) fn http_error(response: &HttpResponse) -> Error { let status = response.status;
if status == StatusCode::SERVICE_UNAVAILABLE { if let Some(retry_after) = response .headers .get("Retry-After") .and_then(|retry_after| retry_after.to_str().ok()) { tracing::debug!( %retry_after, "Received 503 Service Unavailable while looking up a package. The backend may still be generating the *.webc file.", ); return anyhow::anyhow!("{status} (Retry After: {retry_after})"); } }
Error::msg(status)}
/// A quick'n'dirty cache for downloaded packages.////// This makes no attempt at verifying a cached#[derive(Debug, Default)]struct Cache(Mutex<HashMap<WebcHash, Bytes>>);
impl Cache { fn load(&self, hash: &WebcHash) -> Option<Bytes> { let cache = self.0.lock().ok()?; let bytes = cache.get(hash)?; Some(bytes.clone()) }
fn save(&self, hash: WebcHash, bytes: Bytes) { debug_assert_eq!( hash, WebcHash::sha256(bytes.as_ref()), "Mismatched webc hash" );
if let Ok(mut cache) = self.0.lock() { cache.insert(hash, bytes); } }}
wasm

Version Info

Tagged at
4 months ago