├── .gitattributes ├── .github └── workflows │ └── ci.yml ├── .gitignore ├── .vscode └── settings.json ├── README.md ├── deno.json └── main.ts /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto eol=lf 2 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: ci 2 | 3 | on: [push, pull_request] 4 | 5 | jobs: 6 | build: 7 | name: ${{ matrix.kind }} ${{ matrix.os }} 8 | runs-on: ${{ matrix.os }} 9 | strategy: 10 | matrix: 11 | os: [macOS-latest, ubuntu-latest, windows-latest] 12 | 13 | steps: 14 | - uses: actions/checkout@v3 15 | - name: Setup Deno 16 | uses: denoland/setup-deno@v1 17 | 18 | - name: Format 19 | run: deno fmt --check 20 | 21 | - name: Check 22 | run: deno check --remote main.ts 23 | 24 | - name: Lint 25 | run: deno lint 26 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.swp 2 | *.tmp 3 | *.log 4 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "deno.enable": true, 3 | "deno.lint": true, 4 | "deno.unstable": false 5 | } 6 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Deno Deploy CORS Proxy 2 | 3 | https://cors.deno.dev 4 | 5 | ## Usage 6 | 7 | Before: 8 | 9 | ```js 10 | const response = await fetch("https://xxxx.com/api"); 11 | // Uncaught TypeError: Failed to fetch 12 | // Access to fetch at 'https://xxxx.com/api' from origin 'http://localhost' 13 | // has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is 14 | // present on the requested resource. 15 | // If an opaque response serves your needs, set the request's mode to 'no-cors' 16 | // to fetch the resource with CORS disabled. 17 | ``` 18 | 19 | After: 20 | 21 | ```js 22 | const response = await fetch("https://cors.deno.dev/https://xxxx.com/api"); 23 | const json = await response.json(); 24 | ``` 25 | -------------------------------------------------------------------------------- /deno.json: -------------------------------------------------------------------------------- 1 | { 2 | "tasks": { 3 | "start": "deno run -A --watch main.ts" 4 | } 5 | } 6 | -------------------------------------------------------------------------------- /main.ts: -------------------------------------------------------------------------------- 1 | import { serve } from "https://deno.land/std@0.181.0/http/server.ts"; 2 | import { CSS, render } from "https://deno.land/x/gfm@0.1.22/mod.ts"; 3 | 4 | function addCorsIfNeeded(response: Response) { 5 | const headers = new Headers(response.headers); 6 | 7 | if (!headers.has("access-control-allow-origin")) { 8 | headers.set("access-control-allow-origin", "*"); 9 | } 10 | 11 | return headers; 12 | } 13 | 14 | function isUrl(url: string) { 15 | if (!url.startsWith("http://") && !url.startsWith("https://")) { 16 | return false; 17 | } 18 | 19 | try { 20 | new URL(url); 21 | return true; 22 | } catch { 23 | return false; 24 | } 25 | } 26 | 27 | async function handleRequest(request: Request) { 28 | const { pathname, search } = new URL(request.url); 29 | const url = pathname.substring(1) + search; 30 | 31 | if (isUrl(url)) { 32 | console.log("proxy to %s", url); 33 | const corsHeaders = addCorsIfNeeded(new Response()); 34 | if (request.method.toUpperCase() === "OPTIONS") { 35 | return new Response(null, { headers: corsHeaders }); 36 | } 37 | 38 | const response = await fetch(url, request); 39 | const headers = addCorsIfNeeded(response); 40 | return new Response(response.body, { 41 | status: response.status, 42 | statusText: response.statusText, 43 | headers, 44 | }); 45 | } 46 | 47 | const readme = await Deno.readTextFile("./README.md"); 48 | const body = render(readme); 49 | const html = ` 50 | 51 | 52 | 53 | 54 | CORS Proxy 55 | 68 | 69 | 70 |
71 | ${body} 72 |
73 | 74 | `; 75 | return new Response(html, { 76 | headers: { 77 | "content-type": "text/html;charset=utf-8", 78 | }, 79 | }); 80 | } 81 | 82 | const port = Deno.env.get("PORT") ?? "8000"; 83 | 84 | serve(handleRequest, { port: Number(port) }); 85 | --------------------------------------------------------------------------------