Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 | 4x 4x 4x 2x 2x 1x 1x 3x 4x 3x 2x 2x 2x 2x 2x 2x 2x 1x | import { SIGNALS_KEY } from '../../shared/const'
import { isSimpleMethod } from '../../shared/types'
import { TypedEnv } from '../types'
import { getAllowedOrigin } from '../urlMatching'
import { removeHeaderValue } from '../utils/headers'
import { fetchOrigin } from '../utils/origin'
import { copyRequest, setCorsHeadersForInstrumentation } from '../utils/request'
import { copyResponseWithNewHeaders } from '../utils/response'
export type HandleProtectedApiOptionsParams = {
request: Request
env: TypedEnv
}
export async function handleProtectedApiOptionsCall({
request,
env,
}: HandleProtectedApiOptionsParams): Promise<Response> {
// Check if the OPTIONS request was caused by the addition
// of the signals header to the instrumented request
const accessControlRequestHeaders = request.headers.get('Access-Control-Request-Headers')
const accessControlRequestMethod = request.headers.get('Access-Control-Request-Method')
if (
accessControlRequestHeaders === SIGNALS_KEY &&
accessControlRequestMethod &&
isSimpleMethod(accessControlRequestMethod)
) {
const allowedOrigin = getAllowedOrigin(request, env)
if (allowedOrigin) {
// This state implies that the cross-origin request would have been a simple request
// if not for the inclusion of the signals in the request headers. As
// a result, the worker needs to handle this request because the origin is not
// guaranteed to handle it.
console.debug('Handled instrumentation-triggered preflight request without forwarding to origin')
return new Response(null, {
status: 204,
headers: {
'Access-Control-Allow-Origin': allowedOrigin,
'Access-Control-Allow-Headers': SIGNALS_KEY,
'Access-Control-Allow-Methods': accessControlRequestMethod,
'Access-Control-Allow-Credentials': 'true',
},
})
}
// Reaching this point indicates that the worker received a request that
// appears to have been generated by an instrumentation page. However, the
// origin of the request is not one of the configured identification pages.
//
// This likely indicates an issue with the setup such as a different Flow
// worker instance instrumenting a page that calls a protected API handled
// by this Flow worker.
//
// Attempt to fail gracefully and let the origin handle this error case.
}
const accessControlRequestHeadersValues = accessControlRequestHeaders
? accessControlRequestHeaders.split(',').map((s) => s.trim())
: []
if (accessControlRequestHeadersValues.includes(SIGNALS_KEY)) {
// The SIGNALS_KEY needs to be removed from the forwarded request to
// avoid unexpected results from the origin.
const originRequestHeaders = new Headers(request.headers)
removeHeaderValue(originRequestHeaders, 'Access-Control-Request-Headers', SIGNALS_KEY)
const originRequest = copyRequest({
request,
init: {
headers: originRequestHeaders,
},
})
const originResponse = await fetchOrigin(originRequest)
const originResponseHeaders = new Headers(originResponse.headers)
setCorsHeadersForInstrumentation(request, originResponseHeaders)
return copyResponseWithNewHeaders(originResponse, originResponseHeaders)
}
// The OPTIONS request matches a protected API but the request is not being
// instrumented so forward the OPTIONS request to the origin. Protection
// logic will be applied to the actual request
return fetchOrigin(request)
}
|