diff --git a/src-web/components/ConfirmLargeResponse.tsx b/src-web/components/ConfirmLargeResponse.tsx index e1d6fd55..973ed6e1 100644 --- a/src-web/components/ConfirmLargeResponse.tsx +++ b/src-web/components/ConfirmLargeResponse.tsx @@ -3,7 +3,7 @@ import { useMemo, type ReactNode } from 'react'; import { useSaveResponse } from '../hooks/useSaveResponse'; import { useToggle } from '../hooks/useToggle'; import { isProbablyTextContentType } from '../lib/contentType'; -import { getContentTypeHeader } from '../lib/model_util'; +import { getContentTypeFromHeaders } from '../lib/model_util'; import { getResponseBodyText } from '../lib/responseBody'; import { CopyButton } from './CopyButton'; import { Banner } from './core/Banner'; @@ -24,7 +24,7 @@ export function ConfirmLargeResponse({ children, response }: Props) { const { mutate: saveResponse } = useSaveResponse(response); const [showLargeResponse, toggleShowLargeResponse] = useToggle(); const isProbablyText = useMemo(() => { - const contentType = getContentTypeHeader(response.headers); + const contentType = getContentTypeFromHeaders(response.headers); return isProbablyTextContentType(contentType); }, [response.headers]); diff --git a/src-web/components/HttpRequestPane.tsx b/src-web/components/HttpRequestPane.tsx index f8a201dc..c578a579 100644 --- a/src-web/components/HttpRequestPane.tsx +++ b/src-web/components/HttpRequestPane.tsx @@ -7,7 +7,6 @@ import type { CSSProperties } from 'react'; import React, { useCallback, useMemo, useState } from 'react'; import { activeRequestIdAtom } from '../hooks/useActiveRequestId'; import { useCancelHttpResponse } from '../hooks/useCancelHttpResponse'; -import { useContentTypeFromHeaders } from '../hooks/useContentTypeFromHeaders'; import { grpcRequestsAtom } from '../hooks/useGrpcRequests'; import { useHttpAuthenticationSummaries } from '../hooks/useHttpAuthentication'; import { httpRequestsAtom } from '../hooks/useHttpRequests'; @@ -28,7 +27,7 @@ import { BODY_TYPE_JSON, BODY_TYPE_NONE, BODY_TYPE_OTHER, - BODY_TYPE_XML, + BODY_TYPE_XML, getContentTypeFromHeaders, } from '../lib/model_util'; import { prepareImportQuerystring } from '../lib/prepareImportQuerystring'; import { resolvedModelName } from '../lib/resolvedModelName'; @@ -84,7 +83,7 @@ export function HttpRequestPane({ style, fullHeight, className, activeRequest }: const [forceUpdateHeaderEditorKey, setForceUpdateHeaderEditorKey] = useState(0); const { updateKey: forceUpdateKey } = useRequestUpdateKey(activeRequest.id ?? null); const [{ urlKey }, { focusParamsTab, forceUrlRefresh, forceParamsRefresh }] = useRequestEditor(); - const contentType = useContentTypeFromHeaders(activeRequest.headers); + const contentType = getContentTypeFromHeaders(activeRequest.headers); const authentication = useHttpAuthenticationSummaries(); const handleContentTypeChange = useCallback( diff --git a/src-web/components/HttpResponsePane.tsx b/src-web/components/HttpResponsePane.tsx index 217b7244..8f9c3245 100644 --- a/src-web/components/HttpResponsePane.tsx +++ b/src-web/components/HttpResponsePane.tsx @@ -3,9 +3,9 @@ import classNames from 'classnames'; import type { CSSProperties, ReactNode } from 'react'; import React, { useCallback, useMemo } from 'react'; import { useLocalStorage } from 'react-use'; -import { useContentTypeFromHeaders } from '../hooks/useContentTypeFromHeaders'; import { usePinnedHttpResponse } from '../hooks/usePinnedHttpResponse'; import { useResponseViewMode } from '../hooks/useResponseViewMode'; +import { getContentTypeFromHeaders } from '../lib/model_util'; import { ConfirmLargeResponse } from './ConfirmLargeResponse'; import { Banner } from './core/Banner'; import { CountBadge } from './core/CountBadge'; @@ -47,7 +47,7 @@ export function HttpResponsePane({ style, className, activeRequestId }: Props) { 'responsePaneActiveTabs', {}, ); - const contentType = useContentTypeFromHeaders(activeResponse?.headers ?? null); + const contentType = getContentTypeFromHeaders(activeResponse?.headers ?? null); const tabs = useMemo( () => [ diff --git a/src-web/components/responseViewers/BinaryViewer.tsx b/src-web/components/responseViewers/BinaryViewer.tsx index 50cf269a..96aa4fe1 100644 --- a/src-web/components/responseViewers/BinaryViewer.tsx +++ b/src-web/components/responseViewers/BinaryViewer.tsx @@ -1,6 +1,6 @@ import type { HttpResponse } from '@yaakapp-internal/models'; import { useSaveResponse } from '../../hooks/useSaveResponse'; -import { getContentTypeHeader } from '../../lib/model_util'; +import { getContentTypeFromHeaders } from '../../lib/model_util'; import { Banner } from '../core/Banner'; import { Button } from '../core/Button'; import { InlineCode } from '../core/InlineCode'; @@ -13,7 +13,7 @@ interface Props { export function BinaryViewer({ response }: Props) { const saveResponse = useSaveResponse(response); - const contentType = getContentTypeHeader(response.headers) ?? 'unknown'; + const contentType = getContentTypeFromHeaders(response.headers) ?? 'unknown'; // Wait until the response has been fully-downloaded if (response.state === 'closed') { diff --git a/src-web/components/responseViewers/HTMLOrTextViewer.tsx b/src-web/components/responseViewers/HTMLOrTextViewer.tsx index 75a78ba9..b379f218 100644 --- a/src-web/components/responseViewers/HTMLOrTextViewer.tsx +++ b/src-web/components/responseViewers/HTMLOrTextViewer.tsx @@ -1,7 +1,7 @@ import type { HttpResponse } from '@yaakapp-internal/models'; -import { useContentTypeFromHeaders } from '../../hooks/useContentTypeFromHeaders'; import { useResponseBodyText } from '../../hooks/useResponseBodyText'; import { languageFromContentType } from '../../lib/contentType'; +import { getContentTypeFromHeaders } from '../../lib/model_util'; import { BinaryViewer } from './BinaryViewer'; import { TextViewer } from './TextViewer'; import { WebPageViewer } from './WebPageViewer'; @@ -14,10 +14,8 @@ interface Props { export function HTMLOrTextViewer({ response, pretty, textViewerClassName }: Props) { const rawTextBody = useResponseBodyText(response); - const language = languageFromContentType( - useContentTypeFromHeaders(response.headers), - rawTextBody.data ?? '', - ); + const contentType = getContentTypeFromHeaders(response.headers); + const language = languageFromContentType(contentType, rawTextBody.data ?? ''); if (rawTextBody.isLoading || response.state === 'initialized') { return null; diff --git a/src-web/hooks/useContentTypeFromHeaders.ts b/src-web/hooks/useContentTypeFromHeaders.ts deleted file mode 100644 index 1f7c500d..00000000 --- a/src-web/hooks/useContentTypeFromHeaders.ts +++ /dev/null @@ -1,9 +0,0 @@ -import type { HttpResponseHeader } from '@yaakapp-internal/models'; -import { useMemo } from 'react'; - -export function useContentTypeFromHeaders(headers: HttpResponseHeader[] | null): string | null { - return useMemo( - () => headers?.find((h) => h.name.toLowerCase() === 'content-type')?.value ?? null, - [headers], - ); -} diff --git a/src-web/hooks/useSaveResponse.tsx b/src-web/hooks/useSaveResponse.tsx index 8d6e41a2..8f54518a 100644 --- a/src-web/hooks/useSaveResponse.tsx +++ b/src-web/hooks/useSaveResponse.tsx @@ -3,7 +3,7 @@ import type { HttpResponse } from '@yaakapp-internal/models'; import mime from 'mime'; import slugify from 'slugify'; import { InlineCode } from '../components/core/InlineCode'; -import { getContentTypeHeader } from '../lib/model_util'; +import { getContentTypeFromHeaders } from '../lib/model_util'; import { invokeCmd } from '../lib/tauri'; import { showToast } from '../lib/toast'; import { useFastMutation } from './useFastMutation'; @@ -13,10 +13,10 @@ export function useSaveResponse(response: HttpResponse) { return useFastMutation({ mutationKey: ['save_response', response.id], mutationFn: async () => { - const request = await getHttpRequest(response.requestId); + const request = getHttpRequest(response.requestId); if (request == null) return null; - const contentType = getContentTypeHeader(response.headers) ?? 'unknown'; + const contentType = getContentTypeFromHeaders(response.headers) ?? 'unknown'; const ext = mime.getExtension(contentType); const slug = slugify(request.name || 'response', { lower: true }); const filepath = await save({ diff --git a/src-web/lib/model_util.ts b/src-web/lib/model_util.ts index fb82f210..b0cd59d8 100644 --- a/src-web/lib/model_util.ts +++ b/src-web/lib/model_util.ts @@ -36,12 +36,12 @@ export function modelsEq(a: AnyModel, b: AnyModel) { return false; } -export function getContentTypeHeader(headers: HttpResponseHeader[]): string | null { - return headers.find((h) => h.name.toLowerCase() === 'content-type')?.value ?? null; +export function getContentTypeFromHeaders(headers: HttpResponseHeader[] | null): string | null { + return headers?.find((h) => h.name.toLowerCase() === 'content-type')?.value ?? null; } export function getCharsetFromContentType(headers: HttpResponseHeader[]): string | null { - const contentType = getContentTypeHeader(headers); + const contentType = getContentTypeFromHeaders(headers); if (contentType == null) return null; const mimeType = getMimeTypeFromContentType(contentType);