Repository: electron
Issue: [Bug]: interceptors do not respect some headers, e.g. Set-Cookie
Labels: bug :beetle:,platform/all,status/confirmed,has-repro-gist,25-x-y,26-x-y

### Preflight Checklist

- [X] I have read the [Contributing Guidelines](https://github.com/electron/electron/blob/main/CONTRIBUTING.md) for this project.
- [X] I agree to follow the [Code of Conduct](https://github.com/electron/electron/blob/main/CODE_OF_CONDUCT.md) that this project adheres to.
- [X] I have searched the [issue tracker](https://www.github.com/electron/electron/issues) for a bug report that matches the one I want to file, without success.

### Electron Version

25.5.0
32.2.0

### What operating system are you using?

macOS

### Operating System Version

macOS Ventura 13.2.1

### What arch are you using?

arm64 (including Apple Silicon)

### Last Known Working Electron version

0.30.0 (probably before https://github.com/electron/electron/commit/96d53d279ec79bcd86e53b7f1aeb840ca32774c5)

### Expected Behavior

```ts
  if (!protocol.isProtocolHandled("https")) {
    protocol.handle("https", async (req) => {
      return fetch(req)  // not `net.fetch`. Detailed explanations in testcase gist
    });
  }
```

This should respect `Set-Cookie` headers sent by the server, and also send the `Cookie` header to the server.

### Actual Behavior

`Set-Cookie` is not respected, and `Cookie` header disappears. You can see `Set-Cookie` present in server response via logging at the main process, but when `return`-ed to the protocol handler and delivered to the renderer process, cookies would just disappear.

### Testcase Gist URL

https://gist.github.com/XieJiSS/470b405869692f85972ee14f11d28133

### Additional Information

This bug dates back to electron v2.0.0:

1. https://github.com/electron/electron/issues/34243
2. https://github.com/electron/electron/issues/32167
3. https://github.com/electron/electron/issues/30717
4. https://github.com/electron/electron/issues/29473
5. https://github.com/electron/electron/issues/23865
6. https://github.com/electron/electron/issues/13228

And I highly suspect that it might be introduced as early as v0.31.0: https://github.com/electron/electron/commit/96d53d279ec79bcd86e53b7f1aeb840ca32774c5

---

From 2018 to 2023, so many people have created issues regarding this...

Anyway, for people encountering the same problem, a possible workaround is to implement a cookie layer inside the intercept handler:

```ts
const cookieParser = require("set-cookie-parser")

// interceptor

const url = new URL(req.url);
const cookies = await session.defaultSession.cookies.get({
  url: req.url,
  domain: url.hostname,
  path: url.pathname,
  // `secure: true` Cookies should not be sent via http
  secure: url.protocol === "http:" ? false : undefined,
  // theoretically not possible to implement sameSite because we don't know the url
  // of the website that is requesting the resource
});

req.headers.set("Cookie", cookies.map((cookie) => `${cookie.name}=${encodeURI(cookie.value)}`).join("; "));

const resp = await fetch(req);
const { headers } = resp;

if (headers.has("Set-Cookie")) {
  // undici hack that only works for newer versions of Node.js
  const sym = Object.getOwnPropertySymbols(resp.headers).find(s => s.description === "headers list")
  const setCookies = cookieParser(resp.headers[sym].cookies)

  await Promise.all(
    setCookies.map((cookie) =>
      session.defaultSession.cookies.set({
        url: req.url,
        name: cookie.name,
        value: cookie.value,
        path: cookie.path,
        domain: cookie.domain,
        secure: cookie.secure,
        httpOnly: cookie.httpOnly,
        expirationDate: cookie.expires
          ? cookie.expires.getTime() / 1000
          : cookie.maxAge
            ? Date.now() / 1000 + cookie.maxAge
            : undefined,
      })
    )
  );
}

return resp;
```

But this workaround will harm security and might make your app vulnerable to some well-crafted CSRF attacks. Use it at your own risk