typescriptvue.jsnuxt.js

Extra quotes when converting Date to string for fetching request


My Date objects from and to are incorrectly encoded with extra quotes which results in bad request URL. I've tried multiple functions to convert the Date to string (toJSON, toISOString, encodeURIComponent) but nothing has worked so far. For the fetching itself I am using Nuxt's fetching API which is a wrapper around ofetch:

  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 }
  })

This is the successful URL I get from swagger:

https://example.com/users/4/projects/17/rates?from=2024-10-24T16%3A45%3A00.000Z&to=2024-10-24T17%3A45%3A00.000Z

and this is the one from the app:

https://example.com/users/4/projects/17/rates?from=%222024-10-24T16:45:00.000Z%22&to=%222024-10-24T17:00:00.000Z%22

Here is the 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
  })
}

and here the $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
    }
  }
})

And here is the error I get back from API which shows the extra quotation marks: enter image description here


Solution

  • More of a workaround than a proper solution to my problem, but when I use the parameters in the URL directly instead of in the query argument it works as expected:

      const fromISO = from.toISOString()
      const toISO = to.toISOString()    
    
      const { data, error } = await useAPI<RateResponse>(
        `/users/${userId}/projects/${projectId}/rates?from=${fromISO}&to=${toISO}`)