Skip to content

Commit 5700cbd

Browse files
[Workers] Adds rust example cors-header-proxy
1 parent 3646c55 commit 5700cbd

File tree

1 file changed

+126
-1
lines changed

1 file changed

+126
-1
lines changed

src/content/docs/workers/examples/cors-header-proxy.mdx

Lines changed: 126 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ languages:
88
- JavaScript
99
- TypeScript
1010
- Python
11+
- Rust
1112
pcx_content_type: example
1213
title: CORS header proxy
1314
sidebar:
@@ -436,4 +437,128 @@ async def on_fetch(request):
436437
return raw_html_response(demo_page)
437438
```
438439

439-
</TabItem> </Tabs>
440+
</TabItem> <TabItem label="Rust" icon="seti:rust">
441+
```rs
442+
use std::{borrow::Cow, collections::HashMap};
443+
use worker::*;
444+
445+
fn raw_html_response(html: &str) -> Result<Response> {
446+
Response::from_html(html)
447+
}
448+
async fn handle_request(req: Request, api_url: &str) -> Result<Response> {
449+
let url = req.url().unwrap();
450+
let mut api_url2 = url
451+
.query_pairs()
452+
.find(|x| x.0 == Cow::Borrowed("apiurl"))
453+
.unwrap()
454+
.1
455+
.to_string();
456+
if api_url2 == String::from("") {
457+
api_url2 = api_url.to_string();
458+
}
459+
let mut request = req.clone_mut()?;
460+
*request.path_mut()? = api_url2.clone();
461+
if let url::Origin::Tuple(origin, _, _) = Url::parse(&api_url2)?.origin() {
462+
(*request.headers_mut()?).set("Origin", &origin)?;
463+
}
464+
let mut response = Fetch::Request(request).send().await?.cloned()?;
465+
let headers = response.headers_mut();
466+
if let url::Origin::Tuple(origin, _, _) = url.origin() {
467+
headers.set("Access-Control-Allow-Origin", &origin)?;
468+
headers.set("Vary", "Origin")?;
469+
}
470+
471+
Ok(response)
472+
}
473+
474+
fn handle_options(req: Request, cors_headers: &HashMap<&str, &str>) -> Result<Response> {
475+
let headers: Vec<_> = req.headers().keys().collect();
476+
if [
477+
"access-control-request-method",
478+
"access-control-request-headers",
479+
"origin",
480+
]
481+
.iter()
482+
.all(|i| headers.contains(&i.to_string()))
483+
{
484+
let mut headers = Headers::new();
485+
for (k, v) in cors_headers.iter() {
486+
headers.set(k, v)?;
487+
}
488+
return Ok(Response::empty()?.with_headers(headers));
489+
}
490+
Response::empty()
491+
}
492+
#[event(fetch)]
493+
async fn fetch(req: Request, _env: Env, _ctx: Context) -> Result<Response> {
494+
let cors_headers = HashMap::from([
495+
("Access-Control-Allow-Origin", "*"),
496+
("Access-Control-Allow-Methods", "GET,HEAD,POST,OPTIONS"),
497+
("Access-Control-Max-Age", "86400"),
498+
]);
499+
let api_url = "https://examples.cloudflareworkers.com/demos/demoapi";
500+
let proxy_endpoint = "/corsproxy/";
501+
let demo_page = format!(
502+
r#"
503+
<!DOCTYPE html>
504+
<html>
505+
<body>
506+
<h1>API GET without CORS Proxy</h1>
507+
<a target="_blank" 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>
508+
<p id="noproxy-status"/>
509+
<code id="noproxy">Waiting</code>
510+
<h1>API GET with CORS Proxy</h1>
511+
<p id="proxy-status"/>
512+
<code id="proxy">Waiting</code>
513+
<h1>API POST with CORS Proxy + Preflight</h1>
514+
<p id="proxypreflight-status"/>
515+
<code id="proxypreflight">Waiting</code>
516+
<script>
517+
let reqs = {{}};
518+
reqs.noproxy = () => {{
519+
return fetch("{api_url}").then(r => r.json())
520+
}}
521+
reqs.proxy = async () => {{
522+
let href = "{proxy_endpoint}?apiurl={api_url}"
523+
return fetch(window.location.origin + href).then(r => r.json())
524+
}}
525+
reqs.proxypreflight = async () => {{
526+
let href = "{proxy_endpoint}?apiurl={api_url}"
527+
let response = await fetch(window.location.origin + href, {{
528+
method: "POST",
529+
headers: {{
530+
"Content-Type": "application/json"
531+
}},
532+
body: JSON.stringify({{
533+
msg: "Hello world!"
534+
}})
535+
}})
536+
return response.json()
537+
}}
538+
(async () => {{
539+
for (const [reqName, req] of Object.entries(reqs)) {{
540+
try {{
541+
let data = await req()
542+
document.getElementById(reqName).innerHTML = JSON.stringify(data)
543+
}} catch (e) {{
544+
document.getElementById(reqName).innerHTML = e
545+
}}
546+
}}
547+
}})()
548+
</script>
549+
</body>
550+
</html>
551+
"#
552+
);
553+
554+
if req.url()?.path().starts_with(proxy_endpoint) {
555+
match req.method() {
556+
Method::Options => return handle_options(req, &cors_headers),
557+
Method::Get | Method::Head | Method::Post => return handle_request(req, api_url).await,
558+
_ => return Response::error("Method Not Allowed", 405),
559+
}
560+
}
561+
raw_html_response(&demo_page)
562+
}
563+
```
564+
</TabItem> </Tabs>

0 commit comments

Comments
 (0)