Skip to content

Commit 7ae1779

Browse files
authoredApr 1, 2023
perf(fetch): use string comparisons for url schemes (#2038)
1 parent 9013a23 commit 7ae1779

File tree

2 files changed

+50
-12
lines changed

2 files changed

+50
-12
lines changed
 

‎lib/fetch/index.js

+9-9
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,10 @@ const {
3737
isErrorLike,
3838
fullyReadBody,
3939
readableStreamClose,
40-
isomorphicEncode
40+
isomorphicEncode,
41+
urlIsLocal,
42+
urlIsHttpHttpsScheme,
43+
urlHasHttpsScheme
4144
} = require('./util')
4245
const { kState, kHeaders, kGuard, kRealm, kHeadersCaseInsensitive } = require('./symbols')
4346
const assert = require('assert')
@@ -272,7 +275,7 @@ function finalizeAndReportTiming (response, initiatorType = 'other') {
272275
let cacheState = response.cacheState
273276

274277
// 6. If originalURL’s scheme is not an HTTP(S) scheme, then return.
275-
if (!/^https?:/.test(originalURL.protocol)) {
278+
if (!urlIsHttpHttpsScheme(originalURL)) {
276279
return
277280
}
278281

@@ -530,10 +533,7 @@ async function mainFetch (fetchParams, recursive = false) {
530533

531534
// 3. If request’s local-URLs-only flag is set and request’s current URL is
532535
// not local, then set response to a network error.
533-
if (
534-
request.localURLsOnly &&
535-
!/^(about|blob|data):/.test(requestCurrentURL(request).protocol)
536-
) {
536+
if (request.localURLsOnly && !urlIsLocal(requestCurrentURL(request))) {
537537
response = makeNetworkError('local URLs only')
538538
}
539539

@@ -623,7 +623,7 @@ async function mainFetch (fetchParams, recursive = false) {
623623
}
624624

625625
// request’s current URL’s scheme is not an HTTP(S) scheme
626-
if (!/^https?:/.test(requestCurrentURL(request).protocol)) {
626+
if (!urlIsHttpHttpsScheme(requestCurrentURL(request))) {
627627
// Return a network error.
628628
return makeNetworkError('URL scheme must be a HTTP(S) scheme')
629629
}
@@ -1130,7 +1130,7 @@ async function httpRedirectFetch (fetchParams, response) {
11301130

11311131
// 6. If locationURL’s scheme is not an HTTP(S) scheme, then return a network
11321132
// error.
1133-
if (!/^https?:/.test(locationURL.protocol)) {
1133+
if (!urlIsHttpHttpsScheme(locationURL)) {
11341134
return makeNetworkError('URL scheme must be a HTTP(S) scheme')
11351135
}
11361136

@@ -1399,7 +1399,7 @@ async function httpNetworkOrCacheFetch (
13991399
// header if httpRequest’s header list contains that header’s name.
14001400
// TODO: https://github.com/whatwg/fetch/issues/1285#issuecomment-896560129
14011401
if (!httpRequest.headersList.contains('accept-encoding')) {
1402-
if (/^https:/.test(requestCurrentURL(httpRequest).protocol)) {
1402+
if (urlHasHttpsScheme(requestCurrentURL(httpRequest))) {
14031403
httpRequest.headersList.append('accept-encoding', 'br, gzip, deflate')
14041404
} else {
14051405
httpRequest.headersList.append('accept-encoding', 'gzip, deflate')

‎lib/fetch/util.js

+41-3
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ function requestBadPort (request) {
6464

6565
// 2. If url’s scheme is an HTTP(S) scheme and url’s port is a bad port,
6666
// then return blocked.
67-
if (/^https?:/.test(url.protocol) && badPorts.includes(url.port)) {
67+
if (urlIsHttpHttpsScheme(url) && badPorts.includes(url.port)) {
6868
return 'blocked'
6969
}
7070

@@ -285,7 +285,7 @@ function appendRequestOriginHeader (request) {
285285
case 'strict-origin':
286286
case 'strict-origin-when-cross-origin':
287287
// If request’s origin is a tuple origin, its scheme is "https", and request’s current URL’s scheme is not "https", then set serializedOrigin to `null`.
288-
if (/^https:/.test(request.origin) && !/^https:/.test(requestCurrentURL(request))) {
288+
if (request.origin && urlHasHttpsScheme(request.origin) && !urlHasHttpsScheme(requestCurrentURL(request))) {
289289
serializedOrigin = null
290290
}
291291
break
@@ -944,6 +944,41 @@ async function readAllBytes (reader, successSteps, failureSteps) {
944944
}
945945
}
946946

947+
/**
948+
* @see https://fetch.spec.whatwg.org/#is-local
949+
* @param {URL} url
950+
*/
951+
function urlIsLocal (url) {
952+
assert('protocol' in url) // ensure it's a url object
953+
954+
const protocol = url.protocol
955+
956+
return protocol === 'about:' || protocol === 'blob:' || protocol === 'data:'
957+
}
958+
959+
/**
960+
* @param {string|URL} url
961+
*/
962+
function urlHasHttpsScheme (url) {
963+
if (typeof url === 'string') {
964+
return url.startsWith('https:')
965+
}
966+
967+
return url.protocol === 'https:'
968+
}
969+
970+
/**
971+
* @see https://fetch.spec.whatwg.org/#http-scheme
972+
* @param {URL} url
973+
*/
974+
function urlIsHttpHttpsScheme (url) {
975+
assert('protocol' in url) // ensure it's a url object
976+
977+
const protocol = url.protocol
978+
979+
return protocol === 'http:' || protocol === 'https:'
980+
}
981+
947982
/**
948983
* Fetch supports node >= 16.8.0, but Object.hasOwn was added in v16.9.0.
949984
*/
@@ -988,5 +1023,8 @@ module.exports = {
9881023
isReadableStreamLike,
9891024
readableStreamClose,
9901025
isomorphicEncode,
991-
isomorphicDecode
1026+
isomorphicDecode,
1027+
urlIsLocal,
1028+
urlHasHttpsScheme,
1029+
urlIsHttpHttpsScheme
9921030
}

0 commit comments

Comments
 (0)