🧚

Next.js でProxyAPIを実装する

2020/12/30に公開

これは何?

Next.jsのAPI機能を使ってProxy機能を作成します。
/api/proxy/配下で外部APIへプロキシリクエストできるため、CORSを回避できたり、next/Image componentで利用する画像をAmazon S3等外部リソースへプロキシすることができます。

ディレクトリ構成

pages/api
└── proxy
    └── [...slug].ts

Next.jsではpages/api以下をAPIサーバとして利用することができます。
特定パス以降を全てプロキシするため、ファイル名を[...slug]とします。

proxy実装

http-proxyを使って実装します。

import { IncomingMessage, ServerResponse } from 'http'
import httpProxy from 'http-proxy';

const target = "https://api.exchangeratesapi.io/"
const proxy = httpProxy.createProxyServer({ target, changeOrigin: true });

export default async function handler(req: IncomingMessage, res: ServerResponse) {
    req.url = req.url!.replace(new RegExp("^/api/proxy"), "")

    return new Promise((resolve, reject) => {
        try {
            proxy.web(req, res, { proxyTimeout: 5000 }, (e) => {
                reject(e)
            })
	    resolve
        } catch (e) {
            reject(e)
        }
    })
}

サンプルとして通貨取得APIを利用しました。
handlerは非常にシンプルでproxyへreq, resを渡しているだけです。
http-proxypathRewriteといったPathを書き換えるオプションが提供されていないようだったのでreq.urlを自前で書き換えています。

出力

Nextを起動し取得が確認しましょう。

$ curl "http://localhost:3000/api/proxy/latest?base=JPY"
{"rates":{"CAD":0.0123500747,"HKD":0.0747017213,"ISK":1.2284838481,"PHP":0.4629647096,"DKK":0.0584626267,"HUF":2.8651261495,"CZK":0.206727973,"GBP":0.0071416333,"RON":0.0383219367,"SEK":0.0792580366,"IDR":136.0182346931,"INR":0.7069244675,"BRL":0.0500801698,"RUB":0.7088603317,"HRK":0.0592996935,"JPY":1.0,"THB":0.2894443134,"CHF":0.0085372947,"EUR":0.0078597815,"MYR":0.039027745,"BGN":0.0153721607,"TRY":0.0708771516,"CNY":0.0629332705,"NOK":0.0829206948,"NZD":0.0134960308,"ZAR":0.1412017606,"USD":0.0096353061,"MXN":0.1917794545,"SGD":0.0127910084,"AUD":0.0126707538,"ILS":0.0309384579,"KRW":10.5347009353,"PLN":0.035611098},"base":"JPY","date":"2020-12-29"}

Discussion