diff --git a/self-hosted-proxies/cloudflare/README.md b/self-hosted-proxies/cloudflare/README.md new file mode 100644 index 0000000..4c07ad3 --- /dev/null +++ b/self-hosted-proxies/cloudflare/README.md @@ -0,0 +1,28 @@ +# Cloudflare worker para cross domain proxy + +Esta é uma alternativa ao [proxy](../../proxy.php) que é utilizada por defeito. Permite a qualquer pessoa com uma conta na https://www.cloudflare.com/ que tenha o seu próprio proxy a correr. A vantagem é uma camada de segurança: Nenhum request feito pela aplicação passa por um servidor alheio, simplesmente por um cloudflare worker montado por ti. Não é necessário nenhum conhecimento de programação para utilizar esta opção. + +## Exemplo + +Há um proxy a correr aqui: + +https://gira-test.fmacedo.com + +pode ser utilizado para testar só, não para uso diário - se tiver demasiados requests terei que o mandar abaixo 😥 + +## Requisitos + +- Ter uma conta na [cloudflare](https://www.cloudflare.com/) + +## Setup + +Basicamente é seguir a primeira parte [deste guia](https://developers.cloudflare.com/workers/get-started/guide/) e copiar o código presente em [proxy.js](./proxy.js), o que equivale a: + +1. Ir a https://dash.cloudflare.com e escolher **Workers & Pages > Create application**. +2. Seleccionar **Create Worker**, editar o nome para algo mais amigável como "gira" e escolher "Deploy" com o exemplo "Hello world" (código este que será editado no passo seguinte); +3. Escolher "Edit code" e copiar o código presente no ficheiro [proxy.js](./proxy.js) deste repositório para o ficheiro "worker.js" aberto no editor do cloudflare. +4. Escolher "Deploy" no canto superior direito do ecrã. No canto superior direito do editor de texto há um link "workers.dev" - este é o URL do proxy, que deves copiar. Deverá ser algo do género `https://gira.username.workers.dev` em que `username` é o teu username. +5. Na applicação mGira, nas definições de utilizador, editar o campo "Proxy definido pelo utilizador" com o URL copiado no passo anterior. + +A partir de agora todos os pedidos à EMEL que antes passavam pelo proxy publico seram feitos através deste. + diff --git a/self-hosted-proxies/cloudflare/proxy.js b/self-hosted-proxies/cloudflare/proxy.js new file mode 100644 index 0000000..2c23639 --- /dev/null +++ b/self-hosted-proxies/cloudflare/proxy.js @@ -0,0 +1,80 @@ +/** + Cloudflare worker to proxy requests to an API server. + the proxy URL is passed in the x-proxy-url header. + the authorization token is passed in the x-authorization header. + + * Learn more at https://developers.cloudflare.com/workers/ + */ + +export default { + async fetch(request) { + const corsHeaders = { + "Access-Control-Allow-Origin": "*", + "Access-Control-Allow-Methods": "GET,HEAD,POST,OPTIONS", + "Access-Control-Max-Age": "86400", + }; + async function handleRequest(request) { + const url = new URL(request.url); + let apiUrl = request.headers.get("x-proxy-url"); + let auth = request.headers.get("x-authorization"); + const origin = new URL(apiUrl).origin; + + // Rewrite request to point to API URL. This also makes the request mutable + // so you can add the correct Origin header to make the API server think + // that this request is not cross-site. + request = new Request(apiUrl, request); + request.headers.set("Authorization", auth); + request.headers.set("Origin", origin); + let response = await fetch(request); + + // Recreate the response so you can modify the headers + response = new Response(response.body, response); + + // Set CORS headers + response.headers.set("Access-Control-Allow-Origin", "*"); + + // Append to/Add Vary header so browser will cache response correctly + response.headers.append("Vary", "Origin"); + + return response; + } + + async function handleOptions(request) { + if ( + request.headers.get("Origin") !== null && + request.headers.get("Access-Control-Request-Method") !== null && + request.headers.get("Access-Control-Request-Headers") !== null + ) { + // Handle CORS preflight requests. + return new Response(null, { + headers: { + ...corsHeaders, + "Access-Control-Allow-Headers": request.headers.get("Access-Control-Request-Headers"), + }, + }); + } else { + // Handle standard OPTIONS request. + return new Response(null, { + headers: { + Allow: "GET, HEAD, POST, OPTIONS", + }, + }); + } + } + + const url = new URL(request.url); + + if (request.method === "OPTIONS") { + // Handle CORS preflight requests + return handleOptions(request); + } else if (request.method === "GET" || request.method === "HEAD" || request.method === "POST") { + // Handle requests to the API server + return handleRequest(request); + } else { + return new Response(null, { + status: 405, + statusText: "Method Not Allowed", + }); + } + }, +};