見出し画像

Nuxt3でAPI proxyをする方法

Nuxt2からNuxt3へアップデートする際に、proxyに利用していたproxy-module及びデータフェッチライブラリのaxiosを、それぞれhttp-proxy-module、ofetchへと変更しました。
この記事ではそれらのライブラリを利用したproxyの設定や、リクエスト時の共通設定について説明します。

@nuxtjs/axios
Axios module supports Nuxt 2. Nuxt 3 users can use the new isomorphic $fetch API (migration guide).
上記にあるように
Nuxt3になってからaxiosからfetchが推奨になったので元々使っていたaxios moduleから移行する際に行ったproxyの設定の導入の一例となります。


1. インストール

Nuxt3のProjectで下記モジュールをインストールします。
こちらのモジュールは元Nuxt2対応のproxy-moduleでも採用されているものなので、Nuxtとの親和性という部分でも採用しています。
また、beta版ではありますが、Vue3対応のものがbetaとして提供されています。
https://github.com/nuxt-community/proxy-module
http-proxy-middleware@beta

npm install http-proxy-middleware@beta

2. Nuxt ConfigにAPI URLを設定(任意)

runtimeConfig: {
  API_URL: 'https://hogehoge.com'
}

3. Proxyの設定

インストールができたらserver/middlewareでProxyの設定をします。
Proxyで使用するmoduleは下記でoptionが確認できます。

nitoroサーバーでの処理はh3というmoduleを通して行われます。
2点のことを主にしています。
・APIのURLを任意のパスにproxyしている
・リクエストがあったパスがAPIパスかを判定し、APIパスのみproxyするようにしている

/server/middleware/proxy.ts

import { defineEventHandler } from 'h3'
import { createProxyMiddleware } from 'http-proxy-middleware'

export default defineEventHandler(async (event) => {
  const url = event.node.req.url
  // APIパスが複数ある場合
  const apiPaths = ['/api', '/api2']
    // APIのパスと指定したもの以外は処理を止める止めないと他のパスに影響が出る
  const isContained = typeof url === 'string' && apiPaths.some((apiPath: string) => new RegExp(`^${apiPath}([/?]|$)`).test(url))
  if (!isContained) {
    return
  }
  const config = useRuntimeConfig()
    // Nuxt configで登録したAPI_URLを設定
  const API_URL = `${config.API_URL}`
  const myProxy = createProxyMiddleware({
    target: API_URL,
    changeOrigin: true,
    ws: true,
    logger: console,
    pathRewrite: {
      '^/api': '/api',
      '^/api2': '/api2',
    },
    pathFilter: apiPaths
  })
  await new Promise((resolve, reject) => {
    const next = (err?: unknown) => {
      if (err) {
        reject(err)
      } else {
        resolve(true)
      }
    }

    myProxy(event.req, event.res, next)
  })
})

4. Proxy設定とofetchへの移行


上記でのサーバー側のProxy以外にもクライアント側でリクエストができるようにmodule側にbaseURLを設定する必要があります。
また、axiosの際に設定していたinterceptors request(リクエスト時の共通設定)をofetchに移行をしています。

今回はcomposablesで関数を定義しました。
/composables/useApiFetch.ts

import { Buffer } from 'buffer'てい
export const useApiFetch = () => {
  const config = useRuntimeConfig()
  // basic authがある場合、ない場合いらない
  const buffer = `${config.basicUserName}:${config.basicPassword}`
  const basicAuth = `Basic ${Buffer.from(buffer).toString('base64')}`
  const apiFetch = $fetch.create({
    baseURL: config.public.HOME_URL,
    onRequest ({ options }) {
            // headerにCookieをセット
      options.headers = useRequestHeaders(['cookie']) as Record<string, string>
      // ヘッダーを定義し直す
            options.headers = new Headers(options.headers)
      // basic authをAuthorizationにセット
      if (config.basicUserName && config.basicPassword) {
        options.headers.set('Authorization', basicAuth)
      }
    }
  })
  return {
    apiFetch
  }
}

5. 使い方

各Vueファイルのsetup内からcomposables経由で呼び出す

<script lang="ts" setup>
const { apiFetch } = useApiFetch()
</script>

このままconst data = await apiFetch('/api/hoge')のように叩いてもいいですが、Nuxt3の恩恵をより受けたいなら、下記のように叩くと良いです。

const { data: hogeData } = await useAsyncData('hoge-key', apiFetch('/api/hoge'))

6. まとめ

proxy周りの設定について、いくつか方法がありますが、安定した実装を見つけることができたのでよかったです。

また、serverとclientの両方でproxyの設定を行う必要があるため、それぞれの挙動や考慮ポイントについて学びました。

Nuxt3のアップデートが頻繁に行われているため、新しい情報に追いつく必要があると感じました。現在も新しい改善点や重要な変更点が出ている可能性があるので、引き続き情報を追って適応していく予定です。

余談ですが、下記のようなモジュールも提供されているみたいです。


この記事が気に入ったらサポートをしてみませんか?