Skip to content

Commit

Permalink
feat(useFetch): support sending the custom request to an absolute URL…
Browse files Browse the repository at this point in the history
… regardless baseURL (#2210)
  • Loading branch information
sun0day committed Nov 9, 2022
1 parent ab0eea2 commit 934a893
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 13 deletions.
21 changes: 13 additions & 8 deletions packages/core/useFetch/index.test.ts
Expand Up @@ -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)
})
})
Expand Down
19 changes: 14 additions & 5 deletions packages/core/useFetch/index.ts
Expand Up @@ -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<string>

Expand Down Expand Up @@ -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 "<scheme>://" 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()])
Expand Down Expand Up @@ -249,10 +254,14 @@ export function createFetch(config: CreateFetchOptions = {}) {
const _fetchOptions = config.fetchOptions || {}

function useFactoryFetch(url: MaybeComputedRef<string>, ...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
Expand Down

0 comments on commit 934a893

Please sign in to comment.