| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667 |
- /* eslint-disable @typescript-eslint/no-require-imports */
- const { createServer } = require('http');
- const { parse } = require('url');
- const next = require('next');
- const port = Number(process.env.PORT || 4000);
- /**
- * 自定义 server 若写 `next({ dev: false })` 不传 port,Next 内部仍默认 3000(见 next/dist/server/next.js),
- * 与 `listen(4000)` 不一致时,307 Location 会变成 `http://jinclab.com:3000/zh` 这类错误地址。
- *
- * 默认 4000 与常见 Nginx `proxy_pass http://127.0.0.1:4000` 一致;勿随意改默认,否则反代未同步会 502。
- *
- * 反代终止 TLS 后须传 `X-Forwarded-Proto: https`;若漏传,协议会判成 http。
- * 若 Host 误带内网端口,与 NEXT_PUBLIC_SITE_URL 对齐时去掉端口。
- */
- function normalizeProxyHeaders(req) {
- const site = process.env.NEXT_PUBLIC_SITE_URL?.trim().replace(/\/$/, '');
- if (!site || process.env.NODE_ENV !== 'production') return;
- let canonicalHost;
- try {
- canonicalHost = new URL(site).hostname;
- } catch {
- return;
- }
- const allowed = new Set([canonicalHost, `www.${canonicalHost}`]);
- const raw = req.headers.host;
- if (typeof raw !== 'string') return;
- const colon = raw.indexOf(':');
- const hostnameOnly = colon === -1 ? raw : raw.slice(0, colon);
- if (!allowed.has(hostnameOnly)) return;
- if (colon !== -1) {
- req.headers.host = hostnameOnly;
- }
- if (site.startsWith('https:') && !req.headers['x-forwarded-proto']) {
- req.headers['x-forwarded-proto'] = 'https';
- }
- }
- // port 必须与 listen 一致,避免 Next 内部仍按 3000 拼绝对 URL(勿改 hostname,以免内部 initURL 变成 127.0.0.1)
- const app = next({ dev: false, port });
- const handle = app.getRequestHandler();
- app.prepare().then(() => {
- const server = createServer((req, res) => {
- normalizeProxyHeaders(req);
- handle(req, res, parse(req.url, true));
- });
- server.on('error', (error) => {
- if (error.code === 'EADDRINUSE') {
- const fallbackPort = port + 1;
- console.warn(`Port ${port} is in use, retrying on ${fallbackPort}...`);
- server.listen(fallbackPort);
- return;
- }
- throw error;
- });
- server.listen(port);
- });
|