|
1 | 1 | import { type NextRequest, NextResponse } from "next/server"; |
| 2 | +import { getGitHubReleases } from "@/utils/releases"; |
2 | 3 |
|
3 | 4 | export const runtime = "edge"; |
4 | 5 |
|
| 6 | +type FallbackPlatform = "macos-arm64" | "macos-x64" | "windows"; |
| 7 | + |
| 8 | +async function checkCrabNebulaDownload( |
| 9 | + url: string, |
| 10 | +): Promise<{ ok: true; finalUrl: string } | { ok: false }> { |
| 11 | + try { |
| 12 | + const res = await fetch(url, { |
| 13 | + redirect: "follow", |
| 14 | + cache: "no-store", |
| 15 | + headers: { |
| 16 | + Range: "bytes=0-0", |
| 17 | + }, |
| 18 | + }); |
| 19 | + |
| 20 | + if (res.status >= 200 && res.status < 300) { |
| 21 | + return { ok: true, finalUrl: res.url }; |
| 22 | + } |
| 23 | + } catch {} |
| 24 | + |
| 25 | + return { ok: false }; |
| 26 | +} |
| 27 | + |
| 28 | +async function getGitHubFallbackDownloadUrl( |
| 29 | + platform: FallbackPlatform, |
| 30 | +): Promise<string | null> { |
| 31 | + try { |
| 32 | + const releases = await getGitHubReleases(); |
| 33 | + |
| 34 | + for (const release of releases) { |
| 35 | + const url = |
| 36 | + platform === "windows" |
| 37 | + ? release.downloads.windows |
| 38 | + : platform === "macos-arm64" |
| 39 | + ? release.downloads["macos-arm64"] |
| 40 | + : release.downloads["macos-x64"]; |
| 41 | + |
| 42 | + if (url) return url; |
| 43 | + } |
| 44 | + } catch {} |
| 45 | + |
| 46 | + return null; |
| 47 | +} |
| 48 | + |
5 | 49 | export async function GET( |
6 | 50 | request: NextRequest, |
7 | 51 | props: { params: Promise<{ platform: string }> }, |
8 | 52 | ) { |
9 | 53 | const params = await props.params; |
10 | 54 | const platform = params.platform.toLowerCase(); |
11 | 55 |
|
12 | | - // Define download URLs for different platforms |
13 | | - const downloadUrls: Record<string, string> = { |
14 | | - "apple-intel": |
15 | | - "https://cdn.crabnebula.app/download/cap/cap/latest/platform/dmg-x86_64", |
16 | | - intel: |
17 | | - "https://cdn.crabnebula.app/download/cap/cap/latest/platform/dmg-x86_64", // Keep for backward compatibility |
18 | | - mac: "https://cdn.crabnebula.app/download/cap/cap/latest/platform/dmg-aarch64", // Default to Apple Silicon |
19 | | - macos: |
20 | | - "https://cdn.crabnebula.app/download/cap/cap/latest/platform/dmg-aarch64", // Default to Apple Silicon |
21 | | - "apple-silicon": |
22 | | - "https://cdn.crabnebula.app/download/cap/cap/latest/platform/dmg-aarch64", |
23 | | - aarch64: |
24 | | - "https://cdn.crabnebula.app/download/cap/cap/latest/platform/dmg-aarch64", |
25 | | - x86_64: |
26 | | - "https://cdn.crabnebula.app/download/cap/cap/latest/platform/dmg-x86_64", |
27 | | - windows: |
28 | | - "https://cdn.crabnebula.app/download/cap/cap/latest/platform/nsis-x86_64", |
29 | | - win: "https://cdn.crabnebula.app/download/cap/cap/latest/platform/nsis-x86_64", |
| 56 | + const downloadUrls: Record< |
| 57 | + string, |
| 58 | + { url: string; fallback: FallbackPlatform } |
| 59 | + > = { |
| 60 | + "apple-intel": { |
| 61 | + url: "https://cdn.crabnebula.app/download/cap/cap/latest/platform/dmg-x86_64", |
| 62 | + fallback: "macos-x64", |
| 63 | + }, |
| 64 | + intel: { |
| 65 | + url: "https://cdn.crabnebula.app/download/cap/cap/latest/platform/dmg-x86_64", |
| 66 | + fallback: "macos-x64", |
| 67 | + }, |
| 68 | + mac: { |
| 69 | + url: "https://cdn.crabnebula.app/download/cap/cap/latest/platform/dmg-aarch64", |
| 70 | + fallback: "macos-arm64", |
| 71 | + }, |
| 72 | + macos: { |
| 73 | + url: "https://cdn.crabnebula.app/download/cap/cap/latest/platform/dmg-aarch64", |
| 74 | + fallback: "macos-arm64", |
| 75 | + }, |
| 76 | + "apple-silicon": { |
| 77 | + url: "https://cdn.crabnebula.app/download/cap/cap/latest/platform/dmg-aarch64", |
| 78 | + fallback: "macos-arm64", |
| 79 | + }, |
| 80 | + aarch64: { |
| 81 | + url: "https://cdn.crabnebula.app/download/cap/cap/latest/platform/dmg-aarch64", |
| 82 | + fallback: "macos-arm64", |
| 83 | + }, |
| 84 | + x86_64: { |
| 85 | + url: "https://cdn.crabnebula.app/download/cap/cap/latest/platform/dmg-x86_64", |
| 86 | + fallback: "macos-x64", |
| 87 | + }, |
| 88 | + windows: { |
| 89 | + url: "https://cdn.crabnebula.app/download/cap/cap/latest/platform/nsis-x86_64", |
| 90 | + fallback: "windows", |
| 91 | + }, |
| 92 | + win: { |
| 93 | + url: "https://cdn.crabnebula.app/download/cap/cap/latest/platform/nsis-x86_64", |
| 94 | + fallback: "windows", |
| 95 | + }, |
30 | 96 | }; |
31 | 97 |
|
32 | | - // Get the download URL for the requested platform |
33 | | - const downloadUrl = downloadUrls[platform]; |
| 98 | + const download = downloadUrls[platform]; |
34 | 99 |
|
35 | 100 | // If the platform is not supported, redirect to the main download page |
36 | | - if (!downloadUrl) { |
| 101 | + if (!download) { |
37 | 102 | return NextResponse.redirect(new URL("/download", request.url)); |
38 | 103 | } |
39 | 104 |
|
40 | | - // Redirect to the appropriate download URL |
41 | | - return NextResponse.redirect(downloadUrl); |
| 105 | + const primary = await checkCrabNebulaDownload(download.url); |
| 106 | + if (primary.ok) { |
| 107 | + return NextResponse.redirect(primary.finalUrl); |
| 108 | + } |
| 109 | + |
| 110 | + const fallback = await getGitHubFallbackDownloadUrl(download.fallback); |
| 111 | + if (fallback) { |
| 112 | + return NextResponse.redirect(fallback); |
| 113 | + } |
| 114 | + |
| 115 | + return NextResponse.redirect(new URL("/download/versions", request.url)); |
42 | 116 | } |
0 commit comments