mirror of
https://github.com/logto-io/logto.git
synced 2024-12-16 20:26:19 -05:00
refactor(core): dont throw for status errors in prod (#5690)
* refactor(core): dont throw for status errors in prod * refactor(core): report to AppInsights
This commit is contained in:
parent
de47d6ab5e
commit
368385b93d
3 changed files with 42 additions and 9 deletions
5
.changeset/cuddly-buses-obey.md
Normal file
5
.changeset/cuddly-buses-obey.md
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
"@logto/core": patch
|
||||
---
|
||||
|
||||
Management API will not return 500 in production for status codes that are not listed in the OpenAPI spec
|
|
@ -1,6 +1,7 @@
|
|||
import { createMockUtils } from '@logto/shared/esm';
|
||||
import { z } from 'zod';
|
||||
|
||||
import { EnvSet } from '#src/env-set/index.js';
|
||||
import RequestError from '#src/errors/RequestError/index.js';
|
||||
import ServerError from '#src/errors/ServerError/index.js';
|
||||
import { emptyMiddleware, createContextWithRouteParameters } from '#src/utils/test-utils.js';
|
||||
|
@ -135,6 +136,26 @@ describe('koaGuardMiddleware', () => {
|
|||
await expect(koaGuard({ status: [200, 204] })(ctx, next)).rejects.toThrow(ServerError);
|
||||
});
|
||||
|
||||
it('should not throw when status is invalid in production', async () => {
|
||||
const ctx = {
|
||||
...baseCtx,
|
||||
params: {},
|
||||
body: {},
|
||||
guard: {},
|
||||
response: { status: 301 },
|
||||
};
|
||||
const { isProduction } = EnvSet.values;
|
||||
|
||||
// eslint-disable-next-line @silverhand/fp/no-mutating-assign
|
||||
Object.assign(EnvSet.values, { isProduction: true });
|
||||
// @ts-expect-error
|
||||
await expect(koaGuard({ status: 200 })(ctx, next)).resolves.toBeUndefined();
|
||||
// @ts-expect-error
|
||||
await expect(koaGuard({ status: [200, 204] })(ctx, next)).resolves.toBeUndefined();
|
||||
// eslint-disable-next-line @silverhand/fp/no-mutating-assign
|
||||
Object.assign(EnvSet.values, { isProduction });
|
||||
});
|
||||
|
||||
it('should throw when inner middleware throws invalid status', async () => {
|
||||
const ctx = {
|
||||
...baseCtx,
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import { appInsights } from '@logto/app-insights/node';
|
||||
import type { Optional } from '@silverhand/essentials';
|
||||
import { has } from '@silverhand/essentials';
|
||||
import type { MiddlewareType } from 'koa';
|
||||
|
@ -8,7 +9,6 @@ import type { ZodType, ZodTypeDef } from 'zod';
|
|||
import { EnvSet } from '#src/env-set/index.js';
|
||||
import RequestError from '#src/errors/RequestError/index.js';
|
||||
import { ResponseBodyError, StatusCodeError } from '#src/errors/ServerError/index.js';
|
||||
import assertThat from '#src/utils/assert-that.js';
|
||||
import { consoleLog } from '#src/utils/console.js';
|
||||
|
||||
/** Configure what and how to guard. */
|
||||
|
@ -174,6 +174,9 @@ export default function koaGuard<
|
|||
* Assert the status code matches the value(s) in the config. If the config does not
|
||||
* specify a status code, it will not assert anything.
|
||||
*
|
||||
* In production, it will log a warning if the status code does not match the value(s) in the
|
||||
* config for better user experience.
|
||||
*
|
||||
* @param value The status code to assert.
|
||||
* @throws {StatusCodeError} If the status code does not match the value(s) in the config.
|
||||
*/
|
||||
|
@ -182,10 +185,17 @@ export default function koaGuard<
|
|||
return;
|
||||
}
|
||||
|
||||
assertThat(
|
||||
Array.isArray(status) ? status.includes(value) : status === value,
|
||||
new StatusCodeError(status, value)
|
||||
);
|
||||
if (Array.isArray(status) ? status.includes(value) : status === value) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (EnvSet.values.isProduction) {
|
||||
consoleLog.warn('Unexpected status code:', value, 'expected:', status);
|
||||
void appInsights.trackException(new StatusCodeError(status, value));
|
||||
return;
|
||||
}
|
||||
|
||||
throw new StatusCodeError(status, value);
|
||||
};
|
||||
|
||||
try {
|
||||
|
@ -215,10 +225,7 @@ export default function koaGuard<
|
|||
// the properties that are not defined in the schema.
|
||||
ctx.body = result.data;
|
||||
} else {
|
||||
if (!EnvSet.values.isProduction) {
|
||||
consoleLog.error('Invalid response:', result.error);
|
||||
}
|
||||
|
||||
consoleLog.error('Invalid response:', result.error);
|
||||
throw new ResponseBodyError(result.error);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue