/** * Copyright (c) Microsoft Corporation. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import './networkResourceDetails.css'; import * as React from 'react'; import type { ResourceSnapshot } from '../../../server/snapshot/snapshotTypes'; import { Expandable } from '../../components/expandable'; export const NetworkResourceDetails: React.FunctionComponent<{ resource: ResourceSnapshot, index: number, selected: boolean, setSelected: React.Dispatch>, }> = ({ resource, index, selected, setSelected }) => { const [expanded, setExpanded] = React.useState(false); const [requestBody, setRequestBody] = React.useState(null); const [responseBody, setResponseBody] = React.useState<{ dataUrl?: string, text?: string } | null>(null); React.useEffect(() => { setExpanded(false); setSelected(-1); }, [resource, setSelected]); React.useEffect(() => { const readResources = async () => { if (resource.requestSha1) { const response = await fetch(`/sha1/${resource.requestSha1}`); const requestResource = await response.text(); setRequestBody(requestResource); } if (resource.responseSha1) { const useBase64 = resource.contentType.includes('image'); const response = await fetch(`/sha1/${resource.responseSha1}`); if (useBase64) { const blob = await response.blob(); const reader = new FileReader(); const eventPromise = new Promise(f => reader.onload = f); reader.readAsDataURL(blob); setResponseBody({ dataUrl: (await eventPromise).target.result }); } else { setResponseBody({ text: await response.text() }); } } }; readResources(); }, [expanded, resource.responseSha1, resource.requestSha1, resource.contentType]); function formatBody(body: string | null, contentType: string): string { if (body === null) return 'Loading...'; const bodyStr = body; if (bodyStr === '') return ''; if (contentType.includes('application/json')) { try { return JSON.stringify(JSON.parse(bodyStr), null, 2); } catch (err) { return bodyStr; } } if (contentType.includes('application/x-www-form-urlencoded')) return decodeURIComponent(bodyStr); return bodyStr; } function formatStatus(status: number): string { if (status >= 200 && status < 400) return 'status-success'; if (status >= 400) return 'status-failure'; return 'status-neutral'; } const requestContentTypeHeader = resource.requestHeaders.find(q => q.name === 'Content-Type'); const requestContentType = requestContentTypeHeader ? requestContentTypeHeader.value : ''; const resourceName = resource.url.substring(resource.url.lastIndexOf('/') + 1); return
setSelected(index)}>
{resource.status}
{resource.method}
{resourceName}
{resource.type}
} body={
URL
{resource.url}
Request Headers
{resource.requestHeaders.map(pair => `${pair.name}: ${pair.value}`).join('\n')}
Response Headers
{resource.responseHeaders.map(pair => `${pair.name}: ${pair.value}`).join('\n')}
{resource.requestSha1 ?
Request Body
: ''} {resource.requestSha1 ?
{formatBody(requestBody, requestContentType)}
: ''}
Response Body
{!resource.responseSha1 ?
Response body is not available for this request.
: ''} {responseBody !== null && responseBody.dataUrl ? : ''} {responseBody !== null && responseBody.text ?
{formatBody(responseBody.text, resource.contentType)}
: ''}
}/> ; };