Nitro/h3(Nuxt3)<0.6のproduction build後にCORSヘッダが設定されない問題

:::note warn
この記事の内容は古いものです。最新版のドキュメントを確認してください。
:::

:::note info
Nitro0.6以降では解消されているようです。
:::

Nuxt3(nitro/h3)のserver/api以下フォルダなどに配置したapi routesは、defaultでcorsヘッダがありません。
dev時は自動で追加してくれるんですが、buildするとCORSヘッダが綺麗サッパリなくなります。

expressではcorsというモジュールを入れて対応していたのですがNuxt3は以下のように設定すれば不要です。って公式ドキュメントに書いてあったけど嘘でした。

設定する方法はこちら（×）

```nuxt.config.ts
// https://v3.nuxtjs.org/api/configuration/nuxt.config
export default defineNuxtConfig({
  routes: {
    "/api/**": {
      cors: true,
      headers: {
        "Access-Control-Allowed-Methods": "GET, POST, PUT, DELETE",
        "Access-Control-Allow-Origin": "*",
      },
    },
  },
});

```

## でいけると思ったらダメじゃん

defineNuxtConfigの下に書いても無視される・・・型のエラーもでる・・・

> 型 '{ cors: true; headers: { "Access-Control-Allowed-Methods": string; "Access-Control-Allow-Origin": string; }; }' を型 '{ swr?: number | boolean; redirect?: string; } | { swr?: number | boolean; redirect?: string; }' に割り当てることはできません。


https://github.com/nuxt/framework/issues/6650

> The routes setting only works in development mode for me, but doesn't work in production.

（Nitro 0.5.4の場合なので、将来的には解決しているかもしれません）
と思ったら、yarn devの時は自動で`"Access-Control-Allow-Origin": "*"`が入っているだけで、production build して yarn startするとCORSヘッダが入ってない。多分バグ？公式ドキュメントにもExperimentalと書いてあるので今はダメなのかも。

なので、middlewareに以下のように記述すれば、production buildでもcorsヘッダがちゃんと追記されました。

```server/middleware/cors.ts
export default defineEventHandler((event) => {
  setResponseHeaders(event, {
    "X-Hello-Im-Fine": "thankyou",
    "Access-Control-Allow-Methods": "GET, POST, PUT, DELETE",
    "Access-Control-Allow-Origin": "*",
  })
})
```

```sh:curl
curl -v http://localhost:8000/api/hello
*   Trying 127.0.0.1:8000...
* Connected to localhost (127.0.0.1) port 8000 (#0)
> GET /api/hello HTTP/1.1
> Host: localhost:8000
> User-Agent: curl/7.79.1
> Accept: */*
> 
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< X-Hello-Im-Fine: thankyou
< Access-Control-Allowed-Methods: GET, POST, PUT, DELETE
< Access-Control-Allow-Origin: *
< Content-Type: application/json
< Server-Timing: -;dur=0;desc="Generate"
< Date: Sun, 16 Oct 2022 05:17:38 GMT
< Connection: keep-alive
< Keep-Alive: timeout=5
< Content-Length: 15
< 
* Connection #0 to host localhost left intact
```

## これでOKと思ったらまだダメだった。

と思ってbuildしてyarn startしてブラウザからチェックするとプリフライトでエラー。OPTIONSでアクセスしたとき、server/api/hoge.post.ts や hoge.put.ts　のファイルに、OPTIONSでアクセスが行くと405 Method Not Allowedになってしまう。。え〜〜？？？

なので、苦肉の策でこのように回避している。

```server/middleware/cors.ts
export default defineEventHandler((event) => {
  setResponseHeaders(event, {
    "Access-Control-Allow-Methods": "GET,HEAD,PUT,PATCH,POST,DELETE",
    "Access-Control-Allow-Origin": "*",
    'Access-Control-Allow-Credentials': 'true',
    "Access-Control-Allow-Headers": '*',
    "Access-Control-Expose-Headers": '*'
  })
  if(getMethod(event) === 'OPTIONS'){
    event.res.statusCode = 204
    event.res.statusMessage = "No Content."
    return 'OK'
  }
})
```

Nitro、まだ全然ダメじゃん・・・そりゃNuxt3もRCのままですわ・・・

## 参考（にしにくい公式ドキュメント）

https://v3.nuxtjs.org/guide/directory-structure/server#nitro-configuration
https://nitro.unjs.io/config#routes

## プラグインを作ってくれている人がいる

https://github.com/unjs/h3/issues/82
https://github.com/NozomuIkuta/h3-cors