Skip to main content

Responses

AxiSpark Http Plugin provides 3 ways to send responses to the client. Let's explore each of them in detail.

Automatic Response Handling​

When you return a value from a controller method, the Http Plugin automatically handles the response for you. It serializes the returned value and sends it back to the client as a JSON response. This is the default behavior of the Http Plugin, and it works seamlessly for most use cases. In this type of response, you can define the status code by using @HttpCode() decorator. If you don't specify a status code, the default status code will be calculated based on the HTTP method used.

automatic-response-example.ts
import { Controller, Get, HttpStatusCode } from '@axisparkjs/http';

@Controller('/users')
export class UserController {
@Get()
getUsers() {
// The returned value will be automatically serialized and sent as a JSON response
// The status code will be 200 OK by default for GET requests
return [
{ id: 1, name: 'John Doe' },
{ id: 2, name: 'Jane Smith' },
];
}

@Get(':id')
@HttpCode(HttpStatusCode.Accepted) // OR @HttpCode(202)
getUserById(@Path('id') id: number) {
// The returned value will be automatically serialized and sent as a JSON response
// The status code will be 202 Accepted as specified by the @HttpCode() decorator
return { id, name: 'John Doe' };
}
}

These are the default status codes for each HTTP method when using automatic response handling:

HTTP MethodDefault Status Code
GET200 OK
POST201 Created
PUT200 OK
PATCH200 OK
DELETE204 No Content
Other Methods200 OK

In automatic response handling, the best idea to return errors is to throw an HttpError with the appropriate status code and message. You can use the HttpError class or any of its subclasses, such as BadRequestError, UnauthorizedError, ForbiddenError, NotFoundError, and more. The Http Plugin will catch the error and send an appropriate response to the client.

The status code names follow RFC 9110, Section 15. Use HttpStatusCode.MultipleChoices for 300, HttpStatusCode.ContentTooLarge and ContentTooLargeError for 413, HttpStatusCode.RangeNotSatisfiable and RangeNotSatisfiableError for 416, HttpStatusCode.MisdirectedRequest and MisdirectedRequestError for 421, and HttpStatusCode.UnprocessableContent and UnprocessableContentError for 422. Previous names remain available as deprecated aliases.

RFC 9110 marks status 418 as unused and reserved. HttpStatusCode.Unused and UnusedError identify it for completeness; avoid using it for application responses. The former IAmATeapot names remain deprecated compatibility aliases.

automatic-response-error-example.ts
import { Controller, Get, HttpError, BadRequestError, HttpStatusCode } from '@axisparkjs/http';

@Controller('/users')
export class UserController {
@Get()
getError() {
...
throw new HttpError('Invalid request', HttpStatusCode.BadRequest);
}

getBadRequestError() {
...
throw new BadRequestError('Invalid request', { cause: 'Invalid input provided', description: 'The request body is missing required fields' });
}
}

You can handle these errors in a global error filter or in a specific controller error filter. The Http Plugin provides a default error filter that handles these errors and sends appropriate responses to the client. You can also create your own custom error filters to handle errors in a specific way.

Custom Response Handling​

Instead of returning a value from a controller method, you can return an HttpResult object. This allows you to have more control over the response, including setting custom headers, status codes, and response bodies. The HttpResults class provides a fluent API for building responses. You can build them manually or use the static methods provided by the HttpResults class to create common response types.

custom-response-example.ts
import { Controller, Get, HttpStatusCode } from '@axisparkjs/http';

@Controller('/users')
export class UserController {
@Get()
getUsers() {
// Returns a 200 OK response with a JSON body containing the list of users
// Instance handled by HttpResults
return HttpResults.Ok([
{ id: 1, name: 'John Doe' },
{ id: 2, name: 'Jane Smith' },
]);
}

@Get()
getUsers() {
// Returns a 200 OK response with a JSON body containing the list of users
// Instance handled by manually, allows you more control over the response, including setting custom headers, status codes, and response bodies.
return new BodyHttpResult([
{ id: 1, name: 'John Doe' },
{ id: 2, name: 'Jane Smith' },
], HttpStatusCode.Ok, {
'X-Custom-Header': 'CustomValue',
});
}
}

There are a bunch of static methods available in the HttpResults class to create common response types, such as Ok(), Created(), NoContent(), BadRequest(), Unauthorized(), Forbidden(), NotFound(), and more. You can use these methods to quickly create responses with the appropriate status codes and response bodies.

There are also multiple classes available for creating custom responses, such as BodyHttpResult, RedirectHttpResult, ErrorHttpResult, and more. You can use these classes to create responses with different content types and response bodies.

Manual Response Handling​

If none of the above methods suit your needs, you can manually handle the response by using the HttpResponse object provided by the Http Plugin. This allows you to have complete control over the response, including setting custom headers, status codes, and response bodies. You can access the HttpResponse object by injecting it into your controller method with the @Response decorator. Important, in case you use this method, you must return HandledResult to indicate that the response has been handled manually and that the Http Plugin should not attempt to send a response automatically.

manual-response-example.ts
import { HandledResult } from '@axisparkjs/engine';
import { Controller, Get, Response, HttpResponse } from '@axisparkjs/http';

@Controller('/users')
export class UserController {
@Get()
getUsers(@Response() res: HttpResponse) {
// Manually set the status code, headers, and response body
res.status(200).header('X-Custom-Header', 'CustomValue').json([
{ id: 1, name: 'John Doe' },
{ id: 2, name: 'Jane Smith' },
]);
return new HandledResult();
}
}