Skip to content

Commit

Permalink
fix(rest): return 404 when a model was not found
Browse files Browse the repository at this point in the history
Modify the `reject` action to convert ENTITY_NOT_FOUND code to response
status code 404.
  • Loading branch information
bajtos committed Sep 18, 2018
1 parent beb1272 commit 7a56bad
Show file tree
Hide file tree
Showing 5 changed files with 38 additions and 0 deletions.
4 changes: 4 additions & 0 deletions examples/todo-list/test/acceptance/todo-list.acceptance.ts
Expand Up @@ -92,6 +92,10 @@ describe('Application', () => {
expect(result.body).to.deepEqual(expected);
});

it('returns 404 when a todo does not exist', () => {
return client.get('/todo-lists/99999').expect(404);
});

it('updates a todoList by ID', async () => {
const updatedTodoList = givenTodoList({
title: 'A different title to the todo list',
Expand Down
4 changes: 4 additions & 0 deletions examples/todo-list/test/acceptance/todo.acceptance.ts
Expand Up @@ -64,6 +64,10 @@ describe('Application', () => {
expect(result.body).to.deepEqual(expected);
});

it('returns 404 when a todo does not exist', () => {
return client.get('/todos/99999').expect(404);
});

it('replaces the todo by ID', async () => {
const updatedTodo = givenTodo({
title: 'DO SOMETHING AWESOME',
Expand Down
4 changes: 4 additions & 0 deletions examples/todo/test/acceptance/todo.acceptance.ts
Expand Up @@ -96,6 +96,10 @@ describe('Application', () => {
expect(result.body).to.deepEqual(expected);
});

it('returns 404 when a todo does not exist', () => {
return client.get('/todos/99999').expect(404);
});

it('replaces the todo by ID', async () => {
const updatedTodo = givenTodo({
title: 'DO SOMETHING AWESOME',
Expand Down
14 changes: 14 additions & 0 deletions packages/rest/src/providers/reject.provider.ts
Expand Up @@ -9,6 +9,12 @@ import {HttpError} from 'http-errors';
import {RestBindings} from '../keys';
import {writeErrorToResponse, ErrorWriterOptions} from 'strong-error-handler';

// TODO(bajtos) Make this mapping configurable at RestServer level,
// allow apps and extensions to contribute additional mappings.
const codeToStatusCodeMap: {[key: string]: number} = {
ENTITY_NOT_FOUND: 404,
};

export class RejectProvider implements Provider<Reject> {
constructor(
@inject(RestBindings.SequenceActions.LOG_ERROR)
Expand All @@ -23,6 +29,14 @@ export class RejectProvider implements Provider<Reject> {

action({request, response}: HandlerContext, error: Error) {
const err = <HttpError>error;

if (!err.status && !err.statusCode && err.code) {
const customStatus = codeToStatusCodeMap[err.code];
if (customStatus) {
err.statusCode = customStatus;
}
}

const statusCode = err.statusCode || err.status || 500;
writeErrorToResponse(err, request, response, this.errorWriterOptions);
this.logError(error, statusCode, request);
Expand Down
12 changes: 12 additions & 0 deletions packages/rest/test/unit/router/reject.provider.unit.ts
Expand Up @@ -28,6 +28,18 @@ describe('reject', () => {
expect(result).to.have.property('statusCode', 500);
});

it('converts error code ENTITY_NOT_FOUND to status code 404', async () => {
const reject = new RejectProvider(noopLogger).value();

const notFoundError: Error & {code?: string} = new Error('not found');
notFoundError.code = 'ENTITY_NOT_FOUND';

reject(contextStub, notFoundError);
const result = await contextStub.result;

expect(result.statusCode).to.equal(404);
});

it('logs the error', async () => {
const logger = sinon.spy() as LogError & SinonSpy;
const reject = new RejectProvider(logger).value();
Expand Down

0 comments on commit 7a56bad

Please sign in to comment.