diff --git a/.changeset/ninety-jeans-scream.md b/.changeset/ninety-jeans-scream.md new file mode 100644 index 0000000000..3465a67444 --- /dev/null +++ b/.changeset/ninety-jeans-scream.md @@ -0,0 +1,5 @@ +--- +'@backstage/errors': minor +--- + +Added `ServiceUnavailableError` diff --git a/.changeset/tasty-oranges-sleep.md b/.changeset/tasty-oranges-sleep.md new file mode 100644 index 0000000000..7c99ecc822 --- /dev/null +++ b/.changeset/tasty-oranges-sleep.md @@ -0,0 +1,5 @@ +--- +'@backstage/backend-app-api': patch +--- + +Added handling of `ServiceUnavailableError` to error handling middleware. diff --git a/packages/backend-app-api/src/http/MiddlewareFactory.test.ts b/packages/backend-app-api/src/http/MiddlewareFactory.test.ts index 64812564ca..5dbb63ec59 100644 --- a/packages/backend-app-api/src/http/MiddlewareFactory.test.ts +++ b/packages/backend-app-api/src/http/MiddlewareFactory.test.ts @@ -21,6 +21,7 @@ import { NotAllowedError, NotFoundError, NotModifiedError, + ServiceUnavailableError, } from '@backstage/errors'; import express from 'express'; import createError from 'http-errors'; @@ -143,6 +144,9 @@ describe('MiddlewareFactory', () => { app.use('/ConflictError', () => { throw new ConflictError(); }); + app.use('/ServiceUnavailableError', () => { + throw new ServiceUnavailableError(); + }); app.use(middleware.error()); const r = request(app); @@ -165,6 +169,10 @@ describe('MiddlewareFactory', () => { expect((await r.get('/ConflictError')).body.error.name).toBe( 'ConflictError', ); + expect((await r.get('/ServiceUnavailableError')).status).toBe(503); + expect((await r.get('/ServiceUnavailableError')).body.error.name).toBe( + 'ServiceUnavailableError', + ); }); it('logs all 500 errors', async () => { diff --git a/packages/backend-app-api/src/http/MiddlewareFactory.ts b/packages/backend-app-api/src/http/MiddlewareFactory.ts index 833bdba540..774e784d1d 100644 --- a/packages/backend-app-api/src/http/MiddlewareFactory.ts +++ b/packages/backend-app-api/src/http/MiddlewareFactory.ts @@ -36,6 +36,7 @@ import { NotAllowedError, NotFoundError, NotModifiedError, + ServiceUnavailableError, serializeError, } from '@backstage/errors'; import { NotImplementedError } from '@backstage/errors'; @@ -260,6 +261,8 @@ function getStatusCode(error: Error): number { return 409; case NotImplementedError.name: return 501; + case ServiceUnavailableError.name: + return 503; default: break; } diff --git a/packages/errors/api-report.md b/packages/errors/api-report.md index 650a826a30..0d405d8ba6 100644 --- a/packages/errors/api-report.md +++ b/packages/errors/api-report.md @@ -125,6 +125,9 @@ export function serializeError( }, ): SerializedError; +// @public +export class ServiceUnavailableError extends CustomErrorBase {} + // @public export function stringifyError(error: unknown): string; ``` diff --git a/packages/errors/src/errors/common.ts b/packages/errors/src/errors/common.ts index e1a292d7b5..a2ea20e99f 100644 --- a/packages/errors/src/errors/common.ts +++ b/packages/errors/src/errors/common.ts @@ -81,6 +81,13 @@ export class NotModifiedError extends CustomErrorBase {} */ export class NotImplementedError extends CustomErrorBase {} +/** + * The server is not ready to handle the request. + * + * @public + */ +export class ServiceUnavailableError extends CustomErrorBase {} + /** * An error that forwards an underlying cause with additional context in the message. * diff --git a/packages/errors/src/errors/index.ts b/packages/errors/src/errors/index.ts index efd3257fbf..0a59891f87 100644 --- a/packages/errors/src/errors/index.ts +++ b/packages/errors/src/errors/index.ts @@ -25,6 +25,7 @@ export { NotFoundError, NotModifiedError, NotImplementedError, + ServiceUnavailableError, } from './common'; export { CustomErrorBase } from './CustomErrorBase'; export { ResponseError } from './ResponseError';