mswjs / interceptors

Low-level network interception library.
https://npm.im/@mswjs/interceptors
MIT License
527 stars 119 forks source link

Support aborting intercepted requests #520

Open imewish opened 4 months ago

imewish commented 4 months ago

Hello,

Can a timeout be added to the requests on the interceptor?

The goal is to add a timeout for any intercepted request and modify the request.

kettanaito commented 4 months ago

Hi, @imewish. Can you give me an example of what you'd use that timeout for? To cancel a request, I presume? Would love to learn more.

imewish commented 4 months ago

Hey @kettanaito , yes I would like to cancel a request if it's taking more than X Milliseconds. Similar to the timeout specified in AXIOS.

kettanaito commented 4 months ago

This is something I'd love to add too. This is the API I was thinking about, what's your opinion on it?

interceptor.on('request', ({ request, abortController }) => {
  // Abort this intercepted request if it's taking more than 1s.
  setTimeout(() => abortController.abort(), 1000)
})

The problem with this requirement is this: what defines the "taking more than X"? Is it X amount of time as the request is being sent? Before the first byte of the response is received? Before the entire response is received (cannot really cancel afterward)?

Let me know how you'd expect this to behave.

imewish commented 4 months ago

Hey @kettanaito, this looks good. So ideally one should be able to cancel any requests in both cases you mentioned. for eg, if the client was not able to make the network connection to the target domain, we should be able to cancel it instead of hanging forever. Also if the connection was made successfully and the response is taking too much of time we should be able to cancel it as well. Im not sure if this is handled differently in the case of fetch when a user specifies the timeout params.

kettanaito commented 4 months ago

eg, if the client was not able to make the network connection to the target domain

If you don't respond with a mock, the request will happen as-is. The connection shouldn't hang in either case.

Also if the connection was made successfully and the response is taking too much of time we should be able to cancel it as well.

My main question is: how do you describe this in the listener? You don't know which stage of the resolution the request is. The listener is called as soon as the request headers are sent. So you can abort while the request body is streaming, once it's done streaming, once it's waiting for the response. The problem is, you cannot differentiate between any of those in the listener because there's no way of knowing that.

Do you see my concern here? For you, the user of the library, it's a bad experience.

imewish commented 4 months ago

Yeah, I got your concern. So if we cannot differentiate b/w request and response timeout, a generic implementation like you have mentioned here https://github.com/mswjs/interceptors/issues/520#issuecomment-2002618245 should be ok.

So the main use case for me here is we want to abort all the HTTP calls that takes more than X ms, that are used in the code behind our APIs, the API calls we make using axios or fetch, we can set our own timeout config with axios/fetch instances. But, the calls are made behind the scenes of other libraries/SDKs we don't have control. When we were experiencing high latencies in our APIs, and had no clue what was causing the delay, using this library I was able to trace most of the calls made by these libraries. So this thought came in, if we can trace/log these calls, adding timeout/abort config to it will be very useful.