mirror of
https://github.com/awatertrevi/infisical.git
synced 2026-09-22 13:39:35 +00:00
Handle body
This commit is contained in:
@@ -24,20 +24,19 @@ export const HttpBaseEventSchema = z.object({
|
||||
timestamp: z.coerce.date(),
|
||||
requestId: z.string(),
|
||||
eventType: TerminalEventTypeSchema,
|
||||
headers: z.record(z.string(), z.array(z.string()))
|
||||
headers: z.record(z.string(), z.array(z.string())),
|
||||
body: z.string().optional()
|
||||
});
|
||||
|
||||
export const HttpRequestEventSchema = HttpBaseEventSchema.extend({
|
||||
eventType: z.literal(HttpEventTypeSchema.Values.request),
|
||||
method: z.string(),
|
||||
url: z.string()
|
||||
// TODO: optional for now
|
||||
});
|
||||
|
||||
export const HttpResponseEventSchema = HttpBaseEventSchema.extend({
|
||||
eventType: z.literal(HttpEventTypeSchema.Values.response),
|
||||
status: z.string()
|
||||
// TODO: optional for now
|
||||
});
|
||||
|
||||
export const HttpEventSchema = z.discriminatedUnion("eventType", [HttpRequestEventSchema, HttpResponseEventSchema]);
|
||||
|
||||
@@ -16,6 +16,45 @@ export const HttpEventView = ({ events }: Props) => {
|
||||
Record<string, { headers: boolean; body: boolean }>
|
||||
>({});
|
||||
|
||||
const getContentType = (headers: Record<string, string[]>): string | undefined => {
|
||||
const contentTypeKey = Object.keys(headers).find((key) => key.toLowerCase() === "content-type");
|
||||
return contentTypeKey ? headers[contentTypeKey]?.[0] : undefined;
|
||||
};
|
||||
|
||||
const decodeBase64Body = (body: string): string => {
|
||||
try {
|
||||
return atob(body);
|
||||
} catch {
|
||||
// If base64 decoding fails, return original body
|
||||
return body;
|
||||
}
|
||||
};
|
||||
|
||||
const parseBodyForSearch = (
|
||||
body: string | undefined,
|
||||
headers: Record<string, string[]>
|
||||
): string => {
|
||||
if (!body) return "";
|
||||
|
||||
// Decode base64 first
|
||||
const decodedBody = decodeBase64Body(body);
|
||||
|
||||
const contentType = getContentType(headers);
|
||||
const isJson = contentType?.toLowerCase().includes("application/json");
|
||||
|
||||
if (isJson) {
|
||||
try {
|
||||
const parsed = JSON.parse(decodedBody);
|
||||
return JSON.stringify(parsed);
|
||||
} catch {
|
||||
// If JSON parsing fails, fall back to decoded body
|
||||
return decodedBody;
|
||||
}
|
||||
}
|
||||
|
||||
return decodedBody;
|
||||
};
|
||||
|
||||
const filteredEvents = useMemo(
|
||||
() =>
|
||||
events.filter((event) => {
|
||||
@@ -23,6 +62,7 @@ export const HttpEventView = ({ events }: Props) => {
|
||||
if (!searchValue) return true;
|
||||
|
||||
if (event.eventType === "request") {
|
||||
const bodyForSearch = parseBodyForSearch(event.body, event.headers);
|
||||
return (
|
||||
event.method.toLowerCase().includes(searchValue) ||
|
||||
event.url.toLowerCase().includes(searchValue) ||
|
||||
@@ -30,7 +70,8 @@ export const HttpEventView = ({ events }: Props) => {
|
||||
Object.keys(event.headers).some((key) => key.toLowerCase().includes(searchValue)) ||
|
||||
Object.values(event.headers).some((values) =>
|
||||
values.some((value) => value.toLowerCase().includes(searchValue))
|
||||
)
|
||||
) ||
|
||||
bodyForSearch.toLowerCase().includes(searchValue)
|
||||
);
|
||||
}
|
||||
return (
|
||||
@@ -51,6 +92,31 @@ export const HttpEventView = ({ events }: Props) => {
|
||||
.join("\n");
|
||||
};
|
||||
|
||||
const formatBody = (body: string | undefined, headers: Record<string, string[]>): string => {
|
||||
if (!body) {
|
||||
return "";
|
||||
}
|
||||
|
||||
// Decode base64 first
|
||||
const decodedBody = decodeBase64Body(body);
|
||||
|
||||
const contentType = getContentType(headers);
|
||||
const isJson = contentType?.toLowerCase().includes("application/json");
|
||||
|
||||
if (isJson) {
|
||||
try {
|
||||
const parsed = JSON.parse(decodedBody);
|
||||
return JSON.stringify(parsed, null, 2);
|
||||
} catch {
|
||||
// If JSON parsing fails, return decoded body
|
||||
return decodedBody;
|
||||
}
|
||||
}
|
||||
|
||||
// For non-JSON content, return decoded body
|
||||
return decodedBody;
|
||||
};
|
||||
|
||||
const getKubectlCommand = (headers: Record<string, string[]>) => {
|
||||
const headerKey = Object.keys(headers).find((key) => key.toLowerCase() === "kubectl-command");
|
||||
return headerKey ? headers[headerKey]?.[0] : undefined;
|
||||
@@ -156,28 +222,29 @@ export const HttpEventView = ({ events }: Props) => {
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="mt-2 pt-2 border-t border-mineshaft-700">
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => toggleSection(eventKey, "body")}
|
||||
className="flex items-center gap-2 w-full text-left text-bunker-400 text-xs mb-1 hover:text-bunker-300 transition-colors"
|
||||
>
|
||||
<FontAwesomeIcon
|
||||
icon={isSectionExpanded(eventKey, "body") ? faChevronUp : faChevronDown}
|
||||
className="text-xs"
|
||||
/>
|
||||
<span>Body:</span>
|
||||
</button>
|
||||
{isSectionExpanded(eventKey, "body") && (
|
||||
<div className="font-mono whitespace-pre-wrap text-bunker-300 text-xs">
|
||||
<div className="text-bunker-500 italic">
|
||||
{isRequest
|
||||
? "Request body content will be displayed here when available."
|
||||
: "Response body content will be displayed here when available."}
|
||||
{isRequest && event.body && (
|
||||
<div className="mt-2 pt-2 border-t border-mineshaft-700">
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => toggleSection(eventKey, "body")}
|
||||
className="flex items-center gap-2 w-full text-left text-bunker-400 text-xs mb-1 hover:text-bunker-300 transition-colors"
|
||||
>
|
||||
<FontAwesomeIcon
|
||||
icon={isSectionExpanded(eventKey, "body") ? faChevronUp : faChevronDown}
|
||||
className="text-xs"
|
||||
/>
|
||||
<span>Body:</span>
|
||||
</button>
|
||||
{isSectionExpanded(eventKey, "body") && (
|
||||
<div className="font-mono whitespace-pre-wrap text-bunker-300 text-xs">
|
||||
<HighlightText
|
||||
text={formatBody(event.body, event.headers)}
|
||||
highlight={search}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user