IWBH_01

yet another CORS proxy (cloudflare)

Apr 27th, 2021 (edited)
384
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. addEventListener('fetch', function(event) {
  2.   const { request } = event;
  3.   const response = handleRequest(request).catch(handleError);
  4.   event.respondWith(response);
  5. })
  6.  
  7. /**
  8.  * Receives a HTTP request and replies with a response.
  9.  * @param {Request} request
  10.  * @returns {Promise<Response>}
  11.  */
  12.  
  13. var iptbl={};
  14.  
  15. async function handleRequest(request) {
  16.   const { method, url } = request;
  17.   var hedr=request.headers;
  18.   const { host, pathname } = new URL(url);
  19.  
  20.   switch (pathname) {
  21.     case '/time':
  22.       return respondTime(request);
  23.     case '/echo':
  24.       return respondEcho(request);
  25.     case '/favicon.ico':
  26.     case '/robots.txt':
  27.       return new Response(null, { status: 204 });
  28.   }
  29.  
  30.   // Workers on these hostnames have no origin server,
  31.   // therefore there is nothing else to be found
  32.   //?
  33.   /*
  34.   if (host.endsWith('.workers.dev')
  35.       || host.endsWith('.cloudflareworkers.com')) {
  36.     return new Response('Not Found', { status: 404 })
  37.   }
  38.   */
  39.  
  40.   //ip request limtis 2 requests every 3 seconds
  41.   var rmip=request.headers.get("CF-Connecting-IP"),
  42.   lcrt_=rmip in iptbl?iptbl[rmip].pop():(iptbl[rmip]=[1])[0],cst_=(new Date()).getTime();
  43.   iptbl[rmip].unshift(cst_);
  44.   if(cst_-lcrt_<3000) return new Response("Error, exeeds the 2-requests-per-3-seconds limit.",
  45.      { status: 503,  headers:{"Access-Control-Allow-Origin":"*"}});
  46.      
  47.  
  48.   if(pathname.startsWith("/proxy/")){
  49.     //begin cors proxy code
  50.     var prespon,mrespon,chd;
  51.  
  52.     if(request.method=="OPTIONS"){ //ug options
  53.      if(chd=request.headers.get("access-control-request-headers"))chd=", "+chd;
  54.      prespon=["You will run out of options.",
  55.      { status: 200, headers:{"Access-Control-Allow-Headers":"Authorization, Content-Type"+chd} }
  56.      ];
  57.  
  58.     }else if(pathname.length<15){
  59.       return new Response(`Error no target url.
  60.       Please put the url you want to access through
  61.        this proxy immediately following /proxy/ in this server url.
  62.        example: https://${host}/proxy/https://www.example.com `
  63.       ,{status:400});
  64.     }else if(!request.headers.has("X-Requested-With")){
  65.       return new Response(`Error the X-Requested-With header must be set in the
  66.       request headers`
  67.       ,{status:400});
  68.     }else if(pathname.indexOf(host)+1){
  69.       return new Response(`Error, proxy requesting the proxy server is not allowed.`
  70.       ,{status:400});
  71.     }else{
  72.     var rinit={
  73.       headers:new Headers(),
  74.       method:request.method
  75.     };
  76.     var val,reqh=request.headers,rinh=rinit.headers,
  77.     xnope=["x-nope","host"];
  78.     if(reqh.has("X-Nope"))xnope=xnope.concat(reqh.get("X-Nope").split(","));
  79.     for(let h in reqh.keys()){
  80.       val=reqh.get(h);
  81.       if(h.startsWith("x-a-")) rinh.set(h.substr(4),val);
  82.       else if(!(rinh.has(h)||xnope.indexOf(h.toLowerCase())+1)) rinh.set(h,val);
  83.     }
  84.  
  85.     if(request.bodyUsed) rinit.body=request.body;
  86.  
  87.     //actually do the proxy:
  88.     mrespon=await fetch(url.substr(url.indexOf("/proxy/")+7), rinit);
  89.     prespon=[mrespon.body,{status:mrespon.status,headers:Object.fromEntries([...mrespon.headers])}];
  90.     }
  91.     prespon[1].headers["Access-Control-Allow-Origin"]="*";
  92.     prespon[1].headers["Access-Control-Allow-Methods"]="GET, POST, PUT, PATCH, DELETE, UPLOAD";
  93.     return new Response(prespon[0],prespon[1]);
  94.     //return new Response(JSON.stringify( prespon ),{status:200});
  95.     //end cors proxy code
  96.   }
  97.  
  98.   return new Response(`corsh: CORS Hack.
  99.  
  100.   A cors proxy that lets you set forbidden headers.
  101.   useage https://${host}/proxy/https://www.example.com
  102.  
  103.   requests must set the "x-requested-with" header
  104.  
  105.   prefix forbidden headers with x-a-
  106.   example: x-a-orgin: https://www.example.com
  107.  
  108.   also use the header x-nope, to omit request headers
  109.    from the request.
  110.    example: "x-nope: CF-Connecting-IP,Cookie"
  111.   `,
  112.   { status: 200 });
  113. }
  114.  
  115. /**
  116.  * Responds with an uncaught error.
  117.  * @param {Error} error
  118.  * @returns {Response}
  119.  */
  120. function handleError(error) {
  121.   console.error('Uncaught error:', error);
  122.  
  123.   const { stack } = error;
  124.   return new Response(stack || error, {
  125.     status: 500,
  126.     headers: {
  127.       'Content-Type': 'text/plain;charset=UTF-8'
  128.     }
  129.   });
  130. }
  131.  
  132.  
  133. /**
  134.  * Responds with an echo of a request.
  135.  * @param {Request} request
  136.  * @returns {Promise<Response>}
  137.  */
  138. async function respondEcho(request) {
  139.   const { url, method, cf } = request;
  140.   const headers = Object.fromEntries([...request.headers]);
  141.   const body = await request.text();
  142.  
  143.   const echo = { method, url, body, headers, cf };
  144.   const echoBody = JSON.stringify(echo, null, 2);
  145.  
  146.   return new Response(echoBody, {
  147.     status: 200,
  148.     headers: {
  149.       'Content-Type': 'application/json;charset=UTF-8',
  150.       'Cache-Control': 'no-store',
  151.     }
  152.   });
  153. }
  154.  
  155. /**
  156.  * Gets a human-readable description of the local time.
  157.  * @param {string} locale
  158.  * @param {object} cf
  159.  * @returns {string}
  160.  */
  161. function getTime(locale, cf) {
  162.   // In the preview editor, the 'cf' object will be null.
  163.   // To view the object and its variables: make sure you are logged in,
  164.   // click the "Save and Deploy" button, then open the URL in a new tab.
  165.   const { city, region, country, timezone: timeZone } = cf || {};
  166.   const localTime = new Date().toLocaleTimeString(locale, { timeZone });
  167.   const location = [city, region, country].filter(Boolean).join(', ');
  168.  
  169.   return timeZone
  170.     ? 'The local time in ' + location + ' is ' + localTime
  171.     : 'The UTC time is ' + localTime;
  172. }
  173.  
  174. /**
  175.  * Responds with the local time.
  176.  * @param {Request} request
  177.  * @returns {Response}
  178.  */
  179. function respondTime(request) {
  180.   const { headers, cf } = request;
  181.   const locale = (headers.get('Accept-Language') || 'en-US').split(',')[0];
  182.  
  183.   const body = getTime(locale, cf);
  184.   return new Response(body, {
  185.     status: 200,
  186.     headers: {
  187.       'Content-Type': 'text/plain;charset=UTF-8',
  188.       'Content-Language': locale
  189.     }
  190.   });
  191. }
Add Comment
Please, Sign In to add comment