aboutsummaryrefslogtreecommitdiff
path: root/apps
diff options
context:
space:
mode:
authorFuwn <[email protected]>2026-03-27 05:54:01 +0000
committerFuwn <[email protected]>2026-03-27 05:54:01 +0000
commit94213976262eab9b7a68a9d580587a5fbb9248cc (patch)
tree92e72ae66d2ebf9bb5393afd5edffb9709c4d10d /apps
parentfix(actions): resolve quality and trigger deploy drift (diff)
downloaddue.moe-94213976262eab9b7a68a9d580587a5fbb9248cc.tar.xz
due.moe-94213976262eab9b7a68a9d580587a5fbb9248cc.zip
chore(apps): Add proxy
Diffstat (limited to 'apps')
-rw-r--r--apps/proxy/.editorconfig13
-rw-r--r--apps/proxy/.gitignore172
-rw-r--r--apps/proxy/.prettierrc6
-rw-r--r--apps/proxy/package.json13
-rw-r--r--apps/proxy/src/index.js113
-rw-r--r--apps/proxy/wrangler.toml51
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"]