Next.js App Router返回HTML脚本被pre标签包裹问题求助
Next.js App Router 登录回调接口脚本无法执行的解决办法
问题场景
需要实现登录回调接口,返回HTML脚本在客户端设置localStorage并跳转页面,但用App Router写的接口返回的脚本被浏览器转义,包裹在<pre>标签里没法执行。
当前App Router代码
import { NextResponse } from "next/server"; export const GET = () => { return new NextResponse('<script>localStorage.setItem("authToken", "authToken");window.location.assign("/");</script>'); };
当前错误响应
浏览器收到的响应会自动包裹转义后的脚本:
<html> <head><meta name="color-scheme" content="light dark"></head> <body> <pre style="word-wrap: break-word; white-space: pre-wrap;"> &lt;script&gt;localStorage.setItem("authToken", "authToken");window.location.assign("/");&lt;/script&gt; </pre> </body> </html>
期望的正确响应
脚本应直接嵌入HTML中,能被浏览器执行:
<html> <head><meta name="color-scheme" content="light dark"></head> <body> <script>localStorage.setItem("authToken", "authToken");window.location.assign("/")</script> </body> </html>
而用Pages Router的相同逻辑代码可以正常工作:
export default function handler(req: NextApiRequest, res: NextApiResponse) { return res.send('<script>localStorage.setItem("authToken", "authToken");window.location.assign("/");</script>'); }
解决方法
问题核心是没指定正确的响应Content-Type头。App Router里NextResponse默认把字符串响应识别为text/plain,浏览器会把纯文本转义后放在<pre>标签里展示。手动设置Content-Type为text/html就能解决:
修改后的App Router代码:
import { NextResponse } from "next/server"; export const GET = () => { const htmlContent = '<script>localStorage.setItem("authToken", "authToken");window.location.assign("/");</script>'; return new NextResponse(htmlContent, { headers: { "Content-Type": "text/html; charset=utf-8", }, }); };
原因说明
- Pages Router的
res.send()方法会自动检测响应内容类型,识别到HTML标签时会自动设置Content-Type: text/html,所以脚本能正常被浏览器解析执行。 - App Router的
NextResponse构造函数默认不做内容类型推断,直接返回字符串时会用text/plain作为默认类型,导致浏览器把内容当纯文本处理,转义标签并包裹在<pre>中。
内容的提问来源于stack exchange,提问作者Тэмүүлэн Нармандах
相关产品推荐
相关产品推荐

