diff --git a/packages/core/useFetch/index.test.ts b/packages/core/useFetch/index.test.ts index 920b8b6f5fb..cc05a41abff 100644 --- a/packages/core/useFetch/index.test.ts +++ b/packages/core/useFetch/index.test.ts @@ -127,20 +127,25 @@ describe('useFetch', () => { }) test('should create an instance of useFetch with baseUrls', async () => { + const baseUrl = 'https://example.com' + const targetUrl = `${baseUrl}/test` const fetchHeaders = { Authorization: 'test' } const requestHeaders = { 'Accept-Language': 'en-US' } const allHeaders = { ...fetchHeaders, ...requestHeaders } - const useMyFetchWithBaseUrl = createFetch({ baseUrl: 'https://example.com', fetchOptions: { headers: fetchHeaders } }) + const requestOptions = { headers: requestHeaders } + const useMyFetchWithBaseUrl = createFetch({ baseUrl, fetchOptions: { headers: fetchHeaders } }) const useMyFetchWithoutBaseUrl = createFetch({ fetchOptions: { headers: fetchHeaders } }) - useMyFetchWithBaseUrl('test', { headers: requestHeaders }) - useMyFetchWithBaseUrl('/test', { headers: requestHeaders }) - useMyFetchWithoutBaseUrl('https://example.com/test', { headers: requestHeaders }) + + useMyFetchWithBaseUrl('test', requestOptions) + useMyFetchWithBaseUrl('/test', requestOptions) + useMyFetchWithBaseUrl(targetUrl, requestOptions) + useMyFetchWithoutBaseUrl(targetUrl, requestOptions) await retry(() => { - expect(fetchSpy).toHaveBeenCalledTimes(3) - expect(fetchSpy).toHaveBeenNthCalledWith(1, 'https://example.com/test', expect.anything()) - expect(fetchSpy).toHaveBeenNthCalledWith(2, 'https://example.com/test', expect.anything()) - expect(fetchSpy).toHaveBeenNthCalledWith(3, 'https://example.com/test', expect.anything()) + expect(fetchSpy).toHaveBeenCalledTimes(4) + new Array(4).fill(0).forEach((x, i) => { + expect(fetchSpy).toHaveBeenNthCalledWith(i + 1, 'https://example.com/test', expect.anything()) + }) expect(fetchSpyHeaders()).toMatchObject(allHeaders) }) }) diff --git a/packages/core/useFetch/index.ts b/packages/core/useFetch/index.ts index 5cabeef2fbb..c5d864c920c 100644 --- a/packages/core/useFetch/index.ts +++ b/packages/core/useFetch/index.ts @@ -184,7 +184,7 @@ export interface UseFetchOptions { export interface CreateFetchOptions { /** - * The base URL that will be prefixed to all urls + * The base URL that will be prefixed to all urls unless urls are absolute */ baseUrl?: MaybeComputedRef @@ -215,6 +215,11 @@ function isFetchOptions(obj: object): obj is UseFetchOptions { return containsProp(obj, 'immediate', 'refetch', 'initialData', 'timeout', 'beforeFetch', 'afterFetch', 'onFetchError', 'fetch') } +// A URL is considered absolute if it begins with "://" or "//" (protocol-relative URL). +function isAbsoluteURL(url: string) { + return /^([a-z][a-z\d+\-.]*:)?\/\//i.test(url) +} + function headersToObject(headers: HeadersInit | undefined) { if (typeof Headers !== 'undefined' && headers instanceof Headers) return Object.fromEntries([...headers.entries()]) @@ -249,10 +254,14 @@ export function createFetch(config: CreateFetchOptions = {}) { const _fetchOptions = config.fetchOptions || {} function useFactoryFetch(url: MaybeComputedRef, ...args: any[]) { - const computedUrl = computed(() => config.baseUrl - ? joinPaths(resolveUnref(config.baseUrl), resolveUnref(url)) - : resolveUnref(url), - ) + const computedUrl = computed(() => { + const baseUrl = resolveUnref(config.baseUrl) + const targetUrl = resolveUnref(url) + + return baseUrl && !isAbsoluteURL(targetUrl) + ? joinPaths(baseUrl, targetUrl) + : targetUrl + }) let options = _options let fetchOptions = _fetchOptions