-
-
Notifications
You must be signed in to change notification settings - Fork 517
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
fix: add guard for missing context requests #2054
Conversation
Remove non-null assertion when retrieving a request from context, as bypassed and passthrough requests aren't added to context and need to be handled. Update response:bypass type to allow for undefined request prop. fix mswjs#2053
@@ -48,7 +48,7 @@ export type LifeCycleEventsMap = { | |||
'response:bypass': [ | |||
args: { | |||
response: Response | |||
request: Request | |||
request: Request | undefined |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If that's the case, it's a bug. We shouldn't accommodate it. I will look into this once I have a moment. Thanks for bringing this to my attention!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi,
What do we do until you fix this bug. Should we roll back to an older version?
I am on v2.2.2
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ymarios-int this is a comment chain for a line of code. You can ask this on the issue or commit. I am not sure when or if this was introduced. So you can look at the history to see what may have happened. It's only been a few days so I would just wait a bit. you can subscribe to the issue,
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@ymarios-int looks to have been introduced in 2.1.5 so I just downgraded to "msw": "2.1.4" for now. I am not sure if there will be other issue but I figured I'll share.
It was fixing a pretty important fixme it seems
const { requestId } = responseJson | ||
const request = context.requests.get(requestId)! | ||
const request = context.requests.get(requestId) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The "non null assertion" going is definitely the right call. it does need to be handled.
I also ran into this issue :) Seems like this would fix it |
This is interesting. So the issue is when the response listener is called by the worker on bypassed request, right? This needs an extremely careful examination, we don't want to jump to the wrong conclusion and introduce a wrong fix. |
Here's what I think happens now to a bypassed request (can be wrong, feel free to correct):
The resolution then happens after:
At this point, The bypassing logic itself lives in msw/src/core/utils/handleRequest.ts Lines 55 to 60 in b3e47f7
However, I can see that the worker has its own logical branch for bypassing requests, and in that case it won't even send the REQUEST message to the client: Lines 205 to 210 in b3e47f7
I'm trying to remember why this duplication is necessary and my hunch tells me that What happens next is that the worker receives the original response and proceeds to message the client with the RESPONSE event: Line 116 in b3e47f7
Lines 125 to 140 in b3e47f7
While this message will contain the This means that bypassed requests cannot be persisted in the context while it's promised in the contract that even original responses will have the
The thing is, the worker doesn't know what's in the context. This suggestion would imply to always send the request alongside the RESPONSE event, which can be an overkill for the cases when the request has been stored in the context. Besides, we'd have to clone the request once in order to preserve its body so it'd be transferable in the RESPONSE event too. I'm considering the change that all requests trigger the REQUEST event and the request listener, and then we decide whether to go into the request resolution or not, or let this handle the bypassed requests also to stay consistent across environments: msw/src/core/utils/handleRequest.ts Lines 55 to 60 in b3e47f7
This proposal has an implication of involving an additional message roundtrip:
Even with this considered, I think I like for the worker to consistently send REQUEST/RESPONSE events to the client, no matter the request type (bypassed/mocked). The worker should really only be used as the interception mechanism, with no logic that affects the request resolution. If we make it this way, it's precisely what it'll become. The surface that decides what to do with the request will always be the client, and it's the client's responsibility to take bypassed requests into account and send the worker the right instruction message on how to proceed. @thepassle @mattcosta7, what do you think about this, folks? |
ProposalBriefly summarizing my proposal from above. Step 0: Add a failing test for a bypassed requestWe need to catch this issue in an automated test before even considering a fix. It sounds like it's a straightforward issue to solve. Step 1: Remove the bypassed requests handling from the workerThis has to go: Lines 205 to 210 in b3e47f7
Step 2: Ensure that
|
That makes sense to me, I can take a bit of time later to understand this a bit deeper, but on the surface that sounds like a good path, and the consistency between request handling sounds better than having multiple paths to doing that |
This is correct and why I wanted to draw your attention to it. It felt like a larger decision needed to be made on whether the context should always contain bypassed requests - which would require a more extensive solution. |
This is what I understood as well and mentioned it in the original Issue tagged 👍 . Like you, I couldn't reason why that specific branch of logic was there and not in the dedicated request handlers.
Yes, this is what is causing the error to occur at the moment.
Much prefer this solution! |
Merged a few preliminary changes to make this one easier: Now we can move on with updating the worker script as I described above. @lisatassone, does this sound interesting to you? |
Released: v2.2.6 🎉This has been released in v2.2.6! Make sure to always update to the latest version ( Predictable release automation by @ossjs/release. |
Nice one! You got through these quickly :D Thanks for this. |
The current code for
createResponseListener
assumes therequest
is always present incontext
but whenbypass
andpassthrough
functions are used withfetch
, requests never get added to thecontext
. Example usage from the docs for a proxy request.This is the most straightforward fix that doesn't change the original logic, but something else may be desired if the intent of the code should be that those types of requests are added to context and handled specifically. Its unclear why they do not go through the normal flow if there are provisions to deal with these in
core/utils/handleRequest.ts
which is used increateRequestListener
.The tests are TypeScript. If the non-null assertion was not there, the type system would have demanded undefined be handled.
Further, to ensure the Response URL is always set as intended in
createResponseListener
, perhaps the original request can be passed explicitly to theRESPONSE
event to use when its not in context.