You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

求助:Nuxt 3 API返回HTML而非JSON内容的问题排查

Nuxt 3 SSR应用复杂页面API请求异常排查

问题现象

  • 主页及部分页面运行正常,但复杂页面加载异常
  • 正常SSR模式下内部API请求不会在浏览器网络面板中显示,但异常页面的API请求可被观测到
  • 异常页面的API返回HTML内容,而非预期的JSON格式

相关代码

前端请求代码

const {data: service} = await useFetch("/api/service-detail?slug=" + useRoute().params.slug);

服务器端API代码

import {getRequestURL} from "h3";

export default defineEventHandler((event) => {
    var requestUrl = String(getRequestURL(event));
    var slug = requestUrl.split('=')[1];

    return $fetch('https://backend-url.example/api/example-endpoint/' + slug);
});

Nuxt配置

export default defineNuxtConfig({
    buildModules: ['@nuxt/http', '@nuxt/http-security'],
    postcss: {
        plugins: {
            tailwindcss: {},
            autoprefixer: {}
        }
    },
    modules: ['nuxt-schema-org'],
    vite: {
        css: {
            preprocessorOptions: {
                sass: {
                    additionalData: '@import "@/assets/styles/_variables.sass"'
                }
            }
        }
    }
});

问题原因

  1. SSR渲染失败,降级为客户端请求
    服务器端渲染过程中如果出现错误(比如参数解析失败、外部API请求出错),Nuxt会自动回退到客户端重新发起请求,此时请求就会出现在浏览器网络面板中。

  2. 外部API错误未处理,返回HTML兜底
    服务器端API请求外部服务时如果返回错误状态码(如404、500),且未做错误捕获处理,Nuxt会默认返回当前页面的HTML内容,而非预期的JSON格式错误信息。

  3. 参数解析逻辑脆弱
    通过requestUrl.split('=')[1]获取slug的方式存在诸多问题:

    • 若URL中没有=符号,直接报错
    • 若slug本身包含=符号,会被截断
    • 未处理URL编码的特殊字符
  4. 过时模块兼容性冲突
    @nuxt/http模块在Nuxt 3中已被内置的useFetch/$fetch替代,继续使用可能导致SSR请求逻辑冲突;@nuxt/http-security也可能存在与Nuxt 3不兼容的情况,干扰请求处理流程。

修复方案

  1. 安全解析查询参数
    改用h3提供的getQuery工具函数获取参数,避免解析错误:
import {getQuery} from "h3";

export default defineEventHandler((event) => {
    const { slug } = getQuery(event);
    if (!slug) {
        throw createError({ statusCode: 400, statusMessage: 'Slug参数必填' });
    }
    return $fetch(`https://backend-url.example/api/example-endpoint/${slug}`);
});
  1. 添加错误捕获与处理
    在服务器端API中捕获外部请求错误,返回标准JSON格式错误:
import {getQuery, createError} from "h3";

export default defineEventHandler(async (event) => {
    const { slug } = getQuery(event);
    if (!slug) {
        throw createError({ statusCode: 400, statusMessage: 'Slug参数必填' });
    }
    try {
        return await $fetch(`https://backend-url.example/api/example-endpoint/${slug}`);
    } catch (error) {
        throw createError({
            statusCode: error.response?.status || 500,
            statusMessage: error.response?.statusText || '获取数据失败',
            data: { message: error.message }
        });
    }
});
  1. 移除过时模块
    删除Nuxt配置中已废弃的@nuxt/http和@nuxt/http-security模块:
export default defineNuxtConfig({
    postcss: {
        plugins: {
            tailwindcss: {},
            autoprefixer: {}
        }
    },
    modules: ['nuxt-schema-org'],
    vite: {
        css: {
            preprocessorOptions: {
                sass: {
                    additionalData: '@import "@/assets/styles/_variables.sass"'
                }
            }
        }
    }
});
  1. 前端添加错误处理
    在useFetch中处理错误,避免页面崩溃:
const {data: service, error} = await useFetch(`/api/service-detail?slug=${useRoute().params.slug}`);

if (error.value) {
    console.error('服务数据加载失败:', error.value);
    // 可在此添加错误提示UI逻辑
}

内容的提问来源于stack exchange,提问作者Enver

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 14:28:31