diff --git a/lib/fetch/index.js b/lib/fetch/index.js index 0b99d546380..4eafb2fee2d 100644 --- a/lib/fetch/index.js +++ b/lib/fetch/index.js @@ -36,7 +36,8 @@ const { isAborted, isErrorLike, fullyReadBody, - readableStreamClose + readableStreamClose, + isomorphicEncode } = require('./util') const { kState, kHeaders, kGuard, kRealm } = require('./symbols') const assert = require('assert') @@ -832,7 +833,7 @@ async function schemeFetch (fetchParams) { const body = bodyWithType[0] // 5. Let length be body’s length, serialized and isomorphic encoded. - const length = `${body.length}` + const length = isomorphicEncode(`${body.length}`) // 6. Let type be bodyWithType’s type if it is non-null; otherwise the empty byte sequence. const type = bodyWithType[1] ?? '' @@ -1303,8 +1304,7 @@ async function httpNetworkOrCacheFetch ( // 7. If contentLength is non-null, then set contentLengthHeaderValue to // contentLength, serialized and isomorphic encoded. if (contentLength != null) { - // TODO: isomorphic encoded - contentLengthHeaderValue = String(contentLength) + contentLengthHeaderValue = isomorphicEncode(`${contentLength}`) } // 8. If contentLengthHeaderValue is non-null, then append @@ -1327,8 +1327,7 @@ async function httpNetworkOrCacheFetch ( // `Referer`/httpRequest’s referrer, serialized and isomorphic encoded, // to httpRequest’s header list. if (httpRequest.referrer instanceof URL) { - // TODO: isomorphic encoded - httpRequest.headersList.append('referer', httpRequest.referrer.href) + httpRequest.headersList.append('referer', isomorphicEncode(httpRequest.referrer.href)) } // 12. Append a request `Origin` header for httpRequest. diff --git a/lib/fetch/response.js b/lib/fetch/response.js index f36e8406ad4..6ef9aa1c423 100644 --- a/lib/fetch/response.js +++ b/lib/fetch/response.js @@ -10,7 +10,8 @@ const { isAborted, isBlobLike, serializeJavascriptValueToJSONString, - isErrorLike + isErrorLike, + isomorphicEncode } = require('./util') const { redirectStatus, @@ -124,8 +125,7 @@ class Response { responseObject[kState].status = status // 6. Let value be parsedURL, serialized and isomorphic encoded. - // TODO: isomorphic encoded? - const value = parsedURL.toString() + const value = isomorphicEncode(URLSerializer(parsedURL)) // 7. Append `Location`/value to responseObject’s response’s header list. responseObject[kState].headersList.append('location', value) diff --git a/lib/fetch/util.js b/lib/fetch/util.js index c71ab16eec1..0ebc9d560c4 100644 --- a/lib/fetch/util.js +++ b/lib/fetch/util.js @@ -870,6 +870,22 @@ function readableStreamClose (controller) { } } +/** + * @see https://infra.spec.whatwg.org/#isomorphic-encode + * @param {string} input + */ +function isomorphicEncode (input) { + // 1. Assert: input contains no code points greater than U+00FF. + for (let i = 0; i < input.length; i++) { + assert(input.charCodeAt(i) <= 0xFF) + } + + // 2. Return a byte sequence whose length is equal to input’s code + // point length and whose bytes have the same values as the + // values of input’s code points, in the same order + return input +} + /** * Fetch supports node >= 16.8.0, but Object.hasOwn was added in v16.9.0. */ @@ -912,5 +928,6 @@ module.exports = { fullyReadBody, bytesMatch, isReadableStreamLike, - readableStreamClose + readableStreamClose, + isomorphicEncode }