mirror of
https://github.com/nuxt/nuxt.git
synced 2024-11-25 15:15:19 +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 { FetchError, FetchOptions } from 'ofetch'
|
||||||
import type { NitroFetchRequest, TypedInternalResponse, AvailableRouterMethod as _AvailableRouterMethod } from 'nitropack'
|
import type { NitroFetchRequest, TypedInternalResponse, AvailableRouterMethod as _AvailableRouterMethod } from 'nitropack'
|
||||||
import type { MaybeRef, Ref } from 'vue'
|
import type { MaybeRef, Ref } from 'vue'
|
||||||
import { computed, reactive, unref } from 'vue'
|
import { computed, reactive, toValue } from 'vue'
|
||||||
import { hash } from 'ohash'
|
import { hash } from 'ohash'
|
||||||
|
|
||||||
import { useRequestFetch } from './ssr'
|
import { useRequestFetch } from './ssr'
|
||||||
@ -86,10 +86,10 @@ export function useFetch<
|
|||||||
if (typeof r === 'function') {
|
if (typeof r === 'function') {
|
||||||
r = r()
|
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') {
|
if (!_key || typeof _key !== 'string') {
|
||||||
throw new TypeError('[nuxt] [useFetch] key must be a string: ' + _key)
|
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
|
// Use fetch with request context and headers for server direct API calls
|
||||||
if (import.meta.server && !opts.$fetch) {
|
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) {
|
if (isLocalFetch) {
|
||||||
_$fetch = useRequestFetch()
|
_$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
|
// @ts-expect-error we pass an extra argument with the resolved auto-key to prevent another from being injected
|
||||||
autoKey)
|
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']
|
prerendered: ['/specific-prerendered']
|
||||||
})))
|
})))
|
||||||
|
registerEndpoint('/api/test', defineEventHandler((event) => ({
|
||||||
|
method: event.method,
|
||||||
|
headers: Object.fromEntries(event.headers.entries())
|
||||||
|
})))
|
||||||
|
|
||||||
describe('app config', () => {
|
describe('app config', () => {
|
||||||
it('can be updated', () => {
|
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', () => {
|
describe('errors', () => {
|
||||||
it('createError', () => {
|
it('createError', () => {
|
||||||
expect(createError({ statusCode: 404 }).toJSON()).toMatchInlineSnapshot(`
|
expect(createError({ statusCode: 404 }).toJSON()).toMatchInlineSnapshot(`
|
||||||
|
Loading…
Reference in New Issue
Block a user