@@ -5,6 +5,19 @@ import {
55} from '@microsoft/fetch-event-source'
66import { useRef , useCallback } from 'react'
77
8+ /**
9+ * Computes SHA256 hash of the request body for CloudFront + Lambda Function URL with OAC.
10+ * Required by AWS CloudFront when using Origin Access Control with Lambda Function URLs.
11+ * See: https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/private-content-restricting-access-to-lambda.html
12+ */
13+ async function computeSHA256 ( data : string ) : Promise < string > {
14+ const encoder = new TextEncoder ( )
15+ const dataBuffer = encoder . encode ( data )
16+ const hashBuffer = await crypto . subtle . digest ( 'SHA-256' , dataBuffer )
17+ const hashArray = Array . from ( new Uint8Array ( hashBuffer ) )
18+ return hashArray . map ( ( b ) => ( '0' + b . toString ( 16 ) ) . slice ( - 2 ) ) . join ( '' )
19+ }
20+
821// Simple wrapper interface around fetch-event-source
922export interface UseFetchEventSourceOptions {
1023 apiEndpoint : string
@@ -47,13 +60,21 @@ export function useFetchEventSource<TPayload>({
4760 abortControllerRef . current = controller
4861
4962 try {
63+ // Stringify payload once to ensure hash matches the exact body sent
64+ const bodyString = JSON . stringify ( payload )
65+
66+ // Compute SHA256 hash for CloudFront + Lambda Function URL with OAC
67+ // This proves body integrity from client to CloudFront
68+ const contentHash = await computeSHA256 ( bodyString )
69+
5070 await fetchEventSource ( apiEndpoint , {
5171 method : 'POST' ,
5272 headers : {
5373 'Content-Type' : 'application/json' ,
74+ 'x-amz-content-sha256' : contentHash , // Required for CloudFront OAC
5475 ...headers ,
5576 } ,
56- body : JSON . stringify ( payload ) ,
77+ body : bodyString ,
5778 signal : controller . signal , // Use local controller, not ref
5879 onopen : async ( response : Response ) => {
5980 if (
0 commit comments