Skip to content

Commit

Permalink
fetch: implement whatwg/fetch#1544 (nodejs#1780)
Browse files Browse the repository at this point in the history
* fetch: implement whatwg/fetch#1544

* add wpt

* chore: update url
  • Loading branch information
KhafraDev authored and crysmags committed Feb 27, 2024
1 parent 8c40426 commit ac88800
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 9 deletions.
26 changes: 17 additions & 9 deletions lib/fetch/index.js
Expand Up @@ -1135,12 +1135,12 @@ async function httpRedirectFetch (fetchParams, response) {
return makeNetworkError('URL scheme must be a HTTP(S) scheme')
}

// 7. If request’s redirect count is twenty, return a network error.
// 7. If request’s redirect count is 20, then return a network error.
if (request.redirectCount === 20) {
return makeNetworkError('redirect count exceeded')
}

// 8. Increase request’s redirect count by one.
// 8. Increase request’s redirect count by 1.
request.redirectCount += 1

// 9. If request’s mode is "cors", locationURL includes credentials, and
Expand Down Expand Up @@ -1195,36 +1195,44 @@ async function httpRedirectFetch (fetchParams, response) {
}
}

// 13. If request’s body is non-null, then set request’s body to the first return
// 13. If request’s current URL’s origin is not same origin with locationURL’s
// origin, then for each headerName of CORS non-wildcard request-header name,
// delete headerName from request’s header list.
if (!sameOrigin(requestCurrentURL(request), locationURL)) {
// https://fetch.spec.whatwg.org/#cors-non-wildcard-request-header-name
request.headersList.delete('authorization')
}

// 14. If request’s body is non-null, then set request’s body to the first return
// value of safely extracting request’s body’s source.
if (request.body != null) {
assert(request.body.source)
request.body = safelyExtractBody(request.body.source)[0]
}

// 14. Let timingInfo be fetchParams’s timing info.
// 15. Let timingInfo be fetchParams’s timing info.
const timingInfo = fetchParams.timingInfo

// 15. Set timingInfo’s redirect end time and post-redirect start time to the
// 16. Set timingInfo’s redirect end time and post-redirect start time to the
// coarsened shared current time given fetchParams’s cross-origin isolated
// capability.
timingInfo.redirectEndTime = timingInfo.postRedirectStartTime =
coarsenedSharedCurrentTime(fetchParams.crossOriginIsolatedCapability)

// 16. If timingInfo’s redirect start time is 0, then set timingInfo’s
// 17. If timingInfo’s redirect start time is 0, then set timingInfo’s
// redirect start time to timingInfo’s start time.
if (timingInfo.redirectStartTime === 0) {
timingInfo.redirectStartTime = timingInfo.startTime
}

// 17. Append locationURL to request’s URL list.
// 18. Append locationURL to request’s URL list.
request.urlList.push(locationURL)

// 18. Invoke set request’s referrer policy on redirect on request and
// 19. Invoke set request’s referrer policy on redirect on request and
// actualResponse.
setRequestReferrerPolicyOnRedirect(request, actualResponse)

// 19. Return the result of running main fetch given fetchParams and true.
// 20. Return the result of running main fetch given fetchParams and true.
return mainFetch(fetchParams, true)
}

Expand Down
22 changes: 22 additions & 0 deletions test/wpt/server/server.mjs
Expand Up @@ -294,6 +294,28 @@ const server = createServer(async (req, res) => {
res.end('not actually gzip')
break
}
case '/fetch/api/resources/dump-authorization-header.py': {
res.setHeader('Content-Type', 'text/html')
res.setHeader('Cache-Control', 'no-cache')

if (req.headers.origin) {
res.setHeader('Access-Control-Allow-Origin', req.headers.origin)
res.setHeader('Access-Control-Allow-Credentials', 'true')
} else {
res.setHeader('Access-Control-Allow-Origin', '*')
}

res.setHeader('Access-Control-Allow-Headers', 'Authorization')
res.statusCode = 200

if (req.headers.authorization) {
res.end(req.headers.authorization)
return
}

res.end('none')
break
}
default: {
res.statusCode = 200
res.end('body')
Expand Down
@@ -0,0 +1,26 @@
// META: global=window,worker
// META: script=/common/get-host-info.sub.js

const authorizationValue = "Basic " + btoa("user:pass");
async function getAuthorizationHeaderValue(url)
{
const headers = { "Authorization": authorizationValue};
const requestInit = {"headers": headers};
const response = await fetch(url, requestInit);
return response.text();
}

promise_test(async test => {
const result = await getAuthorizationHeaderValue("/fetch/api/resources/dump-authorization-header.py");
assert_equals(result, authorizationValue);
}, "getAuthorizationHeaderValue - no redirection");

promise_test(async test => {
const result = await getAuthorizationHeaderValue("/fetch/api/resources/redirect.py?location=" + encodeURIComponent("/fetch/api/resources/dump-authorization-header.py"));
assert_equals(result, authorizationValue);
}, "getAuthorizationHeaderValue - same origin redirection");

promise_test(async (test) => {
const result = await getAuthorizationHeaderValue(get_host_info().HTTP_REMOTE_ORIGIN + "/fetch/api/resources/redirect.py?allow_headers=Authorization&location=" + encodeURIComponent(get_host_info().HTTP_ORIGIN + "/fetch/api/resources/dump-authorization-header.py"));
assert_equals(result, "none");
}, "getAuthorizationHeaderValue - cross origin redirection");

0 comments on commit ac88800

Please sign in to comment.