⚡
ViteでリクエストURL規則以外のカスタムプロキシを設定する
対象
- Viteにおいて特定のHTTPヘッダなど、リクエストURLの規則以外の情報でプロキシサーバを設定したい(サーバサイドにリクエストを送信したい)方
概要
Viteには開発サーバのカスタムプロキシが用意されており、vite.config.ts
に以下の様な設定が可能です。
export default defineConfig({
server: {
proxy: {
'/api': {
target: 'http://localhost:4000',
changeOrigin: true,
rewrite: (path) => path.replace(/^\/api/, ''),
},
}
}
}
上記の設定は/api
がURLに含まれる場合にhttp://localhost:4000
にリクエストが送信されます。(rewriteの設定により/api
は削除されます)
当該設定ではリクエストURL以外の情報では別サーバに送信できないため/api
を付与出来ない場合には対応できません。
そこでViteのプラグインを作成して独自のプロキシを行います。
解決策
http-proxy
を利用してプロキシサーバを設定します。プラグインのソースコードは以下のとおりです。
import httpProxy, { type ServerOptions } from 'http-proxy';
import type { Plugin } from 'vite';
export const CustomProxyPlugin = (options?: ServerOptions): Plugin => {
const _proxy: httpProxy | undefined = undefined;
return {
name: 'custom-proxy-server',
configureServer(server) {
server.middlewares.use((req, res, next) => {
if (req.headers['custom-header']) {
_proxy = _proxy ?? createProxy();
_proxy.web(req, res, options);
return;
}
next();
});
},
};
};
function createProxy() {
const proxy = httpProxy.createProxyServer();
proxy.on('proxyRes', (proxyRes, _, res) => {
res.on('close', () => {
proxyRes.destroy();
});
});
return proxy;
}
上記のプラグインをvite.config.ts
に設定します。
import { CustomProxyPlugin } from './your-path'
export default defineConfig({
plugins: [
CustomProxyPlugin({
target: 'http://localhost:4000',
changeOrigin: true,
}),
]
})
要素解説
ViteのプラグインはRollupをベースにした設計となっています。詳細はこちらをご参照ください。
ViteにはRollupのビルドフックに加えてVite固有のフックがあります。下記のconfigureServer
はVite内部のconnect
というHTTPサーバのフレームワークにカスタムミドルウェアを追加する際の設定になります。req
はリクエスト情報、res
はレスポンス情報、next
は次のミドルウェアに処理を投げる処理のため当該ミドルウェア(プロキシ)で処理しない場合はnext()
を実行します。下記の設定ではcustom-header
がリクエストヘッダにある場合のみ別サーバへリクエストを送信します。
const CustomProxyPlugin = (): Plugin => {
return {
name: 'custom-proxy-server',
configureServer(server) {
server.middlewares.use((req, res, next) => {
// 独自のヘッダが存在した場合
if (req.headers['custom-header']) {
// プロキシの処理(一部省略)
proxy.web(req, res, options);
return;
}
// それ以外は処理しない
next();
});
},
}
}
おわりに
ViteはRollupのプラグインインタフェースを軸にした素晴らしい拡張性を持っています。基本の設定で対応が難しい内容は独自のプラグインを作ってみるのも良いかもしれません。
Discussion