From 30fe599f93beb27528858db11ebfbcf2173ccefc Mon Sep 17 00:00:00 2001 From: chendianbuji Date: Sat, 20 Dec 2025 02:12:46 +0800 Subject: [PATCH 1/5] fix: remove public /sub endpoint and enforce UUID in subscription path --- src/core/handler.ts | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/core/handler.ts b/src/core/handler.ts index ee3ff8e..f77a8a2 100644 --- a/src/core/handler.ts +++ b/src/core/handler.ts @@ -24,17 +24,18 @@ export async function handleRequest( // Handle regular HTTP requests const url = new URL(request.url) - - // Check for subscription requests with /sub path - if (url.pathname === '/sub') { - // Import the subscription page dynamically - const { subscriptionPage } = await import('../pages/index.ts') - return await subscriptionPage(env, request) - } + // Check for subscription requests with UUID in path const uuids = splitAndFilter(env.UUID, ',') for (const uuid of uuids) { + // Check for subscription requests with ${uuid}/sub path + if (url.pathname === `/${uuid}/sub`) { + // Import the subscription page dynamically + const { subscriptionPage } = await import('../pages/index.ts') + return await subscriptionPage(env, request) + } + if (url.pathname.includes(uuid)) { return new Response(generateSubscription(uuid, url), { status: 200, @@ -51,4 +52,4 @@ export async function handleRequest( console.error('Handler error:', err) return await errorPage() } -} \ No newline at end of file +} From 3e81cf1d7c68021b233655d2e63c792ddf31d34d Mon Sep 17 00:00:00 2001 From: chendianbuji Date: Sat, 20 Dec 2025 02:35:45 +0800 Subject: [PATCH 2/5] fix(pages): render specific subscription based on UUID in URL path --- src/pages/index.ts | 118 +++++++++++++++++++++++++-------------------- 1 file changed, 65 insertions(+), 53 deletions(-) diff --git a/src/pages/index.ts b/src/pages/index.ts index eb8f293..bd5e137 100644 --- a/src/pages/index.ts +++ b/src/pages/index.ts @@ -450,52 +450,7 @@ const errorPageText = ` ` -export async function indexPage(): Promise { - return new Response(indexPageText, { - status: 200, - headers: { - 'Content-Type': 'text/html; charset=utf-8', - }, - }) -} - -export async function errorPage(): Promise { - return new Response(errorPageText, { - status: 500, - headers: { - 'Content-Type': 'text/html; charset=utf-8', - }, - }) -} - -// Subscription page with enhanced UI -export async function subscriptionPage(env: any, request: Request): Promise { - const { splitAndFilter } = await import('../utils/array.ts') - const { generateSubscription, generateVlessConfig } = await import('../services/subscription.ts') - - const uuids = splitAndFilter(env.UUID || '', ',') - const url = new URL(request.url) - - // Generate subscription links for each UUID - const subscriptions = uuids.map((uuid: string) => ({ - uuid, - link: generateSubscription(uuid, url), - vlessJson: JSON.stringify(generateVlessConfig(uuid, url), null, 2) - })) - - // Properly escape strings for HTML/JavaScript - const escapeHtml = (str: string) => { - return str.replace(/&/g, '&') - .replace(//g, '>') - .replace(/"/g, '"') - .replace(/'/g, '''); - }; - - // Get the first subscription if it exists - const firstSubscription = subscriptions.length > 0 ? subscriptions[0] : null; - - const subscriptionPageText = ` + const subscriptionPageTextMaker = subscription => ` @@ -945,21 +900,21 @@ export async function subscriptionPage(env: any, request: Request): Promise
- ${firstSubscription ? ` -
+ ${subscription ? ` +

🦊 VLESS Configuration

- ${firstSubscription.uuid.substring(0, 8)}... + ${subscription.uuid.substring(0, 8)}...
-
${escapeHtml(firstSubscription.link)}
+
${escapeHtml(subscription.link)}
💡 On mobile devices, scroll horizontally to view the full configuration
-
@@ -1049,10 +1004,67 @@ export async function subscriptionPage(env: any, request: Request): Promise ` - return new Response(subscriptionPageText, { +// Properly escape strings for HTML/JavaScript +const escapeHtml = (str: string) => { +return str.replace(/&/g, '&') + .replace(//g, '>') + .replace(/"/g, '"') + .replace(/'/g, '''); +}; + +export async function indexPage(): Promise { + return new Response(indexPageText, { status: 200, headers: { 'Content-Type': 'text/html; charset=utf-8', }, }) -} \ No newline at end of file +} + +export async function errorPage(): Promise { + return new Response(errorPageText, { + status: 500, + headers: { + 'Content-Type': 'text/html; charset=utf-8', + }, + }) +} + +// Subscription page with enhanced UI +export async function subscriptionPage(env: any, request: Request): Promise { + const { splitAndFilter } = await import('../utils/array.ts') + const { generateSubscription, generateVlessConfig } = await import('../services/subscription.ts') + + const uuids = splitAndFilter(env.UUID || '', ',') + const url = new URL(request.url) + + // Generate subscription links for each UUID + const subscriptions = uuids.map((uuid: string) => ({ + uuid, + link: generateSubscription(uuid, url), + vlessJson: JSON.stringify(generateVlessConfig(uuid, url), null, 2) + })) + + let targetSubscription = null; + for (const sub of subscriptions) { + if (url.pathname.includes(sub.uuid)) { + targetSubscription = sub; + break; + } + } + + if (targetSubscription) { + const subscriptionPageText = subscriptionPageTextMaker(targetSubscription) + + return new Response(subscriptionPageText, { + status: 200, + headers: { + 'Content-Type': 'text/html; charset=utf-8', + }, + }) + } else { + return errorPage() + } + +} From 4f2521afaa3d44af026f0f64db516a9c168a0f3f Mon Sep 17 00:00:00 2001 From: chendianbuji Date: Sat, 20 Dec 2025 03:04:35 +0800 Subject: [PATCH 3/5] ci(deploy): use GitHub vars to override wrangler.toml for UUID/PROXY_IP --- .github/workflows/deploy.yml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 349ff80..79905bd 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -29,4 +29,10 @@ jobs: uses: cloudflare/wrangler-action@v3 with: apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }} - accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }} \ No newline at end of file + accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }} + secrets: | + UUID + PROXY_IP + env: + UUID: ${{ vars.UUID }} + PROXY_IP: ${{ vars.PROXY_IP }} From 76af40f13f4d152b4c4320e80c82629d48f7f95d Mon Sep 17 00:00:00 2001 From: chendianbuji Date: Sat, 20 Dec 2025 03:34:06 +0800 Subject: [PATCH 4/5] ci(deploy): inject GitHub vars into wrangler.toml for UUID/PROXY_IP --- .github/workflows/deploy.yml | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/.github/workflows/deploy.yml b/.github/workflows/deploy.yml index 79905bd..66fd2d7 100644 --- a/.github/workflows/deploy.yml +++ b/.github/workflows/deploy.yml @@ -25,14 +25,17 @@ jobs: - name: Build project run: npm run build + - name: Inject GitHub Vars into wrangler.toml + env: + GH_UUID: ${{ vars.UUID }} + GH_PROXY_IP: ${{ vars.PROXY_IP }} + run: | + sed -i "s|UUID = \".*\"|UUID = \"$GH_UUID\"|g" wrangler.toml + sed -i "s|PROXY_IP = \".*\"|PROXY_IP = \"$GH_PROXY_IP\"|g" wrangler.toml + - name: Deploy to Cloudflare Workers uses: cloudflare/wrangler-action@v3 with: apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }} accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }} - secrets: | - UUID - PROXY_IP - env: - UUID: ${{ vars.UUID }} - PROXY_IP: ${{ vars.PROXY_IP }} + From 3278d094ff118d2299d74fdd32b4baf9a50be791 Mon Sep 17 00:00:00 2001 From: chendianbuji Date: Sat, 20 Dec 2025 04:11:24 +0800 Subject: [PATCH 5/5] remove duplicate code --- src/core/handler.ts | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/core/handler.ts b/src/core/handler.ts index f77a8a2..7e731f2 100644 --- a/src/core/handler.ts +++ b/src/core/handler.ts @@ -36,14 +36,6 @@ export async function handleRequest( return await subscriptionPage(env, request) } - if (url.pathname.includes(uuid)) { - return new Response(generateSubscription(uuid, url), { - status: 200, - headers: { - 'Content-Type': 'text/plain; charset=utf-8', - }, - }) - } } // Serve main index page