mirror of
https://github.com/nuxt/nuxt.git
synced 2024-11-21 21:25:11 +00:00
fix(nuxt): deeply unwrap headers/query for useFetch
key (#24307)
This commit is contained in:
parent
6ec267be87
commit
562532778b
@ -1,7 +1,7 @@
|
||||
import type { FetchError, FetchOptions } from 'ofetch'
|
||||
import type { NitroFetchRequest, TypedInternalResponse, AvailableRouterMethod as _AvailableRouterMethod } from 'nitropack'
|
||||
import type { MaybeRef, Ref } from 'vue'
|
||||
import { computed, reactive, unref } from 'vue'
|
||||
import { computed, reactive, toValue } from 'vue'
|
||||
import { hash } from 'ohash'
|
||||
|
||||
import { useRequestFetch } from './ssr'
|
||||
@ -86,10 +86,10 @@ export function useFetch<
|
||||
if (typeof r === 'function') {
|
||||
r = r()
|
||||
}
|
||||
return unref(r)
|
||||
return toValue(r)
|
||||
})
|
||||
|
||||
const _key = opts.key || hash([autoKey, unref(opts.method as MaybeRef<string | undefined> | undefined)?.toUpperCase() || 'GET', unref(opts.baseURL), typeof _request.value === 'string' ? _request.value : '', unref(opts.params || opts.query), unref(opts.headers)])
|
||||
const _key = opts.key || hash([autoKey, typeof _request.value === 'string' ? _request.value : '', ...generateOptionSegments(opts)])
|
||||
if (!_key || typeof _key !== 'string') {
|
||||
throw new TypeError('[nuxt] [useFetch] key must be a string: ' + _key)
|
||||
}
|
||||
@ -144,7 +144,7 @@ export function useFetch<
|
||||
|
||||
// Use fetch with request context and headers for server direct API calls
|
||||
if (import.meta.server && !opts.$fetch) {
|
||||
const isLocalFetch = typeof _request.value === 'string' && _request.value.startsWith('/') && (!unref(opts.baseURL) || unref(opts.baseURL)!.startsWith('/'))
|
||||
const isLocalFetch = typeof _request.value === 'string' && _request.value.startsWith('/') && (!toValue(opts.baseURL) || toValue(opts.baseURL)!.startsWith('/'))
|
||||
if (isLocalFetch) {
|
||||
_$fetch = useRequestFetch()
|
||||
}
|
||||
@ -205,3 +205,22 @@ export function useLazyFetch<
|
||||
// @ts-expect-error we pass an extra argument with the resolved auto-key to prevent another from being injected
|
||||
autoKey)
|
||||
}
|
||||
|
||||
function generateOptionSegments <_ResT, DataT, DefaultT>(opts: UseFetchOptions<_ResT, DataT, any, DefaultT, any, any>) {
|
||||
const segments: Array<string | undefined | Record<string, string>> = [
|
||||
toValue(opts.method as MaybeRef<string | undefined> | undefined)?.toUpperCase() || 'GET',
|
||||
toValue(opts.baseURL),
|
||||
]
|
||||
for (const _obj of [opts.params || opts.query, opts.headers]) {
|
||||
const obj = toValue(_obj)
|
||||
if (!obj) { continue }
|
||||
|
||||
const unwrapped: Record<string, string> = {}
|
||||
const iterator = Array.isArray(obj) ? obj : obj instanceof Headers ? obj.entries() : Object.entries(obj)
|
||||
for (const [key, value] of iterator) {
|
||||
unwrapped[toValue(key)] = toValue(value)
|
||||
}
|
||||
segments.push(unwrapped)
|
||||
}
|
||||
return segments
|
||||
}
|
||||
|
@ -38,6 +38,10 @@ registerEndpoint('/_nuxt/builds/meta/override.json', defineEventHandler(() => ({
|
||||
},
|
||||
prerendered: ['/specific-prerendered']
|
||||
})))
|
||||
registerEndpoint('/api/test', defineEventHandler((event) => ({
|
||||
method: event.method,
|
||||
headers: Object.fromEntries(event.headers.entries())
|
||||
})))
|
||||
|
||||
describe('app config', () => {
|
||||
it('can be updated', () => {
|
||||
@ -237,6 +241,39 @@ describe('useAsyncData', () => {
|
||||
})
|
||||
})
|
||||
|
||||
describe('useFetch', () => {
|
||||
it('should match with/without computed values', async () => {
|
||||
const nuxtApp = useNuxtApp()
|
||||
const getPayloadEntries = () => Object.keys(nuxtApp.payload.data).length
|
||||
const baseCount = getPayloadEntries()
|
||||
|
||||
await useFetch('/api/test')
|
||||
expect(getPayloadEntries()).toBe(baseCount + 1)
|
||||
|
||||
/* @ts-expect-error Overriding auto-key */
|
||||
await useFetch('/api/test', { method: 'POST' }, '')
|
||||
/* @ts-expect-error Overriding auto-key */
|
||||
await useFetch('/api/test', { method: ref('POST') }, '')
|
||||
expect.soft(getPayloadEntries()).toBe(baseCount + 2)
|
||||
|
||||
/* @ts-expect-error Overriding auto-key */
|
||||
await useFetch('/api/test', { headers: { id: '3' } }, '')
|
||||
/* @ts-expect-error Overriding auto-key */
|
||||
await useFetch('/api/test', { headers: { id: ref('3') } }, '')
|
||||
const headers = new Headers()
|
||||
headers.append('id', '3')
|
||||
/* @ts-expect-error Overriding auto-key */
|
||||
await useFetch('/api/test', { headers }, '')
|
||||
/* @ts-expect-error Overriding auto-key */
|
||||
await useFetch('/api/test', { headers: [['id', '3']] }, '')
|
||||
/* @ts-expect-error Overriding auto-key */
|
||||
await useFetch('/api/test', { headers: [['id', ref('3')]] }, '')
|
||||
/* @ts-expect-error Overriding auto-key */
|
||||
await useFetch('/api/test', { headers: [[computed(() => 'id'), '3']] }, '')
|
||||
expect.soft(getPayloadEntries()).toBe(baseCount + 3)
|
||||
})
|
||||
})
|
||||
|
||||
describe('errors', () => {
|
||||
it('createError', () => {
|
||||
expect(createError({ statusCode: 404 }).toJSON()).toMatchInlineSnapshot(`
|
||||
|
Loading…
Reference in New Issue
Block a user