viteのサーバ用にリバースプロキシのミドルウェアを書いた。

expressを使うと楽に実装できた。

まだ試行錯誤しているので、とりあえずvite.config.tsにべた書き。

import { ViteDevServer, PluginOption, defineConfig } from 'vite'
import react from '@vitejs/plugin-react-swc'

import express from 'express';
import type { IncomingMessage, ServerResponse } from 'http';
import { request } from 'http';

function createReverseProxyHandler(path: string, proxyHost: string, proxyPort: number) {
  const handler = function(proxyReq: IncomingMessage, proxyRes: ServerResponse) {
    const serverReq = request({
      host: proxyHost,
      port: proxyPort,
      method: proxyReq.method,
      path: proxyReq.url,
      headers: proxyReq.headers, 
    }).on('error', () => {
      proxyRes.writeHead(502).end();
    }).on('timeout', () => {
      proxyRes.writeHead(504).end();
    }).on('response', serverRes => {
      proxyRes.writeHead(serverRes.statusCode!, serverRes.headers)
      serverRes.pipe(proxyRes);
    })
    proxyReq.pipe(serverReq);
  }

  const router = express();
  router.use(path, handler);
  return router;
}

function ReverseProxyPlugin(props: {path: string, proxyHost: string, proxyPort: number}): PluginOption {
  const { path, proxyHost, proxyPort } = props;
  return {
    name: 'ReverseProxyPlugin',
    configureServer(server: ViteDevServer) {
      server.middlewares.use(createReverseProxyHandler(path, proxyHost, proxyPort));
    },
  } as const satisfies PluginOption;
}

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [
    react(),
    ReverseProxyPlugin({
      path: '/api/',
      proxyHost: '127.0.0.1',
      proxyPort: 4000,
    }),
  ]
})