set-cookieのドメイン属性をlocalhostに書き換えてブラウザにcookieを保存するテスト環境の作成


## やりたいこと

サーバー側からのHttpレスポンスヘッダーに付与されているset-cookieヘッダーのドメイン属性をlocalhostに変換してブラウザ上にcookieを保存する！！

## 利用するライブラリとかツールとか

- [node.js](https://nodejs.org/ja/)
- [express](https://expressjs.com/)
- [http-proxy-middleware](https://github.com/chimurai/http-proxy-middleware)
- [cors](https://github.com/expressjs/cors)
- [ngrok](https://ngrok.com/)
- [Google Chrome](https://www.google.com/intl/ja_jp/chrome/)


## 全体像イメージ

ブラウザからサーバーに対しての問い合わせ
client(chrome)→proxy(localhsot:8000)→ngrok(中身的にはlocalhost:6000)

お問い合わせに対する返信に、proxyがset-cookieヘッダーのドメインをlocalhostに書き換える。




## ディレクトリ

ディレクトリ構成は以下の通り。

```
tree -I node_modules
.
├── package-lock.json
├── package.json
├── proxy.js
├── public
│   └── index.html
└── server.js
```

## client

ブラウザで開くページ。画面リロードで、proxyの `http://localhost:8000/api` にリクエストする。

```html:public/index.html
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>クライアント</title>
  </head>
  <body>
    <script>
      fetch("http://localhost:8000/api", {
        credentials: "include",
      })
        .then((response) => response.json())
        .then((data) => console.log(data));
    </script>
  </body>
</html>
```

## proxy

クライアントの`index.html`をホスティングしながら、サーバーからくるHttpのレスポンスのset-cookieのドメイン属性を、localhostに書き換えしてる。書き換えは、　`http-proxy-middleware` を利用している。`createProxyMiddleware()`の引数で渡す`options()`内で、set-cookieのドメイン属性をどうするか指定している。
クライアントからは、`http://localhost:8000/api`にきたHttpリクエストをngrokのhttpsにプロキシしてる。

```javascript:proxy.js
const path = require("path");
const express = require("express");
const { createProxyMiddleware } = require("http-proxy-middleware");

const app = express();

const options = function (target) {
  return {
    target,
    changeOrigin: true,
    cookieDomainRewrite: "localhost",
    onError: function onError(err, req, res) {
      console.error(err);
    },
  };
};

// ここのoptionsの引数に後述するngrokのコマンドで出力されたhttps~~~を記入してください
const proxy = createProxyMiddleware(
  options("https://84ea-124-195-153-220.ngrok.io")
);
app.use(["/api"], proxy);
app.use(
  "/client-view",
  express.static(path.join(__dirname, "public/index.html"))
);

const PORT = 8000;
app.listen(PORT, () => {
  console.log(`\app listening at http://localhost:${PORT}\n`);
});
```

## server.js

`/api`にきたリクエストに対して、set-cookieヘッダーを付与するレスポンスを返してる。

```javascript:server.js
const express = require("express");
const cors = require("cors");
const app = express();

app.use(cors({ origin: true, credentials: true }));

app.get("/api", (req, res) => {
  res.cookie("cookie-name", "cookie-value", {
    path: "/",
    maxAge: 60000,
    secure: true,
    HttpOnly: true,
  });

  res.json({});
});

app.listen(6000, () => console.log("Example app listening on port 6000!"));
```


## :rocket: 起動方法

クライアント側の起動と、プロキシの起動。

```shell
node proxy.js
```

サーバー側の起動。

```shell
node server.js
```

serverが6000番portで立ち上がるのでngrokでlocalhostをhttpsに変換。

```shell
ngrok http 6000
```

## テスト

`http://localhost:8000/client-view` にアクセス！

DevToolsを開いてみる

### :checkered_flag: 結果
お問合せ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103667/8a6715d8-a16c-ff00-ded5-174fc279afd9.png)

cookieが保存されてるか確認！！
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103667/145a369d-c5d3-2e68-b02a-053fcd8ae26a.png)


ばっちし。

## 最後に

cookieをどうやったらブラウザに保存できるか考えこのような形に。まとめてみるとこんな感じで結構簡単そうにみえますが、辿り着くまでが中々難しい。ngrokならびに便利なツールやライブラリに感謝を。