使用 Bun.serve 实现反向代理

一般情况下, 前端项目中会使用vite等工具作为开发服务器, 这些一般都直接支持 proxy 配置.

Bun 没有内置 proxy 相关的配置, 但可以直接使用 Bun.serve 来实现同样的效果.

主要思路

通过在 fetch 中识别到需要代理的请求, 带着原始的请求信息, 直接发起新的请求到目标服务器, 然后将响应返回给浏览器.

实例代码

此处展示的实例代码没有处理 hop-by-hop 相关的请求头, 以及一些边界情况, 但已经足够展示主要思路了.

import { fetch, serve } from "bun";
import index from "./index.html";
 
const server = serve({
    port: 3000,
    routes: {
        // Serve index.html for all unmatched routes.
        "/": index,
    },
    async fetch(req: Request) {
        const url = new URL(req.url);
        const targetUrl = new URL(url.pathname + url.search, "http://localhost:3001");
 
        try {
            const response = await fetch(targetUrl, {
                method: req.method,
                headers: req.headers,
                body: req.body,
            });
 
            // Since the response is decoded,
            // we need to delete encode-related fields in response header
            response.headers.delete("content-encoding");
            // and let browser re-calculate the length of content (since it's decoded)
            response.headers.delete("content-length");
 
            // Then return the response
            return response;
        } catch (err) {
            console.log(err);
            return new Response("Proxy target unavailable", { status: 502 });
        }
    },
    development: process.env.NODE_ENV !== "production" && {
        // Enable browser hot reloading in development
        hmr: true,
 
        // Echo console logs from the browser to the server
        console: true,
    },
});
 
console.log(`🚀 Server running at ${ server.url }`);

Reference