58 lines
2.1 KiB
JavaScript
58 lines
2.1 KiB
JavaScript
// 本地预览用的极简代理:模拟生产里 proxy(nginx) 的分流。
|
||
//
|
||
// /api/* → 后端(默认 127.0.0.1:8090)
|
||
// 其余 → astro preview(默认 127.0.0.1:4322)
|
||
//
|
||
// 为什么需要它:生产环境里浏览器只访问一个域名,/api 由 nginx 反代到后端;
|
||
// 本地没有 nginx,astro preview 只跑 Astro 自己的路由,/api 会 404。
|
||
// 这个脚本让本地的访问方式和生产一致(同源),不产生 CORS,也不需要改任何业务配置。
|
||
//
|
||
// 用法:
|
||
// node scripts/local-proxy.mjs # 默认 http://localhost:8099
|
||
// PROXY_PORT=9000 node scripts/local-proxy.mjs
|
||
// (先启动 astro preview,再启动它)
|
||
import http from 'node:http'
|
||
|
||
const PORT = Number(process.env.PROXY_PORT || 8099)
|
||
const WEB_ORIGIN = process.env.WEB_ORIGIN || 'http://127.0.0.1:4322'
|
||
const API_ORIGIN = process.env.API_ORIGIN || 'http://127.0.0.1:8090'
|
||
|
||
const server = http.createServer((req, res) => {
|
||
const url = req.url || '/'
|
||
const isApi = url === '/api' || url.startsWith('/api/')
|
||
const target = new URL(url, isApi ? API_ORIGIN : WEB_ORIGIN)
|
||
|
||
const proxyReq = http.request(
|
||
{
|
||
protocol: target.protocol,
|
||
hostname: target.hostname,
|
||
port: target.port,
|
||
path: target.pathname + target.search,
|
||
method: req.method,
|
||
headers: { ...req.headers, host: target.host },
|
||
},
|
||
(proxyRes) => {
|
||
res.writeHead(proxyRes.statusCode || 502, proxyRes.headers)
|
||
proxyRes.pipe(res)
|
||
}
|
||
)
|
||
|
||
proxyReq.on('error', (err) => {
|
||
// 后端没起 / preview 没起时给出明确提示,而不是挂住
|
||
res.writeHead(502, { 'content-type': 'text/plain; charset=utf-8' })
|
||
res.end(
|
||
`local-proxy: 连不上 ${isApi ? API_ORIGIN : WEB_ORIGIN}\n` +
|
||
`${err.message}\n\n` +
|
||
(isApi ? '先把后端跑起来(8090)\n' : '先跑 npm run preview(4322)\n')
|
||
)
|
||
})
|
||
|
||
req.pipe(proxyReq)
|
||
})
|
||
|
||
server.listen(PORT, () => {
|
||
console.log(`[local-proxy] http://localhost:${PORT}`)
|
||
console.log(` /api/* → ${API_ORIGIN}`)
|
||
console.log(` 其余 → ${WEB_ORIGIN}`)
|
||
})
|