mirror of
https://github.com/tiennm99/cloudflare-proxy.git
synced 2026-10-11 03:13:14 +00:00
Initial commit
This commit is contained in:
1 parent
ca1cbce01e
commit
73d4e8ed4e
2 files changed
+181
-1
No files matched your search
@@ -1 +1,115 @@
|
|||||||
# cloudflare-proxy
|
# 🌐 cloudflare-proxy
|
||||||
|
|
||||||
|
Inspired by **[tuanpb99/cf-worker-telegram](https://github.com/tuanpb99/cf-worker-telegram)**, this Cloudflare Worker script has been adapted to act as a **transparent proxy for any HTTP or HTTPS URL**, powered by Cloudflare’s global edge network.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 1️⃣ Overview
|
||||||
|
|
||||||
|
Originally designed as a proxy for the Telegram Bot API, this Worker now lets you forward requests to **any HTTP(S) endpoint** while:
|
||||||
|
|
||||||
|
- Maintaining original status codes, headers, and body content
|
||||||
|
- Supporting all HTTP methods (`GET`, `POST`, `PUT`, `DELETE`, `OPTIONS`, etc.)
|
||||||
|
- Enabling **CORS** for browser-based environments
|
||||||
|
- Serving a built-in documentation page at the root path (`/`)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 2️⃣ Features
|
||||||
|
|
||||||
|
- ✅ Proxy to *any* HTTP or HTTPS URL using the `?url=...` query param
|
||||||
|
- ✅ Full support for **CORS**, great for browser usage
|
||||||
|
- ✅ Handles all HTTP methods
|
||||||
|
- ✅ Supports `application/json` and UTF‑8 encoded bodies
|
||||||
|
- ✅ Streams large responses efficiently
|
||||||
|
- ✅ Stateless: no logging or storage
|
||||||
|
- ✅ Lightweight and fast (runs at Cloudflare’s edge)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 3️⃣ Limitations
|
||||||
|
|
||||||
|
- ⚠️ This proxy is **public** by default — it does **not** enforce authentication or domain restrictions
|
||||||
|
- ⚠️ Although `http://` destinations are supported, they are **not secure** and should be avoided for sensitive data
|
||||||
|
- ❌ Does **not** support WebSockets or raw TCP/UDP
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 4️⃣ Built-in Documentation
|
||||||
|
|
||||||
|
Accessing the root path (`https://your-worker.workers.dev/`) returns a user-friendly HTML page that explains how to use the proxy, with example requests and usage notes.
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 5️⃣ Security Recommendations
|
||||||
|
|
||||||
|
If you plan to expose this worker publicly, consider implementing some or all of the following:
|
||||||
|
|
||||||
|
- 🛡 **Allowlist trusted domains**
|
||||||
|
- 🔐 **Require an access token** via query param or header
|
||||||
|
- 🚫 **Rate-limit** or filter based on IP/User-Agent
|
||||||
|
- 🔎 **Audit usage logs** via external reverse proxy or edge analytics
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 6️⃣ Installation
|
||||||
|
|
||||||
|
1. **Download the Script**
|
||||||
|
Get [`worker.js`](./worker.js) from this repo (or modify as needed)
|
||||||
|
|
||||||
|
2. **Create a Cloudflare Worker**
|
||||||
|
You can follow this guide to create one with a custom domain:
|
||||||
|
👉 https://dev.to/andyjessop/setting-up-a-new-cloudflare-worker-with-a-custom-domain-fl9
|
||||||
|
|
||||||
|
3. **Deploy the Worker**
|
||||||
|
- Go to [Cloudflare dashboard](https://dash.cloudflare.com/)
|
||||||
|
- Navigate to **Workers & Pages**
|
||||||
|
- Create a new Worker
|
||||||
|
- Paste in your code (from `worker.js`)
|
||||||
|
- Click **Deploy**
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 7️⃣ Usage
|
||||||
|
|
||||||
|
Send HTTP requests to your Worker with a query parameter like `?url=https://example.com/...`.
|
||||||
|
|
||||||
|
### 🔗 Original Request
|
||||||
|
|
||||||
|
https://example.com/api/data?query=param
|
||||||
|
|
||||||
|
### 💡 Example Code (JavaScript)
|
||||||
|
|
||||||
|
```js
|
||||||
|
fetch('https://<YOUR_WORKER_URL>/?url=https://example.com/api/data?query=param', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'application/json',
|
||||||
|
'Authorization': 'Bearer YOUR_ACCESS_TOKEN',
|
||||||
|
'X-Custom-Header': 'CustomValue'
|
||||||
|
},
|
||||||
|
body: JSON.stringify({
|
||||||
|
name: 'John Doe',
|
||||||
|
age: 30,
|
||||||
|
message: 'Hello from Cloudflare Worker proxy!'
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.then(response => response.json())
|
||||||
|
.then(data => console.log('Response:', data))
|
||||||
|
.catch(err => console.error('Error:', err));
|
||||||
|
```
|
||||||
|
|
||||||
|
### ✅ Supported HTTP Methods
|
||||||
|
- GET
|
||||||
|
- POST
|
||||||
|
- PUT
|
||||||
|
- DELETE
|
||||||
|
- OPTIONS
|
||||||
|
- HEAD
|
||||||
|
|
||||||
|
The Worker automatically forwards request headers and body (for non-GET/HEAD requests), and includes permissive CORS headers in the response.
|
||||||
|
|
||||||
|
ℹ️ This method supports any website that allows being accessed through a proxy. It is especially useful for client-side apps restricted by CORS.
|
||||||
|
|
||||||
|
### 📄 License
|
||||||
|
Based on an open-source MIT-licensed project from tuanpb99/cf-worker-telegram. This fork or adaptation retains the MIT License.
|
||||||
@@ -0,0 +1,66 @@
|
|||||||
|
async function handleRequest(request) {
|
||||||
|
const url = new URL(request.url);
|
||||||
|
const target = url.searchParams.get("url");
|
||||||
|
|
||||||
|
if (!target) {
|
||||||
|
return new Response("Missing `url` parameter", { status: 400 });
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
const method = request.method;
|
||||||
|
const headers = new Headers(request.headers);
|
||||||
|
|
||||||
|
// Nếu là JSON mà thiếu charset thì thêm vào để tránh lỗi emoji
|
||||||
|
const contentType = headers.get("Content-Type");
|
||||||
|
if (contentType && contentType.startsWith("application/json") && !contentType.includes("charset")) {
|
||||||
|
headers.set("Content-Type", "application/json; charset=UTF-8");
|
||||||
|
}
|
||||||
|
|
||||||
|
const init = {
|
||||||
|
method,
|
||||||
|
headers,
|
||||||
|
redirect: "follow",
|
||||||
|
};
|
||||||
|
|
||||||
|
if (method !== "GET" && method !== "HEAD") {
|
||||||
|
init.body = request.body;
|
||||||
|
}
|
||||||
|
|
||||||
|
const proxyReq = new Request(target, init);
|
||||||
|
const proxiedRes = await fetch(proxyReq);
|
||||||
|
|
||||||
|
const res = new Response(proxiedRes.body, proxiedRes); // Stream lại y chang
|
||||||
|
const reqAllowHeaders = request.headers.get('Access-Control-Request-Headers');
|
||||||
|
const allowHeaders = reqAllowHeaders ? reqAllowHeaders : 'Content-Type';
|
||||||
|
|
||||||
|
res.headers.set("Access-Control-Allow-Origin", "*");
|
||||||
|
res.headers.set("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS, HEAD");
|
||||||
|
res.headers.set("Access-Control-Allow-Headers", allowHeaders);
|
||||||
|
|
||||||
|
return res;
|
||||||
|
} catch (err) {
|
||||||
|
return new Response(`Proxy error: ${err.message}`, { status: 500 });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleOptions(request) {
|
||||||
|
const reqAllowHeaders = request.headers.get("Access-Control-Request-Headers");
|
||||||
|
const allowHeaders = reqAllowHeaders ? reqAllowHeaders : "Content-Type";
|
||||||
|
|
||||||
|
const headers = {
|
||||||
|
"Access-Control-Allow-Origin": "*",
|
||||||
|
"Access-Control-Allow-Methods": "GET, POST, PUT, DELETE, OPTIONS, HEAD",
|
||||||
|
"Access-Control-Allow-Headers": allowHeaders,
|
||||||
|
"Access-Control-Max-Age": "86400",
|
||||||
|
};
|
||||||
|
|
||||||
|
return new Response(null, { status: 204, headers });
|
||||||
|
}
|
||||||
|
|
||||||
|
addEventListener("fetch", event => {
|
||||||
|
if (event.request.method === "OPTIONS") {
|
||||||
|
event.respondWith(handleOptions(event.request));
|
||||||
|
} else {
|
||||||
|
event.respondWith(handleRequest(event.request));
|
||||||
|
}
|
||||||
|
});
|
||||||
Reference in new issue
Block a user