// <reference types="@fastly/js-compute" />
addEventListener("fetch", event => event.respondWith(app(event)));

// define your backend here
// outside of fiddle, it might look like:
// const backend = "https://http-me.glitch.me/"
const backend = "origin_0";

// Logic flow:
//
// - Clone the request twice for different validation tests.
// - Make three separate requests and compare responses.
//   1. Normal request
//   2. Modified request to validate missing `Cookie` header.
//   3. Modified request to validate explicit CORS `Origin` header.
// - Return an error for any unexpected differences.
async function app(event) {
  
  try {
    const req = event.request;
    const anonymousRequest = req.clone();
    const anonymousRequestDifferentOrigin = req.clone();

    // Fetch request from backend with any incoming cookies
    let cookieResponse = await fetch(req, {
      backend: backend,
    });

    // Usable even if there's no cookie
    let cookieBuffer = await cookieResponse.arrayBuffer();

    // Fetch again with the cookies removed
    if (anonymousRequest.headers.has("cookie")) {
      anonymousRequest.headers.delete("cookie");
      let backendResponse = await fetch(anonymousRequest, {
        backend: backend,
        cacheOverride: new CacheOverride("pass"),
      });

      // Compare responses and report which URLs require the cookie header 
      let responseBuffer = await backendResponse.arrayBuffer();
      if (cookieResponse.status != backendResponse.status || !buffersAreEqual(cookieBuffer, responseBuffer)) {
        console.log("URL requires cookie: " + req.url);
      } else {
        console.log("URL appears not to require a cookie: " + req.url);
      }
    } else {
      console.log("Incoming request did not include a cookie: " + req.url);
    }

    // Fetch again with an origin header differing from the backend
    if (!anonymousRequestDifferentOrigin.headers.has("Origin")) {
      anonymousRequestDifferentOrigin.headers.set("Origin", "fastly.com");
      let backendResponse = await fetch(anonymousRequestDifferentOrigin, {
        backend: backend,
        cacheOverride: new CacheOverride("pass"),
      });

      // Compare responses and report which URLs require the same origin
      let responseBuffer = await backendResponse.arrayBuffer();
      if (cookieResponse.status != backendResponse.status || !buffersAreEqual(cookieBuffer, responseBuffer)) {
        console.log("URL requires same origin: " + req.url);
      } else {
        console.log("URL appears not to require same origin: " + req.url);
      }
    } else {
      console.log("Incoming request is already cross-origin: " + req.url);
    }

    // Send the response back to the client by implementing a readable stream
    return new Response(cookieBuffer, {
      headers: cookieResponse.headers,
      status: cookieResponse.status,
    });
  } 
  catch (e) {
    console.error(e);
    return new Response("Error when processing " + req.url + ":" + String(e), {status: 500});
  }
}

function buffersAreEqual(a, b) {
  const aArray = new Uint8Array(a);
  const bArray = new Uint8Array(b);
  if (aArray.length != bArray.length) {
    return false;
  }
  for (let i = 0; i < aArray.length; i++) {
    if (aArray[i] !== bArray[i]) {
      return false;
    }
  }
  return true;
}