-
Notifications
You must be signed in to change notification settings - Fork 28
Open
Labels
help wantedExtra attention is neededExtra attention is needed
Description
// https://fetch.spec.whatwg.org/#fetch-finale
function fetchFinale (fetchParams, response) {
// 1. Let timingInfo be fetchParams’s timing info.
let timingInfo = fetchParams.timingInfo
// 2. If response is not a network error and fetchParams’s request’s client is a secure context,
// then set timingInfo’s server-timing headers to the result of getting, decoding, and splitting
// `Server-Timing` from response’s internal response’s header list.
// TODO
// 3. Let processResponseEndOfBody be the following steps:
const processResponseEndOfBody = () => {
// 1. Let unsafeEndTime be the unsafe shared current time.
const unsafeEndTime = Date.now() // ?
// 2. If fetchParams’s request’s destination is "document", then set fetchParams’s controller’s
// full timing info to fetchParams’s timing info.
if (fetchParams.request.destination === 'document') {
fetchParams.controller.fullTimingInfo = timingInfo
}
// 3. Set fetchParams’s controller’s report timing steps to the following steps given a global object global:
fetchParams.controller.reportTimingSteps = () => {
// 1. If fetchParams’s request’s URL’s scheme is not an HTTP(S) scheme, then return.
if (fetchParams.request.url.protocol !== 'https:') {
return
}
// 2. Set timingInfo’s end time to the relative high resolution time given unsafeEndTime and global.
timingInfo.endTime = unsafeEndTime
// 3. Let cacheState be response’s cache state.
let cacheState = response.cacheState
// 4. Let bodyInfo be response’s body info.
const bodyInfo = response.bodyInfo
// 5. If response’s timing allow passed flag is not set, then set timingInfo to the result of creating an
// opaque timing info for timingInfo and set cacheState to the empty string.
if (!response.timingAllowPassed) {
timingInfo = createOpaqueTimingInfo(timingInfo)
cacheState = ''
}
// 6. Let responseStatus be 0.
let responseStatus = 0
// 7. If fetchParams’s request’s mode is not "navigate" or response’s has-cross-origin-redirects is false:
if (fetchParams.request.mode !== 'navigator' || !response.hasCrossOriginRedirects) {
// 1. Set responseStatus to response’s status.
responseStatus = response.status
// 2. Let mimeType be the result of extracting a MIME type from response’s header list.
const mimeType = extractMimeType(response.headersList)
// 3. If mimeType is not failure, then set bodyInfo’s content type to the result of minimizing a supported MIME type given mimeType.
if (mimeType !== 'failure') {
bodyInfo.contentType = minimizeSupportedMimeType(mimeType)
}
}
// 8. If fetchParams’s request’s initiator type is non-null, then mark resource timing given timingInfo,
// fetchParams’s request’s URL, fetchParams’s request’s initiator type, global, cacheState, bodyInfo,
// and responseStatus.
if (fetchParams.request.initiatorType != null) {
// TODO: update markresourcetiming
markResourceTiming(timingInfo, fetchParams.request.url.href, fetchParams.request.initiatorType, globalThis, cacheState, bodyInfo, responseStatus)
}
}
// 4. Let processResponseEndOfBodyTask be the following steps:
const processResponseEndOfBodyTask = () => {
// 1. Set fetchParams’s request’s done flag.
fetchParams.request.done = true
// 2. If fetchParams’s process response end-of-body is non-null, then run fetchParams’s process
// response end-of-body given response.
if (fetchParams.processResponseEndOfBody != null) {
queueMicrotask(() => fetchParams.processResponseEndOfBody(response))
}
// 3. If fetchParams’s request’s initiator type is non-null and fetchParams’s request’s client’s
// global object is fetchParams’s task destination, then run fetchParams’s controller’s report
// timing steps given fetchParams’s request’s client’s global object.
if (fetchParams.request.initiatorType != null) {
fetchParams.controller.reportTimingSteps()
}
}
// 5. Queue a fetch task to run processResponseEndOfBodyTask with fetchParams’s task destination
queueMicrotask(() => processResponseEndOfBodyTask())
}
// 4. If fetchParams’s process response is non-null, then queue a fetch task to run fetchParams’s
// process response given response, with fetchParams’s task destination.
if (fetchParams.processResponse != null) {
queueMicrotask(() => {
fetchParams.processResponse(response)
fetchParams.processResponse = null
})
}
// 5. Let internalResponse be response, if response is a network error; otherwise response’s internal response.
const internalResponse = response.type === 'error' ? response : (response.internalResponse ?? response)
// 6. If internalResponse’s body is null, then run processResponseEndOfBody.
// 7. Otherwise:
if (internalResponse.body == null) {
processResponseEndOfBody()
} else {
// mcollina: all the following steps of the specs are skipped.
// The internal transform stream is not needed.
// See https://github.com/nodejs/undici/pull/3093#issuecomment-2050198541
// 1. Let transformStream be a new TransformStream.
// 2. Let identityTransformAlgorithm be an algorithm which, given chunk, enqueues chunk in transformStream.
// 3. Set up transformStream with transformAlgorithm set to identityTransformAlgorithm and flushAlgorithm
// set to processResponseEndOfBody.
// 4. Set internalResponse’s body’s stream to the result of internalResponse’s body’s stream piped through transformStream.
finished(internalResponse.body.stream, () => {
processResponseEndOfBody()
})
}
}
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
help wantedExtra attention is neededExtra attention is needed