Skip to content
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

fetch: implement https://github.com/whatwg/fetch/pull/1544 #1780

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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");