diff --git a/lib/web/fetch/index.js b/lib/web/fetch/index.js index 8b88904e9d5..e5b3998600c 100644 --- a/lib/web/fetch/index.js +++ b/lib/web/fetch/index.js @@ -439,6 +439,16 @@ function fetching ({ // extracted. assert(!request.body || request.body.stream) + // Populate request from client. + if (request.traversableForUserPrompts === 'client') { + request.traversableForUserPrompts = 'no-traversable' + + const globalObject = request.client?.globalObject + if (globalObject?.constructor?.name === 'Window' && globalObject.navigable != null) { + request.traversableForUserPrompts = globalObject.navigable.traversableNavigable + } + } + // 8. If request’s window is "client", then set request’s window to request’s // client, if request’s client’s global object is a Window object; otherwise // "no-window". diff --git a/lib/web/fetch/util.js b/lib/web/fetch/util.js index fe63cb3a9b0..8369114369c 100644 --- a/lib/web/fetch/util.js +++ b/lib/web/fetch/util.js @@ -1447,8 +1447,7 @@ function includesCredentials (url) { * @param {object|string} navigable */ function isTraversableNavigable (navigable) { - // TODO - return true + return navigable != null && navigable !== 'client' && navigable !== 'no-traversable' } class EnvironmentSettingsObjectBase { diff --git a/test/fetch/401-statuscode-no-infinite-loop.js b/test/fetch/401-statuscode-no-infinite-loop.js index 96611718036..fa357259d27 100644 --- a/test/fetch/401-statuscode-no-infinite-loop.js +++ b/test/fetch/401-statuscode-no-infinite-loop.js @@ -20,3 +20,26 @@ test('Receiving a 401 status code should not cause infinite retry loop', async ( const response = await fetch(`http://localhost:${server.address().port}`) assert.strictEqual(response.status, 401) }) + +test('Receiving a 401 status code should not fail for stream-backed request bodies', async (t) => { + const server = createServer({ joinDuplicateHeaders: true }, (req, res) => { + res.statusCode = 401 + res.end('Unauthorized') + }).listen(0) + + t.after(closeServerAsPromise(server)) + await once(server, 'listening') + + const response = await fetch(`http://localhost:${server.address().port}`, { + method: 'PUT', + duplex: 'half', + body: new ReadableStream({ + start (controller) { + controller.enqueue(Buffer.from('hello world')) + controller.close() + } + }) + }) + + assert.strictEqual(response.status, 401) +})