├── functions ├── blacklist.txt ├── download.js ├── watch.js ├── proxy.js └── index.js ├── .github └── ISSUE_TEMPLATE │ ├── feature_request.md │ └── bug_report.md ├── LICENSE ├── installation-pages.md └── README.md /functions/blacklist.txt: -------------------------------------------------------------------------------- 1 | example.com 2 | another-example.com 3 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots** 24 | If applicable, add screenshots to help explain your problem. 25 | 26 | **Desktop (please complete the following information):** 27 | - OS: [e.g. iOS] 28 | - Browser [e.g. chrome, safari] 29 | - Version [e.g. 22] 30 | 31 | **Smartphone (please complete the following information):** 32 | - Device: [e.g. iPhone6] 33 | - OS: [e.g. iOS8.1] 34 | - Browser [e.g. stock browser, safari] 35 | - Version [e.g. 22] 36 | 37 | **Additional context** 38 | Add any other context about the problem here. 39 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 MinitorMHS 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /installation-pages.md: -------------------------------------------------------------------------------- 1 | # Installation for Cloudflare Pages 2 | 3 | ## Prerequisites 4 | 5 | - A GitHub account 6 | - A Cloudflare account 7 | 8 | ## Steps 9 | 10 | 1. **Fork the Repository**: 11 | - Go to the [CF_Web_Proxy repository](https://github.com/MinitorMHS/CF_Web_Proxy) on GitHub. 12 | - Click the "Fork" button in the top-right corner to create a copy of the repository in your GitHub account. 13 | 14 | 2. **Create a Cloudflare Account**: 15 | - If you don't already have a Cloudflare account, sign up at [Cloudflare](https://www.cloudflare.com/). 16 | 17 | 3. **Create a New Pages Project**: 18 | - Log in to your Cloudflare account. 19 | - Navigate to the **Workers & Pages** section. 20 | - Click on **Pages** and then **Create a project**. 21 | - Select **Connect to GitHub** and authorize Cloudflare to access your GitHub account. 22 | 23 | 4. **Link the Repository**: 24 | - Choose the forked repository from your GitHub account. 25 | - Click on **Begin setup**. 26 | 27 | 5. **Configure and Deploy**: 28 | - Follow the prompts to configure your Pages project. 29 | - Click on **Save and Deploy** to deploy your project. 30 | 31 | Your Cloudflare web proxy should now be set up and running! 32 | -------------------------------------------------------------------------------- /functions/download.js: -------------------------------------------------------------------------------- 1 | export async function onRequest(context) { 2 | const { request } = context; 3 | const url = new URL(request.url); 4 | const searchParams = url.searchParams; 5 | 6 | const encodedData = searchParams.get('data'); 7 | if (!encodedData) { 8 | return new Response('Data parameter is missing', { status: 400 }); 9 | } 10 | 11 | try { 12 | const { url: decodedUrl, filename } = JSON.parse(atob(encodedData)); 13 | const response = await fetch(decodedUrl, { 14 | headers: request.headers, 15 | }); 16 | 17 | if (!response.ok) { 18 | throw new Error(`HTTP error! status: ${response.status}`); 19 | } 20 | 21 | const contentLength = response.headers.get('Content-Length'); 22 | const newHeaders = new Headers(response.headers); 23 | newHeaders.set('Content-Disposition', `attachment; filename="${filename}"`); 24 | newHeaders.set('Accept-Ranges', 'bytes'); 25 | 26 | if (contentLength) { 27 | newHeaders.set('Content-Length', contentLength); 28 | } 29 | 30 | const range = request.headers.get('Range'); 31 | if (range) { 32 | const parts = range.replace(/bytes=/, "").split("-"); 33 | const start = parseInt(parts[0], 10); 34 | const end = parts[1] ? parseInt(parts[1], 10) : contentLength - 1; 35 | const chunksize = (end - start) + 1; 36 | 37 | newHeaders.set('Content-Range', `bytes ${start}-${end}/${contentLength}`); 38 | newHeaders.set('Content-Length', chunksize.toString()); 39 | 40 | return new Response(response.body, { 41 | status: 206, 42 | headers: newHeaders, 43 | }); 44 | } else { 45 | return new Response(response.body, { 46 | status: 200, 47 | headers: newHeaders, 48 | }); 49 | } 50 | } catch (error) { 51 | return new Response(`Error: ${error.message}`, { status: 400 }); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /functions/watch.js: -------------------------------------------------------------------------------- 1 | export async function onRequest(context) { 2 | const { request } = context; 3 | const url = new URL(request.url); 4 | const searchParams = url.searchParams; 5 | const encodedData = searchParams.get('data'); 6 | 7 | if (!encodedData) { 8 | return new Response('Data parameter is missing', { status: 400 }); 9 | } 10 | 11 | try { 12 | const { url: decodedUrl } = JSON.parse(atob(encodedData)); 13 | const response = await fetch(decodedUrl, { headers: request.headers }); 14 | 15 | if (!response.ok) { 16 | throw new Error(`HTTP error! status: ${response.status}`); 17 | } 18 | 19 | const newHeaders = new Headers(response.headers); 20 | const contentType = newHeaders.get('Content-Type'); 21 | 22 | if (response.headers.get('Set-Cookie')) { 23 | newHeaders.append('Set-Cookie', response.headers.get('Set-Cookie')); 24 | } 25 | 26 | if (contentType && contentType.includes('text/html')) { 27 | const originalText = await response.text(); 28 | const proxiedText = originalText 29 | .replace(/(href|src|action)="([^"]*)"/g, (match, p1, p2) => { 30 | if (p2.startsWith('http') || p2.startsWith('//')) { 31 | return `${p1}="/proxy/${encodeURIComponent(btoa(p2))}"`; 32 | } else { 33 | const newUrl = new URL(p2, decodedUrl).href; 34 | return `${p1}="/watch?data=${encodeURIComponent(btoa(JSON.stringify({ url: newUrl })))}"`; 35 | } 36 | }) 37 | .replace(/]*>([\s\S]*?)<\/script>/gi, (match, p1) => { 38 | return ``; 39 | }); 40 | 41 | return new Response(proxiedText, { 42 | status: 200, 43 | headers: newHeaders, 44 | }); 45 | } else { 46 | return new Response(response.body, { 47 | status: response.status, 48 | headers: newHeaders, 49 | }); 50 | } 51 | } catch (error) { 52 | return new Response(`Error: ${error.message}`, { status: 400 }); 53 | } 54 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CF_Web_Proxy 2 | 3 | ## Overview 4 | 5 | CF_Web_Proxy is a web proxy solution built on Cloudflare network. This project allows users to download and watch content through a proxy, ensuring privacy and security. The functionalities are separated for better performance and user experience. 6 | 7 | ## Note for Iranian Users 8 | 9 | Iranian users, please use this URL to access the service with half bandwidth (Nim baha): [edge05.66065.ir.cdn.ir](http://edge05.66065.ir.cdn.ir) 10 | 11 | ## Features 12 | 13 | - **Download Functionality**: Securely download content through the proxy with the ability to pause downloads. 14 | - **Watch Functionality**: Stream content directly through the proxy. 15 | - **URL Encoding**: Automatically encodes URLs to base64 for secure and efficient processing. 16 | - **Responsive Design**: Optimized for various devices and screen sizes. 17 | - **Blacklist functionality**: You can add various websites to the blastlist.txt to block those domains to be proxied. 18 | 19 | ## Installation 20 | 21 | For detailed installation instructions, please refer to the following files: 22 | - [Installation for Cloudflare Pages (recommend)](installation-pages.md) 23 | 24 | - [Installation for Cloudflare Workers](installation-worker.md) 25 | 26 | ## Usage 27 | 28 | - **Download Content**: Click the "Download" button to securely download content through the proxy. You can pause and resume downloads as needed. 29 | - **Watch Content**: Click the "Watch" button to stream content. Note: Ensure you have a stable internet connection for the best experience. **Only MP4 videos are streamable**. 30 | 31 | ## Contributing 32 | 33 | We welcome contributions! Please follow these steps to contribute: 34 | 35 | 1. Fork the repository. 36 | 2. Create a new branch (`git checkout -b feature-branch`). 37 | 3. Make your changes and commit them (`git commit -m 'Add new feature'`). 38 | 4. Push to the branch (`git push origin feature-branch`). 39 | 5. Open a Pull Request. 40 | 41 | ## License 42 | 43 | This project is licensed under the MIT License. See the [LICENSE](LICENSE) file for details. 44 | 45 | ## Acknowledgements 46 | 47 | - Thanks to the Cloudflare team for their robust platform. 48 | - Special thanks to [geek-spot](https://github.com/geek-spot) for their invaluable help with this code. 49 | 50 | ## Contact 51 | 52 | For any questions or feedback, please open an issue or contact the repository owner. 53 | -------------------------------------------------------------------------------- /functions/proxy.js: -------------------------------------------------------------------------------- 1 | export async function onRequest(context) { 2 | const { request } = context; 3 | const url = new URL(request.url); 4 | const searchParams = url.searchParams; 5 | 6 | let originalUrl = searchParams.get('url'); 7 | if (!originalUrl) { 8 | return new Response('URL parameter is missing', { status: 400 }); 9 | } 10 | 11 | if (!/^https?:\/\//i.test(originalUrl)) { 12 | originalUrl = 'http://' + originalUrl; 13 | } 14 | 15 | // Fetch the blacklist from a remote text file 16 | let blockedDomains = []; 17 | try { 18 | const response = await fetch('https://raw.githubusercontent.com/MinitorMHS/CF_Web_Proxy/main/Functions/blacklist.txt'); 19 | if (response.ok) { 20 | const blacklistContent = await response.text(); 21 | blockedDomains = blacklistContent.split('\n').filter(domain => domain.trim() !== ''); 22 | } else { 23 | console.error('Error fetching blacklist:', response.statusText); 24 | } 25 | } catch (error) { 26 | console.error('Error fetching blacklist:', error); 27 | } 28 | 29 | const requestedDomain = new URL(originalUrl).hostname; 30 | if (blockedDomains.includes(requestedDomain)) { 31 | return new Response('This domain is not allowed', { status: 403 }); 32 | } 33 | 34 | const filename = originalUrl.split('/').pop(); 35 | const encodedData = btoa(JSON.stringify({ url: originalUrl, filename: filename })); 36 | 37 | // Proxying URLs based on the hostname 38 | let proxiedUrl; 39 | let watchUrl; 40 | if (url.hostname === 'proxy.minitor.eu.org') { 41 | proxiedUrl = `https://cfproxy.global.ssl.fastly.net/download?data=${encodedData}`; 42 | watchUrl = `https://cfproxy.global.ssl.fastly.net/watch?data=${encodedData}`; 43 | } else { 44 | proxiedUrl = `${url.origin}/download?data=${encodedData}`; 45 | watchUrl = `${url.origin}/watch?data=${encodedData}`; 46 | } 47 | 48 | return new Response(` 49 | 50 | 51 | 64 | 65 | 66 |
67 |

Watch

68 | 69 | Watch 70 |
71 |
72 |

Download

73 | 74 | Download 75 |
76 |

Filename: ${filename}

77 | 78 | 79 | `, { headers: { 'Content-Type': 'text/html' } }); 80 | } -------------------------------------------------------------------------------- /functions/index.js: -------------------------------------------------------------------------------- 1 | export async function onRequest(context) { 2 | return new Response(` 3 | 4 | 5 | 6 | Web Proxy 7 | 8 | 9 | 10 | 11 | 12 | 175 | 176 | 177 |
178 |

About

179 |

This website helps you encode and secure your download links

180 |
181 |
182 | 183 | GitHub Icon 184 | 185 | 188 |
189 |
190 | 191 | 192 |
193 |
194 | Gmail Icon Email Me for  DMCA 195 | Telegram Icon Contact me on Telegram 196 |
197 | 200 | 201 | 202 | `, { headers: { 'Content-Type': 'text/html' } }); 203 | } 204 | --------------------------------------------------------------------------------