Response
--------
What is returned by the Route method will be sent to the client as the response.
The [Routing](/route/README.md) section touched this briefly, here we will go over
all the options of respoding to a request.
[Responding to Routes](#responding)
[Errors](#errors)
[Response Factories](#factories)
[Default Error/Response Codes](#defaults)
## Responding to Routes
All returned and resolved values that are not `Response` objects will be converted
to `Response` objects at some point. When this happens, if your route does not
specify the type of response, a default will be chosen from the context. The
defaults and their conditions are-
**200** - Is the default for any resolved/returned request with a payload.
**204** - Is the default for any resolved/returned request without a payload.
**400** - Is the default for any request that has missing required `injectables`
or fails `DTO` validation.
**500** - Is the default for any rejected request, thrown error, failed `rule`,
or failed `resource resolution`.
For more control over the status code, the generically named `Response` object
should be used. When creating a response, you should provide the http status code
as well as the data to be sent to the client.
```typescript
import {Route, Response} from 'expresskit';
export class FooRouter {
@Route('GET', '/foo')
public static fooRoute() {
return 'foo';
// is the same as
return new Response(200, 'foo');
// is the same as
return Promise.resolve('foo');
// is the same as
return Promise.resolve(new Response(200, 'foo'));
}
}
```
## Errors
To respond with an error you can simple return a response with an error code.
```typescript
return new Response(500, 'something bad happened');
```
Under two conditions will an error be **assumed**. Those conditions are if the route
encounters a `Thrown Error` or `Rejected Promise`. In these cases, the status code
will default to a `500 Internal Server Error`. However, a thrown `Error` is not the
same as a thrown `Resposne`.
```typescript
import {Route} from 'expresskit';
export class FooRouter {
@Route('GET', '/foo')
public static fooRoute() {
throw new Error('An error occured')
// is NOT the same as
return Promise.reject('An error occured');
}
}
```
If an error is thrown, it assumed that there is an actual runtime error and the
stacktrace will be returned. You can throw intended errors by throwing a `Response`.
```typescript
import {Route, Response} from 'expresskit';
export class FooRouter {
@Route('GET', '/foo')
public static fooRoute() {
return new Response(500, 'An error occured');
// is the same as
throw new Response(500, 'An error occured')
// is the same as
return Promise.reject('An error occured');
// is the same as
return Promise.reject(new Response(500, 'An error occured'));
}
}
```
## Response Factories
For convenience sake, some response factories are available. Each response
factory defaults the response code as well as the response value if not given.
```typescript
import {Route, Response} from 'expresskit';
export class FooRouter {
@Route('GET', '/foo')
public static fooRoute() {
return Response.NotFound(`Couldn't find Foo`);
}
}
```
The available factories and their values are-
| Factory Function | Resposne Code | Default Response Value |
|------------------------|---------------|-------------------------|
| Ok | 200 | Ok |
| Created | 201 | Created |
| Accepted | 202 | Accepted |
| None | 204 | |
| BadRequest | 400 | Bad Request |
| Unauthorized | 401 | Unauthorized |
| PaymentRequired | 402 | Payment Required |
| Forbidden | 403 | Forbidden |
| NotFound | 404 | Not Found |
| MethodNotAllowed | 405 | Method Not Allowed |
| NotAcceptable | 406 | Not Acceptable |
| Conflict | 409 | Conflict |
| Gone | 410 | No Long Available |
| Error | 500 | Internal Server Error |
| NotImplemented | 501 | Not Implemented |
| BadGateway | 502 | Bad Gateway |
| TemporarilyUnavailable | 503 | Temporarily Unavailable |
| GatewayTimeout | 504 | GatewayTimeout |
## Default Error/Response Codes
Returning a `Response` should be used if the route or rule may return different
types of responses. For everything else, use the `ResponseCode` and `ErrorCode`
decorators if you don't intended to use the defaults. These decorators override
the default response codes for success and error responses. Only one default
response code and error code can be used for a particular `Route`, `Rule`, or
`Resolver`.
```typescript
import {Route, Param, Resolver, ResponseCode, ErrorCode} from 'expresskit';
export class WidgetRouter {
@Resolver('Widget')
@Route('GET', '/widget/:id')
@ResponseCode(200) // Redundant but you get the point
@ErrorCode(404)
public static getWidget(@Param('id') id: string): Promise {
let widget = /* get widget from database*/;
if(widget) {
return Promise.resolve(widget);
} else {
return Promise.reject(`Widget by id '${id}' not found.`);
}
}
}
```
In the above example, the `getWidget` method is both a `Route` and a `Resource
Resolver`. If another route wants to resolve the `Widget` resource for that route
using this resolver, a `404` error will be returned that the resolution fails.
```typescript
import {Route, Param, Resolver, ResponseCode, ErrorCode} from 'expresskit';
export class WidgetRouter {
@Resolver('Widget')
@Route('GET', '/widget/:id')
@ResponseCode(200) // Redundant but you get the point
@ErrorCode(404)
public static getWidget(@Param('id') id: string): Promise {
let widget = /* get widget from database*/;
if(widget) {
return Promise.resolve(widget);
} else {
return Promise.reject(`Widget by id '${id}' not found.`);
}
}
// If `Widget` cannot be resolved, a 404 error will be returned
@Route('PUT', '/widget/:id')
public static updateWidget(@Resource('Widget') widget: Widget) {
// update widget
}
```
## Keep Reading
[Routing](/route/README.md)
[Response](/response/README.md)
[Middleware](/middleware/README.md)
[Resource Resolutions](/resource/README.md)
[Rules](/rule/README.md)
[DTOs](/dto/README.md)
## More Links
[Expresskit Seed Project](https://github.com/iamchairs/expresskit-seed)
[Github](https://github.com/iamchairs/restkit)
[Issues](https://github.com/iamchairs/restkit/issues)
[NPM](https://www.npmjs.com/package/restkit)
[Twitter](https://twitter.com/micahwllmsn)