diff --git a/src-web/components/responseViewers/MultipartViewer.tsx b/src-web/components/responseViewers/MultipartViewer.tsx new file mode 100644 index 00000000..38c873ae --- /dev/null +++ b/src-web/components/responseViewers/MultipartViewer.tsx @@ -0,0 +1,83 @@ +import { type MultipartPart, parseMultipart } from '@mjackson/multipart-parser'; +import type { HttpResponse } from '@yaakapp-internal/models'; +import { useState } from 'react'; +import { useResponseBodyBytes } from '../../hooks/useResponseBodyText'; +import { getMimeTypeFromContentType, languageFromContentType } from '../../lib/contentType'; +import { getContentTypeFromHeaders } from '../../lib/model_util'; +import { Editor } from '../core/Editor/LazyEditor'; +import { Icon } from '../core/Icon'; +import { TabContent, Tabs } from '../core/Tabs/Tabs'; +import { CsvViewerInner } from './CsvViewer'; +import { ImageViewer } from './ImageViewer'; + +interface Props { + response: HttpResponse; +} + +export function MultipartViewer({ response }: Props) { + const body = useResponseBodyBytes({ response }); + const [tab, setTab] = useState(); + + if (body.data == null) return null; + + const contentTypeHeader = getContentTypeFromHeaders(response.headers); + const boundary = contentTypeHeader?.split('boundary=')[1] ?? 'unknown'; + + const parsed = parseMultipart(body.data, { boundary }); + const parts = Array.from(parsed); + + return ( + ({ + label: part.name ?? '', + value: part.name ?? '', + rightSlot: + part.filename && part.headers.contentType.mediaType?.startsWith('image/') ? ( +
+ +
+ ) : part.filename ? ( + + ) : null, + }))} + > + {parts.map((part, i) => ( + + + + ))} +
+ ); +} + +function Part({ part }: { part: MultipartPart }) { + const contentType = part.headers.get('content-type'); + const mimeType = contentType == null ? null : getMimeTypeFromContentType(contentType).essence; + + if (mimeType?.match(/^image/i)) { + return ; + } + + if (mimeType?.match(/csv|tab-separated/i)) { + const content = new TextDecoder().decode(part.arrayBuffer); + return ; + } + + const content = new TextDecoder().decode(part.arrayBuffer); + const language = languageFromContentType(contentType, content); + return ; +}