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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 16:50:56