-
Notifications
You must be signed in to change notification settings - Fork 1.2k
fix(miniflare): prevent fetch failed on POST 401 responses #13328
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| --- | ||
| "miniflare": patch | ||
| --- | ||
|
|
||
| fix(miniflare): prevent fetch failed on POST 401 responses | ||
|
|
||
| Set `credentials: "omit"` in miniflare's fetch wrapper to bypass undici's HTTP 401 authentication retry logic. Workerd uses streamed request bodies where `body.source` is null, causing undici to throw "expected non-null body source" on POST 401 responses. | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -83,6 +83,15 @@ export async function fetch( | |
|
|
||
| const response = await undici.fetch(request, { | ||
| dispatcher: requestInit?.dispatcher, | ||
| // Prevent undici's HTTP 401 authentication retry logic from triggering. | ||
| // When a POST request with a streamed body (body.source === null) receives | ||
| // a 401, undici tries to re-extract the request body for re-sending with | ||
| // credentials, but fails with "expected non-null body source" because | ||
| // workerd uses streamed bodies. Setting credentials to "omit" bypasses | ||
| // the 401 handling entirely (Fetch spec §4.4 step 14). This is safe | ||
| // because miniflare dispatches to workerd directly — there is no HTTP | ||
| // authentication to retry. | ||
| credentials: "omit", | ||
|
devin-ai-integration[bot] marked this conversation as resolved.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This change makes value.outboundService = (req) => fetch(req, { dispatcher: fetchMock });While likely harmless (miniflare has no credential store), this is a broader behavioral change than the PR description suggests. Worth noting explicitly. Also, this fix is redundant with the existing undici patch at |
||
| }); | ||
| return new Response(response.body, response); | ||
| } | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -2707,6 +2707,14 @@ export class Miniflare { | |
|
|
||
| const forwardInit = forward as RequestInit; | ||
| forwardInit.dispatcher = dispatcher; | ||
| // Omit credentials to prevent undici's HTTP 401 authentication retry | ||
| // logic from triggering. When a POST request with a streamed body | ||
| // receives a 401, undici tries to re-extract the body source for | ||
| // credential re-authentication. Since workerd uses streamed bodies | ||
| // (body.source === null), this causes a "fetch failed" network error | ||
| // with "expected non-null body source". Setting credentials to "omit" | ||
| // bypasses the 401 handling entirely (see Fetch spec step 14). | ||
| forwardInit.credentials = "omit"; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is redundant with the
Both set |
||
| const response = await fetch(url, forwardInit); | ||
|
|
||
| // If the Worker threw an uncaught exception, propagate it to the caller | ||
|
|
||
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.
Minor: per
.changeset/README.md, the body should explain "the reason for the change and anything notable about the approach" in a way useful for changelog readers. Consider simplifying to focus on user-facing impact: