mirror of
https://github.com/zhom/donutbrowser.git
synced 2026-08-09 04:36:15 +02:00
chore: linting
This commit is contained in:
+45
-14
@@ -121,6 +121,46 @@ function extractArchive(archive, destinationDir, windowsTarget) {
|
||||
};
|
||||
}
|
||||
|
||||
/// Attempts for the archive download. A release asset fetch is a network call
|
||||
/// on every CI job, and a single transport error ("fetch failed") has taken
|
||||
/// whole builds down. Retrying is safe because the checksum below is verified
|
||||
/// on every attempt, so a truncated or substituted archive still cannot pass.
|
||||
const DOWNLOAD_ATTEMPTS = 3;
|
||||
|
||||
async function downloadVerifiedArchive(url, archive, expectedSha256) {
|
||||
let lastError;
|
||||
|
||||
for (let attempt = 1; attempt <= DOWNLOAD_ATTEMPTS; attempt += 1) {
|
||||
try {
|
||||
const response = await fetch(url);
|
||||
if (!response.ok) {
|
||||
throw new Error(
|
||||
`Failed to download Xray-core (${response.status} ${response.statusText})`,
|
||||
);
|
||||
}
|
||||
writeFileSync(archive, Buffer.from(await response.arrayBuffer()));
|
||||
|
||||
const actual = sha256(archive);
|
||||
if (actual !== expectedSha256) {
|
||||
throw new Error(
|
||||
`Xray-core checksum mismatch: expected ${expectedSha256}, got ${actual}`,
|
||||
);
|
||||
}
|
||||
return;
|
||||
} catch (error) {
|
||||
lastError = error;
|
||||
if (attempt < DOWNLOAD_ATTEMPTS) {
|
||||
console.warn(
|
||||
`Xray-core download attempt ${attempt} failed (${error.message}); retrying`,
|
||||
);
|
||||
await new Promise((resolve) => setTimeout(resolve, attempt * 2000));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
throw lastError;
|
||||
}
|
||||
|
||||
export async function downloadXray(target = requestedTarget()) {
|
||||
const asset = XRAY_ASSETS[target];
|
||||
if (!asset) {
|
||||
@@ -157,20 +197,11 @@ export async function downloadXray(target = requestedTarget()) {
|
||||
const scratch = mkdtempSync(join(tmpdir(), "donut-xray-"));
|
||||
try {
|
||||
const archive = join(scratch, basename(asset.name));
|
||||
const response = await fetch(xrayDownloadUrl(asset.name));
|
||||
if (!response.ok) {
|
||||
throw new Error(
|
||||
`Failed to download Xray-core (${response.status} ${response.statusText})`,
|
||||
);
|
||||
}
|
||||
writeFileSync(archive, Buffer.from(await response.arrayBuffer()));
|
||||
|
||||
const actual = sha256(archive);
|
||||
if (actual !== asset.sha256) {
|
||||
throw new Error(
|
||||
`Xray-core checksum mismatch: expected ${asset.sha256}, got ${actual}`,
|
||||
);
|
||||
}
|
||||
await downloadVerifiedArchive(
|
||||
xrayDownloadUrl(asset.name),
|
||||
archive,
|
||||
asset.sha256,
|
||||
);
|
||||
|
||||
const extracted = extractArchive(archive, scratch, windowsTarget);
|
||||
if (!existsSync(extracted.binary) || !existsSync(extracted.license)) {
|
||||
|
||||
@@ -627,6 +627,37 @@ async fn cleanup_runtime() {
|
||||
test_harness::stop_vpn_servers().await;
|
||||
}
|
||||
|
||||
/// Request through the proxy until the tunnel behind it actually carries the
|
||||
/// traffic, or the deadline passes.
|
||||
///
|
||||
/// Returns the last response either way, so a genuine failure still asserts
|
||||
/// against the real body rather than a timeout message.
|
||||
async fn wait_for_tunnel(
|
||||
local_port: u16,
|
||||
url: &str,
|
||||
host_header: &str,
|
||||
timeout: Duration,
|
||||
) -> Result<String, Box<dyn std::error::Error + Send + Sync>> {
|
||||
let deadline = tokio::time::Instant::now() + timeout;
|
||||
|
||||
loop {
|
||||
let last = match raw_http_request_via_proxy(local_port, url, host_header).await {
|
||||
Ok(response) => {
|
||||
if response.contains("WG-TUNNEL-OK") {
|
||||
return Ok(response);
|
||||
}
|
||||
response
|
||||
}
|
||||
Err(e) => format!("request error: {e}"),
|
||||
};
|
||||
|
||||
if tokio::time::Instant::now() >= deadline {
|
||||
return Ok(last);
|
||||
}
|
||||
sleep(Duration::from_millis(250)).await;
|
||||
}
|
||||
}
|
||||
|
||||
async fn wait_for_file(
|
||||
path: &std::path::Path,
|
||||
timeout: Duration,
|
||||
@@ -661,12 +692,22 @@ async fn run_proxy_feature_suite(
|
||||
let proxy =
|
||||
start_proxy_with_upstream(binary_path, &vpn_upstream, &[], None, Some(&profile_id)).await?;
|
||||
|
||||
sleep(Duration::from_millis(500)).await;
|
||||
|
||||
let internal_url = format!("http://{}:8080/", server_tunnel_ip);
|
||||
let internal_host = format!("{}:8080", server_tunnel_ip);
|
||||
let http_response =
|
||||
raw_http_request_via_proxy(proxy.local_port, &internal_url, &internal_host).await?;
|
||||
|
||||
// The proxy answers as soon as it is listening, but the route behind it is
|
||||
// not ready until the WireGuard handshake completes and the in-tunnel server
|
||||
// accepts. A fixed sleep raced that on a loaded runner and came back
|
||||
// `502 Bad Gateway`, which is the tunnel not being up yet rather than
|
||||
// anything under test being wrong. Poll to a deadline instead, the same way
|
||||
// `wait_for_file` does below.
|
||||
let http_response = wait_for_tunnel(
|
||||
proxy.local_port,
|
||||
&internal_url,
|
||||
&internal_host,
|
||||
Duration::from_secs(20),
|
||||
)
|
||||
.await?;
|
||||
assert!(
|
||||
http_response.contains("WG-TUNNEL-OK"),
|
||||
"HTTP traffic through donut-proxy+VPN tunnel should succeed, got: {}",
|
||||
|
||||
Reference in New Issue
Block a user