Skip to content

Commit

Permalink
fix: server.js
Browse files Browse the repository at this point in the history
  • Loading branch information
521xueweihan committed Aug 12, 2024
1 parent 8a8c88e commit 15baa30
Show file tree
Hide file tree
Showing 3 changed files with 212 additions and 64 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
"next": "^12.1.6",
"next-i18next": "^15.3.0",
"nprogress": "^0.2.0",
"pino-http": "^10.2.0",
"raw-loader": "^4.0.2",
"rc-image": "^7.0.0-2",
"rc-util": "^5.34.1",
Expand Down
123 changes: 60 additions & 63 deletions server.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
const express = require('express');
const next = require('next');
const cookieParser = require('cookie-parser');
const pino = require('pino-http')();

const app = next({ dev: false });
const handle = app.getRequestHandler();
Expand All @@ -11,81 +12,77 @@ const DEFAULT_LOCALE = 'zh';
const FALLBACK_LOCALE = 'en';
const SUPPORTED_LOCALES = ['zh', 'en'];

const isStaticRoute = (url) => url.startsWith('/_next') || url.startsWith('/static');

const getLocaleFromUrl = (path) => {
const urlParts = path.split('/');
return SUPPORTED_LOCALES.includes(urlParts[1]) ? urlParts[1] : null;
};

const determineLocale = (req, urlLocale) => {
let locale = req.cookies.locale;
if (!locale) {
const browserLocale = req.acceptsLanguages(SUPPORTED_LOCALES);
locale = urlLocale || browserLocale || FALLBACK_LOCALE;
if (browserLocale && browserLocale !== 'zh') {
locale = FALLBACK_LOCALE;
}
}
return SUPPORTED_LOCALES.includes(locale) ? locale : FALLBACK_LOCALE;
};

const handleRedirect = (req, res, locale, urlLocale) => {
if (urlLocale) {
if (urlLocale !== locale) {
locale = urlLocale;
}
if (locale === DEFAULT_LOCALE) {
const newUrl = req.url.replace(`/${DEFAULT_LOCALE}`, '') || '/';
return res.redirect(307, newUrl);
}
} else if (locale !== DEFAULT_LOCALE) {
let newUrl = `/${locale}${req.url}`;
if (newUrl.endsWith('/') && newUrl.length > 1) {
newUrl = newUrl.slice(0, -1);
}
return res.redirect(307, newUrl);
}
return false;
};

const canSetCookie = (req) => {
// 检查请求头中是否有 'cookie' 字段
return req.headers.cookie !== undefined;
};

async function startServer() {
try {
await app.prepare();
const server = express();
server.use(cookieParser());
server.use(pino);

// 中间件处理语言选择和路由
server.use((req, res, next) => {
if (req.url.startsWith('/_next') || req.url.startsWith('/static')) {
next();
} else {
let locale = req.cookies.locale;

// 解析 URL 中的语言设置
const urlParts = req.path.split('/');
const urlLocale = SUPPORTED_LOCALES.includes(urlParts[1])
? urlParts[1]
: null;

if (!locale) {
// 如果没有 cookie,使用 URL 中的语言或浏览器偏好
const browserLocale = req.acceptsLanguages(SUPPORTED_LOCALES);
locale = urlLocale || browserLocale || FALLBACK_LOCALE;

// 如果浏览器语言不是中文,默认使用英语
if (browserLocale && browserLocale !== 'zh') {
locale = FALLBACK_LOCALE;
}
}

// 确保 locale 是支持的语言之一
locale = SUPPORTED_LOCALES.includes(locale) ? locale : FALLBACK_LOCALE;
if (urlLocale) {
// URL 中有语言前缀
if (urlLocale !== locale) {
// URL 语言与 cookie 不匹配,更新 locale
locale = urlLocale;
}
if (locale === DEFAULT_LOCALE) {
// 默认语言不应该在 URL 中显示,重定向到无前缀的 URL
const newUrl = req.url.replace(`/${DEFAULT_LOCALE}`, '') || '/';
return res.redirect(307, newUrl);
}
} else if (locale !== DEFAULT_LOCALE) {
// URL 中没有语言前缀,且不是默认语言,添加前缀并重定向
let newUrl = `/${locale}${req.url}`;
if (newUrl.endsWith('/')) {
// 如果以 '/' 结尾,去掉末尾的 '/'
newUrl = newUrl.slice(0, -1);
}
return res.redirect(307, newUrl);
}

// 设置或更新 cookie
res.cookie('locale', locale, {
maxAge: 365 * 24 * 60 * 60 * 1000,
});
if (isStaticRoute(req.url)) {
return next();
}

req.locale = locale;
const urlLocale = getLocaleFromUrl(req.path);
let locale = determineLocale(req, urlLocale);

// // 处理尾部斜杠并重定向
// if (req.url.length > 1 && req.path.endsWith('/')) {
// const newUrl =
// req.path.slice(0, -1) + req.params
// return res.redirect(301, newUrl);
// }
if (handleRedirect(req, res, locale, urlLocale)) {
return; // 如果发生重定向,立即返回
}

next();
// 检查响应头是否已经发送
if (canSetCookie(req) && !res.headersSent) {
res.cookie('locale', locale, { maxAge: 365 * 24 * 60 * 60 * 1000 });
}
req.locale = locale;
next();
});

// 处理所有其他请求
server.all('*', (req, res) => {
return handle(req, res);
});
server.all('*', (req, res) => handle(req, res));

server.listen(PORT, (err) => {
if (err) throw err;
Expand All @@ -97,4 +94,4 @@ async function startServer() {
}
}

startServer();
startServer();
Loading

0 comments on commit 15baa30

Please sign in to comment.