@@ -7,6 +7,7 @@ import { useLocation } from 'react-router-dom'
77import {
88 AUIApplicationBridgeLocation ,
99 AUIApplicationBridgeTheme ,
10+ createBridgeFetchResponse ,
1011 createBridgeLocation ,
1112 createBridgeTheme ,
1213} from './auiapplication-bridge'
@@ -104,18 +105,39 @@ const createApplicationDocument = (
104105 return headers;
105106 };
106107
107- const createBridgeResponse = (response) => ({
108- ok: response.ok,
109- status: response.status,
110- statusText: response.statusText,
111- url: response.url,
112- headers: {
113- get: (name) => response.headers[String(name).toLowerCase()] || null,
114- entries: () => Object.entries(response.headers),
115- },
116- text: () => Promise.resolve(response.body),
117- json: () => Promise.resolve(JSON.parse(response.body)),
118- });
108+ const createBodyBuffer = (body) => {
109+ if (ArrayBuffer.isView(body)) {
110+ return body.buffer.slice(body.byteOffset, body.byteOffset + body.byteLength);
111+ }
112+
113+ if (body && typeof body.byteLength === 'number') {
114+ return body.slice(0);
115+ }
116+
117+ return new TextEncoder().encode(String(body || '')).buffer;
118+ };
119+
120+ const createBridgeResponse = (response) => {
121+ const bodyBuffer = createBodyBuffer(response.body);
122+ const getHeader = (name) => response.headers[String(name).toLowerCase()] || null;
123+ const getBodyCopy = () => bodyBuffer.slice(0);
124+ const getBodyText = () => Promise.resolve(new TextDecoder().decode(getBodyCopy()));
125+
126+ return {
127+ ok: response.ok,
128+ status: response.status,
129+ statusText: response.statusText,
130+ url: response.url,
131+ headers: {
132+ get: getHeader,
133+ entries: () => Object.entries(response.headers),
134+ },
135+ text: getBodyText,
136+ json: () => getBodyText().then((body) => JSON.parse(body)),
137+ arrayBuffer: () => Promise.resolve(getBodyCopy()),
138+ blob: () => Promise.resolve(new Blob([getBodyCopy()], { type: getHeader('content-type') || '' })),
139+ };
140+ };
119141
120142 window.addEventListener('message', (event) => {
121143 const data = event.data || {};
@@ -293,37 +315,38 @@ export const AUIApplicationView: React.FC = () => {
293315 return
294316 }
295317
296- const postResponse = ( message : Record < string , unknown > ) => {
297- frameRef . current ?. contentWindow ?. postMessage (
298- {
299- source : AUI_APPLICATION_CONTENT_TYPE ,
300- requestId : data . requestId ,
301- ...message ,
302- } ,
303- '*' ,
304- )
318+ const postResponse = ( message : Record < string , unknown > , transfer ?: Transferable [ ] ) => {
319+ const targetWindow = frameRef . current ?. contentWindow
320+ const responseMessage = {
321+ source : AUI_APPLICATION_CONTENT_TYPE ,
322+ requestId : data . requestId ,
323+ ...message ,
324+ }
325+
326+ if ( ! targetWindow ) {
327+ return
328+ }
329+
330+ if ( transfer ?. length ) {
331+ targetWindow . postMessage ( responseMessage , '*' , transfer )
332+ return
333+ }
334+
335+ targetWindow . postMessage ( responseMessage , '*' )
305336 }
306337
307338 try {
308339 const requestUrl = getRepositoryRequestUrl ( repository . configuration . repositoryUrl , data . input )
309340 const response = await repository . fetch ( requestUrl , getBridgeRequestInit ( data . init ) )
310- const headers : Record < string , string > = { }
341+ const bridgeResponse = await createBridgeFetchResponse ( response )
311342
312- response . headers . forEach ( ( value , key ) => {
313- headers [ key . toLowerCase ( ) ] = value
314- } )
315-
316- postResponse ( {
317- type : 'fetch:success' ,
318- response : {
319- ok : response . ok ,
320- status : response . status ,
321- statusText : response . statusText ,
322- url : response . url ,
323- headers,
324- body : await response . text ( ) ,
343+ postResponse (
344+ {
345+ type : 'fetch:success' ,
346+ response : bridgeResponse ,
325347 } ,
326- } )
348+ [ bridgeResponse . body ] ,
349+ )
327350 } catch ( error ) {
328351 postResponse ( {
329352 type : 'fetch:error' ,
0 commit comments