diff options
| author | Fuwn <[email protected]> | 2026-03-27 05:54:01 +0000 |
|---|---|---|
| committer | Fuwn <[email protected]> | 2026-03-27 05:54:01 +0000 |
| commit | 94213976262eab9b7a68a9d580587a5fbb9248cc (patch) | |
| tree | 92e72ae66d2ebf9bb5393afd5edffb9709c4d10d /apps/proxy | |
| parent | fix(actions): resolve quality and trigger deploy drift (diff) | |
| download | due.moe-94213976262eab9b7a68a9d580587a5fbb9248cc.tar.xz due.moe-94213976262eab9b7a68a9d580587a5fbb9248cc.zip | |
chore(apps): Add proxy
Diffstat (limited to 'apps/proxy')
| -rw-r--r-- | apps/proxy/.editorconfig | 13 | ||||
| -rw-r--r-- | apps/proxy/.gitignore | 172 | ||||
| -rw-r--r-- | apps/proxy/.prettierrc | 6 | ||||
| -rw-r--r-- | apps/proxy/package.json | 13 | ||||
| -rw-r--r-- | apps/proxy/src/index.js | 113 | ||||
| -rw-r--r-- | apps/proxy/wrangler.toml | 51 |
6 files changed, 368 insertions, 0 deletions
diff --git a/apps/proxy/.editorconfig b/apps/proxy/.editorconfig new file mode 100644 index 00000000..64ab2601 --- /dev/null +++ b/apps/proxy/.editorconfig @@ -0,0 +1,13 @@ +# http://editorconfig.org +root = true + +[*] +indent_style = tab +tab_width = 2 +end_of_line = lf +charset = utf-8 +trim_trailing_whitespace = true +insert_final_newline = true + +[*.yml] +indent_style = space diff --git a/apps/proxy/.gitignore b/apps/proxy/.gitignore new file mode 100644 index 00000000..3b0fe33c --- /dev/null +++ b/apps/proxy/.gitignore @@ -0,0 +1,172 @@ +# Logs + +logs +_.log +npm-debug.log_ +yarn-debug.log* +yarn-error.log* +lerna-debug.log* +.pnpm-debug.log* + +# Diagnostic reports (https://nodejs.org/api/report.html) + +report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json + +# Runtime data + +pids +_.pid +_.seed +\*.pid.lock + +# Directory for instrumented libs generated by jscoverage/JSCover + +lib-cov + +# Coverage directory used by tools like istanbul + +coverage +\*.lcov + +# nyc test coverage + +.nyc_output + +# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) + +.grunt + +# Bower dependency directory (https://bower.io/) + +bower_components + +# node-waf configuration + +.lock-wscript + +# Compiled binary addons (https://nodejs.org/api/addons.html) + +build/Release + +# Dependency directories + +node_modules/ +jspm_packages/ + +# Snowpack dependency directory (https://snowpack.dev/) + +web_modules/ + +# TypeScript cache + +\*.tsbuildinfo + +# Optional npm cache directory + +.npm + +# Optional eslint cache + +.eslintcache + +# Optional stylelint cache + +.stylelintcache + +# Microbundle cache + +.rpt2_cache/ +.rts2_cache_cjs/ +.rts2_cache_es/ +.rts2_cache_umd/ + +# Optional REPL history + +.node_repl_history + +# Output of 'npm pack' + +\*.tgz + +# Yarn Integrity file + +.yarn-integrity + +# dotenv environment variable files + +.env +.env.development.local +.env.test.local +.env.production.local +.env.local + +# parcel-bundler cache (https://parceljs.org/) + +.cache +.parcel-cache + +# Next.js build output + +.next +out + +# Nuxt.js build / generate output + +.nuxt +dist + +# Gatsby files + +.cache/ + +# Comment in the public line in if your project uses Gatsby and not Next.js + +# https://nextjs.org/blog/next-9-1#public-directory-support + +# public + +# vuepress build output + +.vuepress/dist + +# vuepress v2.x temp and cache directory + +.temp +.cache + +# Docusaurus cache and generated files + +.docusaurus + +# Serverless directories + +.serverless/ + +# FuseBox cache + +.fusebox/ + +# DynamoDB Local files + +.dynamodb/ + +# TernJS port file + +.tern-port + +# Stores VSCode versions used for testing VSCode extensions + +.vscode-test + +# yarn v2 + +.yarn/cache +.yarn/unplugged +.yarn/build-state.yml +.yarn/install-state.gz +.pnp.\* + +# wrangler project + +.dev.vars +.wrangler/ diff --git a/apps/proxy/.prettierrc b/apps/proxy/.prettierrc new file mode 100644 index 00000000..5c7b5d3c --- /dev/null +++ b/apps/proxy/.prettierrc @@ -0,0 +1,6 @@ +{ + "printWidth": 140, + "singleQuote": true, + "semi": true, + "useTabs": true +} diff --git a/apps/proxy/package.json b/apps/proxy/package.json new file mode 100644 index 00000000..62c13765 --- /dev/null +++ b/apps/proxy/package.json @@ -0,0 +1,13 @@ +{ + "name": "due-proxy", + "version": "0.0.0", + "private": true, + "scripts": { + "deploy": "wrangler deploy", + "dev": "wrangler dev", + "start": "wrangler dev" + }, + "devDependencies": { + "wrangler": "^3.0.0" + } +}
\ No newline at end of file diff --git a/apps/proxy/src/index.js b/apps/proxy/src/index.js new file mode 100644 index 00000000..f2a37111 --- /dev/null +++ b/apps/proxy/src/index.js @@ -0,0 +1,113 @@ +const handleRequest = async (request) => { + try { + const url = new URL(request.url); + let query; + let dropHeaders = false; + + if (url.search.includes('&dh')) { + url.search = url.search.replace('&dh', ''); + dropHeaders = true; + } + + if (url.search.includes('?q=')) { + query = url.search.split('?q=')[1]; + } else if (url.search.includes('?d=')) { + query = atob(url.search.split('?d=')[1]); + } else if (url.search.includes('?d2=')) { + const fullEncodedURL = url.search.split('?d2=')[1]; + const key = parseInt(fullEncodedURL.slice(-2)); + + query = atob(fullEncodedURL.slice(0, -2)) + .split(':') + .map((char) => String.fromCharCode(char - key)) + .join(''); + } else { + return new Response(null, { + status: 400, + statusText: 'Bad Request', + }); + } + + request = new Request(query, request); + + request.headers.set('Host', new URL(query).origin); + request.headers.set('Referrer', new URL(query)); + request.headers.set('Origin', new URL(query)); + request.headers.set('Access-Control-Allow-Credentials', 'true'); + request.headers.delete('X-Content-Type-Options'); + + let response = await fetch(request); + + response = new Response(response.body, response); + + if (dropHeaders) response.headers.forEach((_, key) => response.headers.delete(key)); + + response.headers.set('Access-Control-Allow-Origin', 'https://due.moe'); + response.headers.append('Vary', 'Origin'); + response.headers.set('Cache-Control', 'max-age=300'); + + return response; + } catch { + return new Response(null, { + status: 400, + statusText: 'Bad Request', + }); + } +}; + +const handleOptions = async (request) => { + if ( + request.headers.get('Origin') !== null && + request.headers.get('Access-Control-Request-Method') !== null && + request.headers.get('Access-Control-Request-Headers') !== null + ) { + return new Response(null, { + headers: { + 'Access-Control-Allow-Origin': '*', + 'Access-Control-Allow-Methods': 'GET, HEAD, POST, OPTIONS', + 'Access-Control-Allow-Headers': '*', + }, + }); + } else { + return new Response(null, { + headers: { + Allow: 'GET, HEAD, POST, OPTIONS', + }, + }); + } +}; + +addEventListener('fetch', (event) => { + const request = event.request; + + try { + switch (request.method) { + case 'OPTIONS': + event.respondWith(handleOptions(request)); + + break; + + case 'GET': + case 'HEAD': + case 'POST': + event.respondWith(handleRequest(request)); + + break; + + default: + event.respondWith(async () => { + return new Response(null, { + status: 405, + statusText: 'Method Not Allowed', + }); + }); + + break; + } + } catch { + return new Response(null, { + status: 400, + statusText: 'Bad Request', + }); + } +}); diff --git a/apps/proxy/wrangler.toml b/apps/proxy/wrangler.toml new file mode 100644 index 00000000..f65cc413 --- /dev/null +++ b/apps/proxy/wrangler.toml @@ -0,0 +1,51 @@ +name = "due-proxy" +main = "src/index.js" +compatibility_date = "2023-12-18" + +# Variable bindings. These are arbitrary, plaintext strings (similar to environment variables) +# Note: Use secrets to store sensitive data. +# Docs: https://developers.cloudflare.com/workers/platform/environment-variables +# [vars] +# MY_VARIABLE = "production_value" + +# Bind a KV Namespace. Use KV as persistent storage for small key-value pairs. +# Docs: https://developers.cloudflare.com/workers/runtime-apis/kv +# [[kv_namespaces]] +# binding = "MY_KV_NAMESPACE" +# id = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" + +# Bind an R2 Bucket. Use R2 to store arbitrarily large blobs of data, such as files. +# Docs: https://developers.cloudflare.com/r2/api/workers/workers-api-usage/ +# [[r2_buckets]] +# binding = "MY_BUCKET" +# bucket_name = "my-bucket" + +# Bind a Queue producer. Use this binding to schedule an arbitrary task that may be processed later by a Queue consumer. +# Docs: https://developers.cloudflare.com/queues/get-started +# [[queues.producers]] +# binding = "MY_QUEUE" +# queue = "my-queue" + +# Bind a Queue consumer. Queue Consumers can retrieve tasks scheduled by Producers to act on them. +# Docs: https://developers.cloudflare.com/queues/get-started +# [[queues.consumers]] +# queue = "my-queue" + +# Bind another Worker service. Use this binding to call another Worker without network overhead. +# Docs: https://developers.cloudflare.com/workers/platform/services +# [[services]] +# binding = "MY_SERVICE" +# service = "my-service" + +# Bind a Durable Object. Durable objects are a scale-to-zero compute primitive based on the actor model. +# Durable Objects can live for as long as needed. Use these when you need a long-running "server", such as in realtime apps. +# Docs: https://developers.cloudflare.com/workers/runtime-apis/durable-objects +# [[durable_objects.bindings]] +# name = "MY_DURABLE_OBJECT" +# class_name = "MyDurableObject" + +# Durable Object migrations. +# Docs: https://developers.cloudflare.com/workers/learning/using-durable-objects#configure-durable-object-classes-with-migrations +# [[migrations]] +# tag = "v1" +# new_classes = ["MyDurableObject"] |