mirror of
https://github.com/Unleash/unleash.git
synced 2025-04-15 01:16:22 +02:00
feat: make maintenance-related 503s more intuitive (#5018)
This makes maintenance-related 503s more intuitive on our UI by mentioning that maintenance banner is currently enabled. 
This commit is contained in:
parent
c41f23ae54
commit
6c21ed5f74
@ -4,3 +4,4 @@ export const CREATED = 201;
|
|||||||
export const NOT_FOUND = 404;
|
export const NOT_FOUND = 404;
|
||||||
export const FORBIDDEN = 403;
|
export const FORBIDDEN = 403;
|
||||||
export const UNAUTHORIZED = 401;
|
export const UNAUTHORIZED = 401;
|
||||||
|
export const UNAVAILABLE = 503;
|
||||||
|
@ -5,6 +5,7 @@ import {
|
|||||||
NOT_FOUND,
|
NOT_FOUND,
|
||||||
OK,
|
OK,
|
||||||
UNAUTHORIZED,
|
UNAUTHORIZED,
|
||||||
|
UNAVAILABLE,
|
||||||
} from 'constants/statusCodes';
|
} from 'constants/statusCodes';
|
||||||
import {
|
import {
|
||||||
AuthenticationError,
|
AuthenticationError,
|
||||||
@ -12,6 +13,7 @@ import {
|
|||||||
ForbiddenError,
|
ForbiddenError,
|
||||||
headers,
|
headers,
|
||||||
NotFoundError,
|
NotFoundError,
|
||||||
|
UnavailableError,
|
||||||
} from 'utils/apiUtils';
|
} from 'utils/apiUtils';
|
||||||
import { formatApiPath } from 'utils/formatPath';
|
import { formatApiPath } from 'utils/formatPath';
|
||||||
import { ACCESS_DENIED_TEXT } from 'utils/formatAccessText';
|
import { ACCESS_DENIED_TEXT } from 'utils/formatAccessText';
|
||||||
@ -27,6 +29,7 @@ interface IUseAPI {
|
|||||||
handleNotFound?: ApiErrorHandler;
|
handleNotFound?: ApiErrorHandler;
|
||||||
handleUnauthorized?: ApiErrorHandler;
|
handleUnauthorized?: ApiErrorHandler;
|
||||||
handleForbidden?: ApiErrorHandler;
|
handleForbidden?: ApiErrorHandler;
|
||||||
|
handleUnavailable?: ApiErrorHandler;
|
||||||
propagateErrors?: boolean;
|
propagateErrors?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -35,6 +38,7 @@ const useAPI = ({
|
|||||||
handleNotFound,
|
handleNotFound,
|
||||||
handleForbidden,
|
handleForbidden,
|
||||||
handleUnauthorized,
|
handleUnauthorized,
|
||||||
|
handleUnavailable,
|
||||||
propagateErrors = false,
|
propagateErrors = false,
|
||||||
}: IUseAPI) => {
|
}: IUseAPI) => {
|
||||||
const [errors, setErrors] = useState<Record<string, string>>({});
|
const [errors, setErrors] = useState<Record<string, string>>({});
|
||||||
@ -104,6 +108,22 @@ const useAPI = ({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (res.status === UNAVAILABLE) {
|
||||||
|
if (handleUnavailable) {
|
||||||
|
return handleUnavailable(setErrors, res, requestId);
|
||||||
|
} else {
|
||||||
|
setErrors((prev) => ({
|
||||||
|
...prev,
|
||||||
|
unavailable: 'This operation is unavailable',
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (propagateErrors) {
|
||||||
|
const response = await res.json();
|
||||||
|
throw new UnavailableError(res.status, response);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (res.status > 399) {
|
if (res.status > 399) {
|
||||||
const response = await res.json();
|
const response = await res.json();
|
||||||
if (response?.details?.length > 0 && propagateErrors) {
|
if (response?.details?.length > 0 && propagateErrors) {
|
||||||
|
@ -3,12 +3,17 @@ import {
|
|||||||
FORBIDDEN,
|
FORBIDDEN,
|
||||||
NOT_FOUND,
|
NOT_FOUND,
|
||||||
UNAUTHORIZED,
|
UNAUTHORIZED,
|
||||||
|
UNAVAILABLE,
|
||||||
} from 'constants/statusCodes';
|
} from 'constants/statusCodes';
|
||||||
|
|
||||||
export interface IErrorBody {
|
export interface IErrorBody {
|
||||||
|
message?: string;
|
||||||
details?: { message: string }[];
|
details?: { message: string }[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const getErrorMessage = (body: IErrorBody) =>
|
||||||
|
body.details?.[0]?.message || body.message;
|
||||||
|
|
||||||
export class AuthenticationError extends Error {
|
export class AuthenticationError extends Error {
|
||||||
statusCode: number;
|
statusCode: number;
|
||||||
|
|
||||||
@ -24,23 +29,31 @@ export class ForbiddenError extends Error {
|
|||||||
body: IErrorBody;
|
body: IErrorBody;
|
||||||
|
|
||||||
constructor(statusCode: number = FORBIDDEN, body: IErrorBody = {}) {
|
constructor(statusCode: number = FORBIDDEN, body: IErrorBody = {}) {
|
||||||
super(
|
super(getErrorMessage(body) || 'You cannot perform this action');
|
||||||
body.details?.length
|
|
||||||
? body.details[0].message
|
|
||||||
: 'You cannot perform this action',
|
|
||||||
);
|
|
||||||
this.name = 'ForbiddenError';
|
this.name = 'ForbiddenError';
|
||||||
this.statusCode = statusCode;
|
this.statusCode = statusCode;
|
||||||
this.body = body;
|
this.body = body;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export class UnavailableError extends Error {
|
||||||
|
statusCode: number;
|
||||||
|
body: IErrorBody;
|
||||||
|
|
||||||
|
constructor(statusCode: number = UNAVAILABLE, body: IErrorBody = {}) {
|
||||||
|
super(getErrorMessage(body) || 'This operation is unavailable');
|
||||||
|
this.name = 'UnavailableError';
|
||||||
|
this.statusCode = statusCode;
|
||||||
|
this.body = body;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
export class BadRequestError extends Error {
|
export class BadRequestError extends Error {
|
||||||
statusCode: number;
|
statusCode: number;
|
||||||
body: IErrorBody;
|
body: IErrorBody;
|
||||||
|
|
||||||
constructor(statusCode: number = BAD_REQUEST, body: IErrorBody = {}) {
|
constructor(statusCode: number = BAD_REQUEST, body: IErrorBody = {}) {
|
||||||
super(body.details?.length ? body.details[0].message : 'Bad request');
|
super(getErrorMessage(body) || 'Bad request');
|
||||||
this.name = 'BadRequestError';
|
this.name = 'BadRequestError';
|
||||||
this.statusCode = statusCode;
|
this.statusCode = statusCode;
|
||||||
this.body = body;
|
this.body = body;
|
||||||
|
@ -2,6 +2,9 @@ import { IUnleashConfig } from '../types';
|
|||||||
import MaintenanceService from '../services/maintenance-service';
|
import MaintenanceService from '../services/maintenance-service';
|
||||||
import { IAuthRequest } from '../routes/unleash-types';
|
import { IAuthRequest } from '../routes/unleash-types';
|
||||||
|
|
||||||
|
export const MAINTENANCE_MODE_ENABLED =
|
||||||
|
'Unleash is currently in maintenance mode.';
|
||||||
|
|
||||||
const maintenanceMiddleware = (
|
const maintenanceMiddleware = (
|
||||||
{ getLogger }: Pick<IUnleashConfig, 'getLogger' | 'flagResolver'>,
|
{ getLogger }: Pick<IUnleashConfig, 'getLogger' | 'flagResolver'>,
|
||||||
maintenanceService: MaintenanceService,
|
maintenanceService: MaintenanceService,
|
||||||
@ -17,7 +20,9 @@ const maintenanceMiddleware = (
|
|||||||
writeMethod &&
|
writeMethod &&
|
||||||
(await maintenanceService.isMaintenanceMode())
|
(await maintenanceService.isMaintenanceMode())
|
||||||
) {
|
) {
|
||||||
res.status(503).send({});
|
res.status(503).send({
|
||||||
|
message: MAINTENANCE_MODE_ENABLED,
|
||||||
|
});
|
||||||
} else {
|
} else {
|
||||||
next();
|
next();
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user