If you want to get started quickly, click on the button below.
This creates a repository in your GitHub account and deploys the application to Cloudflare Workers.
exportdefault{asyncfetch(request){constcorsHeaders={"Access-Control-Allow-Origin":"*","Access-Control-Allow-Methods":"GET,HEAD,POST,OPTIONS","Access-Control-Max-Age":"86400",};// The URL for the remote third party API you want to fetch from// but does not implement CORSconstAPI_URL="https://examples.cloudflareworkers.com/demos/demoapi";// The endpoint you want the CORS reverse proxy to be onconstPROXY_ENDPOINT="/corsproxy/";// The rest of this snippet for the demo pagefunctionrawHtmlResponse(html){returnnewResponse(html,{headers:{"content-type":"text/html;charset=UTF-8",},});}constDEMO_PAGE=`<!DOCTYPE html><html><body><h1>API GET without CORS Proxy</h1><a href="https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch#Checking_that_the_fetch_was_successful">Shows TypeError: Failed to fetch since CORS is misconfigured</a><p/><code>Waiting</code><h1>API GET with CORS Proxy</h1><p/><code>Waiting</code><h1>API POST with CORS Proxy + Preflight</h1><p/><code>Waiting</code><script>let reqs = {};reqs.noproxy = () => {return fetch("${API_URL}").then(r => r.json())}reqs.proxy = async () => {let href = "${PROXY_ENDPOINT}?apiurl=${API_URL}"return fetch(window.location.origin + href).then(r => r.json())}reqs.proxypreflight = async () => {let href = "${PROXY_ENDPOINT}?apiurl=${API_URL}"let response = await fetch(window.location.origin + href, {method: "POST",headers: {"Content-Type": "application/json"},body: JSON.stringify({msg: "Hello world!"})})return response.json()}(async () => {for (const [reqName, req] of Object.entries(reqs)) {try {let data = await req()document.getElementById(reqName).innerHTML = JSON.stringify(data)} catch (e) {document.getElementById(reqName).innerHTML = e}}})()</script></body></html>`;asyncfunctionhandleRequest(request){consturl=newURL(request.url);letapiUrl=url.searchParams.get("apiurl");if (apiUrl==null){apiUrl=API_URL;}// 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=newRequest(apiUrl,request);request.headers.set("Origin",newURL(apiUrl).origin);letresponse=awaitfetch(request);// Recreate the response so you can modify the headersresponse=newResponse(response.body,response);// Set CORS headersresponse.headers.set("Access-Control-Allow-Origin",url.origin);// Append to/Add Vary header so browser will cache response correctlyresponse.headers.append("Vary","Origin");returnresponse;}asyncfunctionhandleOptions(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.returnnewResponse(null,{headers:{...corsHeaders,"Access-Control-Allow-Headers":request.headers.get("Access-Control-Request-Headers",),},});}else{// Handle standard OPTIONS request.returnnewResponse(null,{headers:{Allow:"GET, HEAD, POST, OPTIONS",},});}}consturl=newURL(request.url);if (url.pathname.startsWith(PROXY_ENDPOINT)){if (request.method==="OPTIONS"){// Handle CORS preflight requestsreturnhandleOptions(request);}elseif (request.method==="GET"||request.method==="HEAD"||request.method==="POST"){// Handle requests to the API serverreturnhandleRequest(request);}else{returnnewResponse(null,{status:405,statusText:"Method Not Allowed",});}}else{returnrawHtmlResponse(DEMO_PAGE);}},};exportdefault{asyncfetch(request):Promise<Response>{constcorsHeaders={"Access-Control-Allow-Origin":"*","Access-Control-Allow-Methods":"GET,HEAD,POST,OPTIONS","Access-Control-Max-Age":"86400",};// The URL for the remote third party API you want to fetch from// but does not implement CORSconstAPI_URL="https://examples.cloudflareworkers.com/demos/demoapi";// The endpoint you want the CORS reverse proxy to be onconstPROXY_ENDPOINT="/corsproxy/";// The rest of this snippet for the demo pagefunctionrawHtmlResponse(html){returnnewResponse(html,{headers:{"content-type":"text/html;charset=UTF-8",},});}constDEMO_PAGE=`<!DOCTYPE html><html><body><h1>API GET without CORS Proxy</h1><a href="https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch#Checking_that_the_fetch_was_successful">Shows TypeError: Failed to fetch since CORS is misconfigured</a><p/><code>Waiting</code><h1>API GET with CORS Proxy</h1><p/><code>Waiting</code><h1>API POST with CORS Proxy + Preflight</h1><p/><code>Waiting</code><script>let reqs = {};reqs.noproxy = () => {return fetch("${API_URL}").then(r => r.json())}reqs.proxy = async () => {let href = "${PROXY_ENDPOINT}?apiurl=${API_URL}"return fetch(window.location.origin + href).then(r => r.json())}reqs.proxypreflight = async () => {let href = "${PROXY_ENDPOINT}?apiurl=${API_URL}"let response = await fetch(window.location.origin + href, {method: "POST",headers: {"Content-Type": "application/json"},body: JSON.stringify({msg: "Hello world!"})})return response.json()}(async () => {for (const [reqName, req] of Object.entries(reqs)) {try {let data = await req()document.getElementById(reqName).textContent = JSON.stringify(data)} catch (e) {document.getElementById(reqName).textContent = e}}})()</script></body></html>`;asyncfunctionhandleRequest(request){consturl=newURL(request.url);letapiUrl=url.searchParams.get("apiurl");if (apiUrl==null){apiUrl=API_URL;}// 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=newRequest(apiUrl,request);request.headers.set("Origin",newURL(apiUrl).origin);letresponse=awaitfetch(request);// Recreate the response so you can modify the headersresponse=newResponse(response.body,response);// Set CORS headersresponse.headers.set("Access-Control-Allow-Origin",url.origin);// Append to/Add Vary header so browser will cache response correctlyresponse.headers.append("Vary","Origin");returnresponse;}asyncfunctionhandleOptions(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.returnnewResponse(null,{headers:{...corsHeaders,"Access-Control-Allow-Headers":request.headers.get("Access-Control-Request-Headers",),},});}else{// Handle standard OPTIONS request.returnnewResponse(null,{headers:{Allow:"GET, HEAD, POST, OPTIONS",},});}}consturl=newURL(request.url);if (url.pathname.startsWith(PROXY_ENDPOINT)){if (request.method==="OPTIONS"){// Handle CORS preflight requestsreturnhandleOptions(request);}elseif (request.method==="GET"||request.method==="HEAD"||request.method==="POST"){// Handle requests to the API serverreturnhandleRequest(request);}else{returnnewResponse(null,{status:405,statusText:"Method Not Allowed",});}}else{returnrawHtmlResponse(DEMO_PAGE);}},}satisfiesExportedHandler;import{Hono} from"hono";import{cors} from"hono/cors";// The URL for the remote third party API you want to fetch from// but does not implement CORSconstAPI_URL="https://examples.cloudflareworkers.com/demos/demoapi";// The endpoint you want the CORS reverse proxy to be onconstPROXY_ENDPOINT="/corsproxy/";constapp=newHono();// Demo page handlerapp.get("*",async(c)=>{// Only handle non-proxy requests with this handlerif (c.req.path.startsWith(PROXY_ENDPOINT)){returnnext();}// Create the demo page HTMLconstDEMO_PAGE=`<!DOCTYPE html><html><body><h1>API GET without CORS Proxy</h1><a href="https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch#Checking_that_the_fetch_was_successful">Shows TypeError: Failed to fetch since CORS is misconfigured</a><p/><code>Waiting</code><h1>API GET with CORS Proxy</h1><p/><code>Waiting</code><h1>API POST with CORS Proxy + Preflight</h1><p/><code>Waiting</code><script>let reqs = {};reqs.noproxy = () => {return fetch("${API_URL}").then(r => r.json())}reqs.proxy = async () => {let href = "${PROXY_ENDPOINT}?apiurl=${API_URL}"return fetch(window.location.origin + href).then(r => r.json())}reqs.proxypreflight = async () => {let href = "${PROXY_ENDPOINT}?apiurl=${API_URL}"let response = await fetch(window.location.origin + href, {method: "POST",headers: {"Content-Type": "application/json"},body: JSON.stringify({msg: "Hello world!"})})return response.json()}(async () => {for (const [reqName, req] of Object.entries(reqs)) {try {let data = await req()document.getElementById(reqName).innerHTML = JSON.stringify(data)} catch (e) {document.getElementById(reqName).innerHTML = e}}})()</script></body></html>`;returnc.html(DEMO_PAGE);});// CORS proxy routesapp.on(["GET","HEAD","POST","OPTIONS"],PROXY_ENDPOINT+"*",async(c)=>{consturl=newURL(c.req.url);// Handle OPTIONS preflight requestsif (c.req.method==="OPTIONS"){constorigin=c.req.header("Origin");constrequestMethod=c.req.header("Access-Control-Request-Method");constrequestHeaders=c.req.header("Access-Control-Request-Headers");if (origin&&requestMethod&&requestHeaders){// Handle CORS preflight requestsreturnnewResponse(null,{headers:{"Access-Control-Allow-Origin":"*","Access-Control-Allow-Methods":"GET,HEAD,POST,OPTIONS","Access-Control-Max-Age":"86400","Access-Control-Allow-Headers":requestHeaders,},});}else{// Handle standard OPTIONS requestreturnnewResponse(null,{headers:{Allow:"GET, HEAD, POST, OPTIONS",},});}}// Handle actual requestsletapiUrl=url.searchParams.get("apiurl")||API_URL;// Rewrite request to point to API URLconstmodifiedRequest=newRequest(apiUrl,c.req.raw);modifiedRequest.headers.set("Origin",newURL(apiUrl).origin);letresponse=awaitfetch(modifiedRequest);// Recreate the response so we can modify the headersresponse=newResponse(response.body,response);// Set CORS headersresponse.headers.set("Access-Control-Allow-Origin",url.origin);// Append to/Add Vary header so browser will cache response correctlyresponse.headers.append("Vary","Origin");returnresponse;});// Handle method not allowed for proxy endpointapp.all(PROXY_ENDPOINT+"*",(c)=>{returnnewResponse(null,{status:405,statusText:"Method Not Allowed",});});exportdefaultapp;from workersimport WorkerEntrypointfrom pyodide.ffiimport to_jsas _to_jsfrom jsimport Response, URL, fetch, Object, Requestdefto_js(x):return_to_js(x,dict_converter=Object.fromEntries)classDefault(WorkerEntrypoint):asyncdeffetch(self,request):cors_headers={"Access-Control-Allow-Origin":"*","Access-Control-Allow-Methods":"GET,HEAD,POST,OPTIONS","Access-Control-Max-Age":"86400",}api_url="https://examples.cloudflareworkers.com/demos/demoapi"proxy_endpoint="/corsproxy/"defraw_html_response(html):return Response.new(html,headers=to_js({"content-type":"text/html;charset=UTF-8"}))demo_page=f'''<!DOCTYPE html><html><body><h1>API GET without CORS Proxy</h1><a href="https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch#Checking_that_the_fetch_was_successful">Shows TypeError: Failed to fetch since CORS is misconfigured</a><p/><code>Waiting</code><h1>API GET with CORS Proxy</h1><p/><code>Waiting</code><h1>API POST with CORS Proxy + Preflight</h1><p/><code>Waiting</code><script>let reqs ={{}};reqs.noproxy = () =>{{return fetch("{api_url}").then(r => r.json())}}reqs.proxy = async () =>{{let href = "{proxy_endpoint}?apiurl={api_url}"return fetch(window.location.origin + href).then(r => r.json())}}reqs.proxypreflight = async () =>{{let href = "{proxy_endpoint}?apiurl={api_url}"let response = await fetch(window.location.origin + href,{{method: "POST",headers:{{"Content-Type": "application/json"}},body: JSON.stringify({{msg: "Hello world!"}})}})return response.json()}}(async () =>{{for (const [reqName, req] of Object.entries(reqs)){{try{{let data = await req()document.getElementById(reqName).innerHTML = JSON.stringify(data)}} catch (e){{document.getElementById(reqName).innerHTML = e}}}}}})()</script></body></html>'''asyncdefhandle_request(request):url= URL.new(request.url)api_url2= url.searchParams["apiurl"]ifnot api_url2:api_url2= api_urlrequest= Request.new(api_url2, request)request.headers["Origin"]=(URL.new(api_url2)).originprint(request.headers)response=awaitfetch(request)response= Response.new(response.body, response)response.headers["Access-Control-Allow-Origin"]= url.originresponse.headers["Vary"]="Origin"return responseasyncdefhandle_options(request):if"Origin"in request.headersand"Access-Control-Request-Method"in request.headersand"Access-Control-Request-Headers"in request.headers:return Response.new(None,headers=to_js({**cors_headers,"Access-Control-Allow-Headers": request.headers["Access-Control-Request-Headers"]}))return Response.new(None,headers=to_js({"Allow":"GET, HEAD, POST, OPTIONS"}))url= URL.new(request.url)if url.pathname.startswith(proxy_endpoint):if request.method=="OPTIONS":returnhandle_options(request)if request.methodin("GET","HEAD","POST"):returnhandle_request(request)return Response.new(None,status=405,statusText="Method Not Allowed")returnraw_html_response(demo_page)usestd::{borrow::Cow,collections::HashMap};useworker::*;fnraw_html_response(html:&str)->Result<Response>{Response::from_html(html)}asyncfnhandle_request(req:Request,api_url:&str)->Result<Response>{leturl=req.url().unwrap();letmutapi_url2=url.query_pairs().find(|x|x.0==Cow::Borrowed("apiurl")).unwrap().1.to_string();ifapi_url2==String::from(""){api_url2=api_url.to_string();}letmutrequest=req.clone_mut()?;*request.path_mut()?=api_url2.clone();ifleturl::Origin::Tuple(origin,_,_)=Url::parse(&api_url2)?.origin(){(*request.headers_mut()?).set("Origin",&origin)?;}letmutresponse=Fetch::Request(request).send().await?.cloned()?;letheaders=response.headers_mut();ifleturl::Origin::Tuple(origin,_,_)=url.origin(){headers.set("Access-Control-Allow-Origin",&origin)?;headers.set("Vary","Origin")?;}Ok(response)}fnhandle_options(req:Request,cors_headers:&HashMap<&str,&str>)->Result<Response>{letheaders:Vec<_>=req.headers().keys().collect();if["access-control-request-method","access-control-request-headers","origin",].iter().all(|i|headers.contains(&i.to_string())){letmutheaders=Headers::new();for(k,v)incors_headers.iter(){headers.set(k,v)?;}returnOk(Response::empty()?.with_headers(headers));}Response::empty()}#[event(fetch)]asyncfnfetch(req:Request,_env:Env,_ctx:Context)->Result<Response>{letcors_headers=HashMap::from([("Access-Control-Allow-Origin","*"),("Access-Control-Allow-Methods","GET,HEAD,POST,OPTIONS"),("Access-Control-Max-Age","86400"),]);letapi_url="https://examples.cloudflareworkers.com/demos/demoapi";letproxy_endpoint="/corsproxy/";letdemo_page=format!(r#"<!DOCTYPE html><html><body><h1>API GET without CORS Proxy</h1><a href="https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch#Checking_that_the_fetch_was_successful">Shows TypeError: Failed to fetch since CORS is misconfigured</a><p/><code>Waiting</code><h1>API GET with CORS Proxy</h1><p/><code>Waiting</code><h1>API POST with CORS Proxy + Preflight</h1><p/><code>Waiting</code><script>let reqs = {{}};reqs.noproxy = () => {{return fetch("{api_url}").then(r => r.json())}}reqs.proxy = async () => {{let href = "{proxy_endpoint}?apiurl={api_url}"return fetch(window.location.origin + href).then(r => r.json())}}reqs.proxypreflight = async () => {{let href = "{proxy_endpoint}?apiurl={api_url}"let response = await fetch(window.location.origin + href, {{method: "POST",headers: {{"Content-Type": "application/json"}},body: JSON.stringify({{msg: "Hello world!"}})}})return response.json()}}(async () => {{for (const [reqName, req] of Object.entries(reqs)) {{try {{let data = await req()document.getElementById(reqName).innerHTML = JSON.stringify(data)}} catch (e) {{document.getElementById(reqName).innerHTML = e}}}}}})()</script></body></html>"#);ifreq.url()?.path().starts_with(proxy_endpoint){matchreq.method(){Method::Options=>returnhandle_options(req,&cors_headers),Method::Get|Method::Head|Method::Post=>returnhandle_request(req,api_url).await,_=>returnResponse::error("Method Not Allowed",405),}}raw_html_response(&demo_page)}