求助:useFetch请求API返回HTML而非JSON的问题排查
问题:调用/api/auth/exists/email接口时返回HTML页面而非预期JSON数据
调用/api/auth/exists/email接口时,前端useFetch返回的是HTML页面而非预期的JSON数据,已尝试注释代码块并逐步测试但问题仍未解决。相关代码如下:
前端请求代码
const { data } = await useFetch('/api/auth/exists/email', { query: { email_address: enteredEmail.value }, baseURL: '/api/auth/exists/email', onResponseError: ({error}) => { console.error(error); registrationErrors.email.push('An unexpected error has occurred.') } });
返回的HTML内容
RESPONSE: <!DOCTYPE html> <html > <head><meta charset="utf-8"> <meta name="viewport" content="width=device-width, initial-scale=1"><link rel="preload" as="style" href="/_nuxt/node_modules/@fortawesome/fontawesome-svg-core/styles.css"><link rel="preload" as="style" href="/_nuxt/node_modules/@vueform/multiselect/themes/default.css"><link rel="preload" as="style" href="/_nuxt/node_modules/animate.css/animate.min.css"><link rel="preload" as="style" href="/_nuxt/node_modules/@vueform/toggle/themes/default.css"><link rel="preload" as="style" href="/_nuxt/node_modules/.cache/nuxt-google-fonts/css/nuxt-google-fonts.css"><link rel="preload" as="style" href="/_nuxt/node_modules/vite-plugin-vue-inspector/src/Overlay.vue?vue&type=style&index=0&scoped=31d1379f&lang.css"><link rel="preload" as="style" href="/_nuxt/components/AppHeader.vue?vue&type=style&index=0&lang.scss"><link rel="preload" as="style" href="/_nuxt/components/AuthModal.vue?vue&type=style&index=0&scoped=ff55f906&lang.scss"><link rel="preload" as="style" href="/_nuxt/components/Modal.vue?vue&type=style&index=0&scoped=0b5a066a&lang.scss"><link rel="preload" as="style" href="/_nuxt/components/FormGroup.vue?vue&type=style&index=0&scoped=6b1d710f&lang.scss"><link rel="preload" as="style" href="/_nuxt/components/ErrorBox.vue?vue&type=style&index=0&scoped=c34b980e&lang.scss"><link rel="preload" as="style" href="/_nuxt/components/TextInput.vue?vue&type=style&index=0&scoped=4f98be6b&lang.scss"><link rel="preload" as="style" href="/_nuxt/components/Checkbox.vue?vue&type=style&index=0&scoped=84f5ff5b&lang.scss"><link rel="preload" as="style" href="/_nuxt/components/ButtonPrimary.vue?vue&type=style&index=0&scoped=fcc59362&lang.scss"><link rel="preload" as="style" href="/_nuxt/components/AppHeaderSubMenu.vue?vue&type=style&index=0&lang.scss"><link rel="modulepreload" as="script" crossorigin href="/_nuxt/Users/hayden/Desktop/k_discuss/node_modules/nuxt/dist/app/entry.js"><link rel="stylesheet" href="/_nuxt/node_modules/@fortawesome/fontawesome-svg-core/styles.css"><link rel="stylesheet" href="/_nuxt/node_modules/@vueform/multiselect/themes/default.css"><link rel="stylesheet" href="/_nuxt/node_modules/animate.css/animate.min.css"><link rel="stylesheet" href="/_nuxt/node_modules/@vueform/toggle/themes/default.css"><link rel="stylesheet" href="/_nuxt/node_modules/.cache/nuxt-google-fonts/css/nuxt-google-fonts.css"><link rel="stylesheet" href="/_nuxt/node_modules/vite-plugin-vue-inspector/src/Overlay.vue?vue&type=style&index=0&scoped=31d1379f&lang.css"><link rel="stylesheet" href="/_nuxt/components/AppHeader.vue?vue&type=style&index=0&lang.scss"><link rel="stylesheet" href="/_nuxt/components/AuthModal.vue?vue&type=style&index=0&scoped=ff55f906&lang.scss"><link rel="stylesheet" href="/_nuxt/components/Modal.vue?vue&type=style&index=0&scoped=0b5a066a&lang.scss"><link rel="stylesheet" href="/_nuxt/components/FormGroup.vue?vue&type=style&index=0&scoped=6b1d710f&lang.scss"><link rel="stylesheet" href="/_nuxt/components/ErrorBox.vue?vue&type=style&index=0&scoped=c34b980e&lang.scss"><link rel="stylesheet" href="/_nuxt/components/TextInput.vue?vue&type=style&index=0&scoped=4f98be6b&lang.scss"><link rel="stylesheet" href="/_nuxt/components/Checkbox.vue?vue&type=style&index=0&scoped=84f5ff5b&lang.scss"><link rel="stylesheet" href="/_nuxt/components/ButtonPrimary.vue?vue&type=style&index=0&scoped=fcc59362&lang.scss"><link rel="stylesheet" href="/_nuxt/components/AppHeaderSubMenu.vue?vue&type=style&index=0&lang.scss"><script> window.__NUXT_DEVTOOLS_TIME_METRIC__ = window.__NUXT_DEVTOOLS_TIME_METRIC__ || {} window.__NUXT_DEVTOOLS_TIME_METRIC__.appInit = Date.now() </script></head> <body ><div id="__nuxt"><div data-v-inspector="app.vue:2:3"><div data-v-inspector="layouts/default.vue:2:5"><div data-v-inspector="components/AppHeader.vue:2:5"><header class="app-header" data-v-inspector="components/AppHeader.vue:3:9"><img src="/_nuxt/assets/img/kd_logo.png" alt="Knox Discuss Logo" class="logo" data-v-inspector="components/AppHeader.vue:4:13"><button class="login-btn" data-v-inspector="components/AppHeader.vue:5:13"><span></span><span data-v-inspector="components/AppHeader.vue:7:17">Login / Register</span></button></header><!----></div><div class="menu-bar" data-v-inspector="components/AppHeaderSubMenu.vue:2:5"><a class="menu-bar__link" href="#" data-v-inspector="components/AppHeaderSubMenu.vue:3:9"><span></span> Live Feed </a><a class="menu-bar__link" href="#" data-v-inspector="components/AppHeaderSubMenu.vue:9:9"><span></span> Channels </a><a class="menu-bar__link" href="#" data-v-inspector="components/AppHeaderSubMenu.vue:15:9"><span></span> Trending </a></div><!--[--> hi <!--]--></div></div></div><script type="application/json" id="__NUXT_DATA__" data-ssr="true">[["Reactive",1],{"data":2,"state":3,"_errors":6,"serverRendered":7,"path":8,"pinia":9},{},{"$s__nuxt_devtools__":4},{"timeSsrStart":5},1689438997965,{},true,"/api/auth/exists/email",{"modal":10},{"authModalIsOpen":11},["EmptyRef",12],"false"]</script><script>window.__NUXT__={};window.__NUXT__.config={public:{},app:{baseURL:"/",buildAssetsDir:"/_nuxt/",cdnURL:""}}</script><script type="module" src="/_nuxt/@vite/client" crossorigin></script><script type="module" src="/_nuxt/Users/hayden/Desktop/k_discuss/node_modules/nuxt/dist/app/entry.js" crossorigin></script></body> </html>
后端API代码(server/api/auth.ts)
router.get('/exists/email', defineEventHandler(event => { try{ const queryParams = getQuery(event); /* if(!queryParams['email_address']){ throw new ResponseError({ status_code: 422, short_msg: 'ERR_MISSING_INFO', body: { message: 'Missing email.' } }); } const { data } = await $fetch(`${accountAPIUri}/auth/exists/username`, { query: { email_address: queryParams['email_address'] }, onResponseError({error}) { console.error(error); }, }); console.log(data.value); */ return { data: 1234 }; }catch(e) { return ResponseError.respondWithError(e); } })) export default useBase('/api/auth', router.handler);
错误原因及解决方案
错误点
前端useFetch配置中错误设置了baseURL参数:
baseURL: '/api/auth/exists/email',
useFetch的第一个参数是相对baseURL的路径,当你同时传入baseURL和路径参数时,最终请求的URL会是baseURL + 第一个参数,也就是:/api/auth/exists/email/api/auth/exists/email
这个不存在的URL会被Nuxt的路由系统捕获,返回前端应用的HTML页面,而不是命中你的API接口。
修正后的前端代码
删除错误的baseURL配置即可(Nuxt会自动处理API路由的基础路径):
const { data } = await useFetch('/api/auth/exists/email', { query: { email_address: enteredEmail.value }, onResponseError: ({error}) => { console.error(error); registrationErrors.email.push('An unexpected error has occurred.') } });
或者如果你需要设置baseURL(比如统一API前缀),应该将其设为基础路径,而非完整接口路径:
const { data } = await useFetch('/exists/email', { query: { email_address: enteredEmail.value }, baseURL: '/api/auth', // 这里设为基础前缀 onResponseError: ({error}) => { console.error(error); registrationErrors.email.push('An unexpected error has occurred.') } });
内容的提问来源于stack exchange,提问作者Hayden
相关产品推荐
相关产品推荐

