ALIEZ 1 ヶ月 前
コミット
1d1a2c011c
1 ファイル変更47 行追加14 行削除
  1. 47 14
      server.js

+ 47 - 14
server.js

@@ -2,24 +2,57 @@
 const { createServer } = require('http');
 const { parse } = require('url');
 const next = require('next');
- 
+
 const port = Number(process.env.PORT || 4000);
-const app = next({ dev: false });
+
+/**
+ * 自定义 server 若写 `next({ dev: false })` 不传 port,Next 内部仍默认 3000(见 next/dist/server/next.js),
+ * 与 `listen(4000)` 不一致时,307 Location 会变成 `http://jinclab.com:3000/zh` 这类错误地址。
+ *
+ * 反代终止 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) =>
-	{
-		// Be sure to pass `true` as the second argument to `url.parse`.
-		// This tells it to parse the query portion of the URL.
+
+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')
-		{
+	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);
@@ -29,4 +62,4 @@ app.prepare().then(() =>
 	});
 
 	server.listen(port);
-});
+});