Date转字符串带多余引号致请求URL错误的问题排查
Date对象转字符串时被添加多余引号导致请求无效的问题
问题详情
- Date类型的
from和to参数转换为字符串后被错误添加多余引号,导致生成的请求URL无效。尝试过toJSON、toISOString、encodeURIComponent等转换函数均未解决。 - 项目使用基于ofetch封装的Nuxt自定义API(useAPI),业务代码如下:
const fromISO = encodeURIComponent(from.toISOString()) const toISO = encodeURIComponent(to.toISOString()) const { data, error } = await useAPI<RateResponse>(`/users/${userId}/projects/${projectId}/rates`, { query: { from: fromISO, to: toISO } })
- 正确的请求URL(Swagger生成):
https://example.com/users/4/projects/17/rates?from=2024-10-24T16%3A45%3A00.000Z&to=2024-10-24T17%3A45%3A00.000Z
- 实际生成的错误URL(引号被编码为
%22):
https://example.com/users/4/projects/17/rates?from=%222024-10-24T16:45:00.000Z%22&to=%222024-10-24T17:00:00.000Z%22
- useAPI封装代码(useApi.ts):
import type { UseFetchOptions } from 'nuxt/app' export function useAPI<T>(url: string | (() => string),options?:UseFetchOptions<T>) { return useFetch(url, { ...options, $fetch: useNuxtApp().$api }) }
- $api实例定义代码:
export default defineNuxtPlugin(nuxtApp => { const loginStore = useLoginStore() const api = $fetch.create({ baseURL: useRuntimeConfig().public.apiUrl, retryStatusCodes: [401], retry: 1, retryDelay: 500, onRequest({ request, options, error }) { if (loginStore?.token) { const headers = options.headers || {} if (Array.isArray(headers)) { headers.push(['Authorization', `Bearer ${loginStore.token}`]) } else if (headers instanceof Headers) { headers.set('Authorization', `Bearer ${loginStore.token}`) } console.log(request) } }, async onResponseError({ request, options, response }) { console.log(options) console.log(response) if (response.status === 401) { if (loginStore.refreshToken) { try { await loginStore.refreshExpiredToken() } catch { loginStore.logout() await nuxtApp.runWithContext(() => navigateTo('/login')) } } loginStore.logout() await nuxtApp.runWithContext(() => navigateTo('/login')) } } }) // Expose to useNuxtApp().$api return { provide: { api } } })
- API返回错误:参数
from无效,无法解析包含多余引号的日期时间字符串。
解决方法
1. 移除手动编码,直接传递原始ISO字符串
ofetch会自动对query参数进行URL编码,手动调用encodeURIComponent会导致双重编码,同时可能触发额外的字符串序列化逻辑(比如添加引号)。修改代码如下:
const { data, error } = await useAPI<RateResponse>(`/users/${userId}/projects/${projectId}/rates`, { query: { from: from.toISOString(), to: to.toISOString() } })
2. 检查全局序列化配置
确认Nuxt项目中是否存在全局的fetch配置,或是否有插件修改了query参数的序列化规则。比如检查nuxt.config.ts中的fetch选项,或是否自定义了ofetch的querySerializer。
3. 手动拼接URL(绕过框架自动处理)
如果上述方法无效,直接将参数拼接到URL中,完全控制生成逻辑:
const fromISO = from.toISOString() const toISO = to.toISOString() const requestUrl = `/users/${userId}/projects/${projectId}/rates?from=${encodeURIComponent(fromISO)}&to=${encodeURIComponent(toISO)}` const { data, error } = await useAPI<RateResponse>(requestUrl)
4. 调试参数来源
在$api的onRequest钩子中添加日志,检查传递的query参数是否已经带引号:
onRequest({ request, options, error }) { console.log('当前query参数:', options.query) // 打印参数确认是否已带引号 // 原逻辑... }
如果日志显示参数本身已包含引号,说明from和to的来源可能不是Date对象,而是被错误转成带引号的字符串,需要追溯参数的生成逻辑。
内容的提问来源于stack exchange,提问作者zmaten
相关产品推荐
相关产品推荐

