@@ -8,6 +8,7 @@ languages:
88 - JavaScript
99 - TypeScript
1010 - Python
11+ - Rust
1112pcx_content_type : example
1213title : CORS header proxy
1314sidebar :
@@ -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