ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

Epic Stack 重定向实战:在 Express 层统一处理 HTTPS、尾部斜杠与 www 子域跳转

Epic Stack 重定向实战:在 Express 层统一处理 HTTPS、尾部斜杠与 www 子域跳转 Epic Stack 重定向实战在 Express 层统一处理 HTTPS、尾部斜杠与 www 子域跳转【免费下载链接】epic-stackThis is a Full Stack app starter with the foundational things setup and configured for you to hit the ground running on your next EPIC idea.项目地址: https://gitcode.com/GitHub_Trending/ep/epic-stack本指南基于 docs/redirects.md 展开讲解 Epic Stack 如何在 React RouterRemix框架接手请求之前于 Express 中间件层统一完成三类重定向HTTP 强制跳转 HTTPS、去除 URL 尾部斜杠、以及 www 子域与根域之间的互相跳转。读完本文你将掌握在 Express 中实现高性能、SEO 友好的重定向的完整代码方案并能直接在本仓库的 server/index.ts 中看到对应落地实现。为什么在 Express 层处理重定向而不是在 React Router 里Epic Stack 的服务端架构是 Express 在前、React Router 在后server/index.ts启动 Express 应用所有中间件按注册顺序依次执行最终才把请求交给server/app.ts中通过createRequestHandler创建的 React Router 请求处理器。Express 中间件压缩、Helmet、限流、重定向…… ↓ React Router 请求处理器createRequestHandler见 server/app.ts ↓ 路由模块app/routes/**把重定向放在 Express 层而不是路由层核心收益是性能入站请求在到达 React Router 之前就会被 Express 拦截并直接返回响应无需经过完整的路由匹配、加载器执行与渲染流程。Epic Stack 在 docs/redirects.md 中明确说明了这一设计初衷——by redirecting earlier you improve performance。在源码 server/index.ts 中这些重定向中间件确实被放置在中间件链的最前面紧随app.set(trust proxy, true)之后早于compression()压缩、Helmet 安全头、morgan 日志和限流中间件确保重定向路径的开销降到最低。前置条件正确获取代理层转发的请求头所有重定向逻辑都依赖一个共同的基础正确识别客户端请求的协议与域名。由于 Epic Stack 部署在 Fly.io 这类反向代理之后Express 拿到的直接连接来自代理而非客户端因此必须信任并读取代理注入的转发头。// 源码server/index.ts const getHost (req: { get: (key: string) string | undefined }) req.get(X-Forwarded-Host) ?? req.get(host) ?? // fly is our proxy app.set(trust proxy, true)app.set(trust proxy, true)告诉 Express 信任反向代理使req.ip等字段基于代理头计算getHost(req)优先读取X-Forwarded-Host由 Fly 网关注入取不到再回退到标准Host头兜底为空字符串。HTTP 强制跳转 HTTPSEpic Stack 默认强制所有流量走 HTTPS杜绝任何环节的明文请求被拦截的可能。实现方式是检查代理转发的协议头X-Forwarded-Proto只要它是http就立即 302 跳转到对应的https地址。文档中的核心实现app.use((req, res, next) { const proto req.get(X-Forwarded-Proto) const host getHost(req) if (proto http) { res.set(X-Forwarded-Proto, https) res.redirect(https://${host}${req.originalUrl}) return } next() })注意两个容易被忽略的细节X-Forwarded-Proto来自 Fly文档明确指出 we use Flys request headers for determining when to redirect因此本地开发localhost不会误触发该跳转跳转目标拼接了req.originalUrl它包含完整的原始路径与查询字符串保证跳转后用户停留在原页面而非首页。源码中的一处增强仅拦截 GET 请求文档中的示例对任何方法都生效而仓库实际实现 server/index.ts 加了一层守卫app.use((req, res, next) { if (req.method ! GET) return next() const proto req.get(X-Forwarded-Proto) const host getHost(req) if (proto http) { res.set(X-Forwarded-Proto, https) res.redirect(https://${host}${req.originalUrl}) return } next() })这是因为非 GET 请求如表单 POST 提交若被 302 重定向浏览器会丢失原始请求体与方法导致提交失败。只对 GET 请求做协议升级重定向是一种更安全的做法。平台层兜底Fly 的 force_https除了应用内中间件Epic Stack 的 fly.toml 在平台层也做了 HTTPS 强制[[services.ports]] handlers [ http ] port 80 force_https trueforce_https true会让 Fly 网关在 80 端口直接拒绝或升级 HTTP 流量与应用层中间件形成双重保障。实践中应用层逻辑仍然是必需的因为并非所有部署环境都能配置平台级强制。去除 URL 尾部斜杠SEO 关键处理爬虫如 Google会把https://example.com/foo/与https://example.com/foo视为两个独立 URL从而产生重复内容问题。Epic Stack 通过 Express 中间件自动将带尾部斜杠的 URL 301 跳转到无斜杠版本。文档中的核心实现app.use((req, res, next) { if (req.path.endsWith(/) req.path.length 1) { const query req.url.slice(req.path.length) const safepath req.path.slice(0, -1).replace(/\//g, /) res.redirect(301, safepath query) } else { next() } })逐行拆解这段逻辑req.path.endsWith(/) req.path.length 1排除根路径/本身根路径的斜杠是合法的不能去掉const query req.url.slice(req.path.length)从完整 URL 中截取查询字符串部分?abcd因为req.url是路径 查询串而req.path只有路径const safepath req.path.slice(0, -1).replace(/\//g, /)去掉末尾斜杠并把连续多个斜杠///折叠为单个斜杠res.redirect(301, safepath query)使用301 永久重定向把 SEO 权重完整传递给新地址。例如请求https://example.com/foo/?utm_sourcexreq.path为/foo/query为?utm_sourcex最终 301 到https://example.com/foo?utm_sourcex查询参数完整保留。源码中的实际差异302 而非 301仓库实际实现 server/index.ts 与文档示例有一处状态码差异——生产代码使用的是 302// no ending slashes for SEO reasons // https://github.com/epicweb-dev/epic-stack/discussions/108 app.get(/.*/, (req, res, next) { if (req.path.endsWith(/) req.path.length 1) { const query req.url.slice(req.path.length) const safepath req.path.slice(0, -1).replace(/\//g, /) res.redirect(302, safepath query) } else { next() } })另外两点差异值得注意注册方式不同生产代码使用app.get(/.*/, ...)而不是app.use(...)效果上只对 GET 请求生效避免 POST 表单因重定向丢失请求体状态码为 302在先验证跳转正确、再切换 301的发布策略下更稳妥。如果你想追求最佳 SEO 效果可以参照 docs/redirects.md 的示例改用301但要确保所有内部链接已同步去除尾部斜杠避免永久跳转链。www 子域与根域之间的跳转Epic Stack 同时支持两种域名规范化方向根域跳转到 www或www 跳转到根域二选一即可避免同一站点在多个域名下被索引为不同站点。为什么不能在 DNS 层做文档特别指出DNS 级别的重定向在 Fly.io 上不可用Fly 平台不支持 CNAME flattening 之类的隐式跳转因此推荐在应用代码里实现。前提是你需要为两个域名分别注册 SSL 证书——在 Fly 后台选中应用后进入 Certificates 面板或通过fly certs add类命令在终端注册之后 Fly 会同时接受来自两个域名的流量应用层再按规则跳转到首选域名。方向一根域 → wwwapp.use((req, res, next) { const host getHost(req) if (!host.startsWith(www.)) { return res.redirect(301, https://www.${host}${req.url}) } else { next() } })当Host不是以www.开头时301 永久重定向到https://www. 原域名 原路径req.url保留查询字符串。若访问的是https://example.com/about?tab1将跳到https://www.example.com/about?tab1。方向二www → 根域app.use((req, res, next) { const host getHost(req) if (host.startsWith(www.)) { return res.redirect(301, https://${host.slice(4)}${req.url}) } else { next() } })host.slice(4)恰好去掉www.这 4 个字符其余逻辑与方向一对称。两个方向只能启用其一具体选择取决于你的品牌域名偏好如epicstack.dev官方站点即采用 www 形式见测试工具 tests/utils.ts 中的BASE_URL https://www.epicstack.dev。注意这三个重定向中间件HTTPS、尾部斜杠、www在实际部署时是按顺序叠加的例如请求http://example.com/foo/可能依次经历协议升级、去斜杠、域名规范化多次跳转。若想减少跳转次数可以将判断合并进单一中间件。在测试中验证重定向行为Epic Stack 的测试体系为重定向断言提供了专用匹配器toHaveRedirect定义于 tests/setup/custom-matchers.ts。它做三件事检查响应头存在location且状态码落在 3xx 区间支持传入期望的跳转地址做精确断言对location与期望值做规范化比较urlsMatch忽略 origin、排序后的 query 参数与 hash 差异避免因端口、参数顺序导致误报。例如断言某请求应 302 跳转到登录页可以这样写const response await request(...) expect(response).toHaveRedirect(/login)配合BASE_URLtests/utils.ts与实际用例如 tests/e2e/settings-profile.test.ts 中保存头像后的跳转断言可以在端到端层面守住重定向行为防止中间件顺序或状态码调整造成回归。小结Epic Stack 在 Express 层完成的三类重定向体现了一个值得借鉴的服务端设计原则能在入口层解决的问题不要拖到应用层。通过 docs/redirects.md 与 server/index.ts 的对照可以看到HTTP→HTTPS 通过X-Forwarded-Proto头判断仅对 GET 请求生效配合 Fly 的force_https双保险去除尾部斜杠使用折叠斜杠 保留查询串的跳转SEO 场景应使用 301www 域规范化因 Fly 不支持 DNS 级跳转而必须在代码中完成需先为两个域名注册证书所有重定向都发生在 React Router 接手之前性能开销最小且可通过toHaveRedirect匹配器在测试中锁定行为。直接复制文档中的三段 Express 中间件即可在任意 Express React Router 应用中复现这套完整、SEO 友好的重定向方案。【免费下载链接】epic-stackThis is a Full Stack app starter with the foundational things setup and configured for you to hit the ground running on your next EPIC idea.项目地址: https://gitcode.com/GitHub_Trending/ep/epic-stack创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表