Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: html error formatting MAASENG-2935 #5405

Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions src/app/utils/formatErrors.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,4 +51,23 @@ describe("formatErrors", () => {
"The primary rack controller must be up and running to set a secondary rack controller."
);
});

it("can handle HTML", () => {
const html = `
<html>
<head>
<title>502 Bad Gateway</title>
</head>
<body>
<center>
<h1>502 Bad Gateway</h1>
</center>
<hr>
<center>nginx/1.18.0 (Ubuntu)</center>
</body>
</html>
`;

expect(formatErrors(html)).toEqual("502 Bad Gateway nginx/1.18.0 (Ubuntu)");
});
});
51 changes: 47 additions & 4 deletions src/app/utils/formatErrors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,10 +60,34 @@ const parseObjectError = (
return null;
};

const parseHtmlToText = (htmlContent: string): string | null => {
const bodyMatch = htmlContent.match(/<body[^>]*>([\s\S]*?)<\/body>/i);

if (bodyMatch) {
const bodyContent = bodyMatch[1];
const strippedText = bodyContent
// Remove all HTML tags from the body content
.replace(/<[^>]+>/g, "")
// Collapse multiple consecutive whitespace characters into a single space
.replace(/\s+/g, " ")
// Trim any leading or trailing whitespace from the resulting text
.trim();

return strippedText !== "" ? strippedText : null;
petermakowski marked this conversation as resolved.
Show resolved Hide resolved
}

// Return the original content if the body tag is not found
return htmlContent;
};

type ErrorFormatter = (errors: any, errorKey?: string) => FlattenedError;
const errorTypeFormatters: Record<string, ErrorFormatter> = {

type ErrorTypeFormat = "string" | "object" | "html";

const errorTypeFormatters: Record<ErrorTypeFormat, ErrorFormatter> = {
string: parseJSONError,
object: parseObjectError,
html: parseHtmlToText,
};

export type ErrorType<E = null, I = any, K extends keyof I = any> =
Expand All @@ -84,7 +108,26 @@ export const formatErrors = <E, I, K extends keyof I>(
if (!errors) {
return null;
}
const errorType = typeof errors;
const formatErrors = errorTypeFormatters[errorType];
return formatErrors ? formatErrors(errors, errorKey) : null;

const isHTMLContent = (content: string): boolean => {
return /<\/?[a-z][\s\S]*>/i.test(content);
};

const getErrorType = (errors: ErrorType<E, I, K>): ErrorTypeFormat => {
if (typeof errors === "string" && isHTMLContent(errors)) {
return "html";
}
return typeof errors in errorTypeFormatters
? (typeof errors as ErrorTypeFormat)
: "string";
};

const errorType = getErrorType(errors);
const formatErrorsByType = errorTypeFormatters[errorType];

if (formatErrorsByType) {
return formatErrorsByType(errors, errorKey);
}

return null;
};
Loading