Usage with MSW / patched fetch
meesvandongen opened this issue · 13 comments
Environment
Node
Reproduction
https://codesandbox.io/p/sandbox/stoic-https-6gjdtz?file=/index.js:14,16
import { setupServer } from "msw/node";
import { http, HttpResponse } from "msw";
import wretch from 'wretch'
import { ofetch, fetch, createFetch } from 'ofetch'
import got from 'got'
const server = setupServer(
http.get('https://example.com', () => {
return HttpResponse.text('1')
})
)
server.listen();
console.table([
['fetch', await globalThis.fetch('https://example.com').then(res => res.text()).then(res => res === '1')],
['ofetch fetch', await fetch('https://example.com').then(res => res.text()).then(res => res === '1')],
['ofetch createFetch', await createFetch()('https://example.com').then(res => res === '1')],
['ofetch', await ofetch('https://example.com').then(res => res === '1')],
['wretch', await wretch('https://example.com').get().text().then(res => res === '1')],
['got', await got.get('https://example.com').text().then(res => res === '1')],
])
Describe the bug
When other tools patch fetch, the global instance of ofetch will have the original fetch
instance. This will cause tools such as msw to not be able to intercept requests with ofetch. A workaround could be to only get the globalThis.fetch at request time if no other fetch is specified.
Additional context
Users can work around this at this time by using the createFetch
helper function.
Logs
No response
Thanks @meesvandongen for opening this issue, which is also a problem we have encountered. PooyaJaan @pi0 please let us know what is the best and efficient temporary solution to solve this problem until it is resolved? Should we use the createFetch
function?
For anyone coming here, I found a hacky and pretty bad but functional way to workaround this for now using the Proxy
constructor
function createMyFetch() {
const newFetch = createFetch({
fetch: globalThis.fetch,
Headers: globalThis.Headers,
});
return newFetch.create({
// ...default options
});
}
const original = createMyFetch();
export const http = new Proxy(original, {
apply(_, thisArg, argumentsList) {
return Reflect.apply(createMyFetch(), thisArg, argumentsList);
},
});
// Then in other file calling `http` will be intercepted but maintaining the same usage
http('https://jsonplaceholder.typicode.com/todos/1')
This will work with msw@2.0.8 and node@18.18.0. You can merge the arguments instead of creating a new stance every time, or creating one only on the first call, etc
Running into this issue as well, a fix or workaround for usage with msw
would be greatly appreciated.