Service Return
This library automatically handle the serialisation of the response of your methods. It takes care of content type headers and status codes to be sent.
When a primitive type is returned by a service method, it is sent as a plain text into the response body.
@GET
sayHello(): string {
return "Hello";
}
The response will contains only the String Hello
as a plain text
When an object is returned, it is sent as a JSON serialised string into the response body.
@GET
@Path(":id")
getPerson(@PathParam("id") id: number): Person {
return new Person(id);
}
The response will contains the person JSON serialisation (ex: {id: 123}
. The response
will have a application/json
context type.
When the method returns nothing, an empty body is sent with a 204
status code.
@POST
test(myObject: MyClass): void {
//...
}
We provide also, some special types to inform that a reference to a resource is returned and that the server should handle it properly.
Type | Description |
---|---|
NewResource | Inform that a new resource was created. Server will add a Location header and set status to 201 |
RequestAccepted | Inform that the request was accepted but is not completed. A Location header should inform the location where the user can monitor his request processing status. Server will set the status to 202 |
MovedPermanently | Inform that the resource has permanently moved to a new location, and that future references should use a new URI with their requests. Server will set the status to 301 |
MovedTemporarily | Inform that the resource has temporarily moved to another location, but that future references should still use the original URI to access the resource. Server will set the status to 302 |
import {Return} from "typescript-rest";
@Path("test")
class TestService {
@POST
test(myObject: MyClass, @ContextRequest request: express.Request): Return.NewResource<void> {
//...
return new Return.NewResource<void>(req.url + "/" + generatedId);
}
}
The server will return an empty body with a 201
status code and a Location
header pointing to
the URL of the created resource.
It is possible to specify a body to be sent in responses:
import {Return} from "typescript-rest";
interface NewObject {
id: string;
}
@Path("test")
class TestService {
@POST
test(myObject: MyClass, @ContextRequest request: express.Request): Return.NewResource<NewObject> {
//...
return new Return.NewResource<NewObject>(req.url + "/" + generatedId, {id: generatedId}); //Returns a JSON on body {id: generatedId}
}
@POST
testWithStringBody(myObject: MyClass, @ContextRequest request: express.Request): Return.NewResource<string> {
//...
return new Return.NewResource<string>(req.url + "/" + generatedId, 'The body of the response');
}
}
You can also use special return types to handle file downloads:
Type | Description |
---|---|
DownloadResource | Used to reference a resource (by its fileName) and download it |
DownloadBinaryData | Used to return a file to download, based on a Buffer object |
For example:
import {Return} from "typescript-rest";
@Path("download")
class TestDownload {
@GET
testDownloadFile(): Return.DownloadResource {
return new Return.DownloadResource(__dirname +'/test-rest.spec.js', '/test-rest.spec.js');
}
@GET
testDownloadFile(): Promise<Return.DownloadBinaryData> {
return new Promise<Return.DownloadBinaryData>((resolve, reject)=>{
fs.readFile(__dirname + '/test-rest.spec.js', (err, data)=>{
if (err) {
return reject(err);
}
return resolve(new Return.DownloadBinaryData(data, 'application/javascript', 'test-rest.spec.js'))
});
});
}
}
If you want to handle by yourself the server response, you can use NoResponse
return value to tell typescript-rest that you don't want that it send any response to the client. Eg:
import {Return} from "typescript-rest";
@Path("noresponse")
class TestNoResponse {
@GET
public test() {
return Return.NoResponse;
}
}
app.use("/noresponse", (req, res, next) => {
res.send("I am handling the response here, in other middleware");
});
or
import {Return} from "typescript-rest";
@Path("noresponse")
class TestNoResponse {
@GET
public test(@ContextResponse res: express.Response) {
res.send("I am handling the response here, don't do it automatically");
return Return.NoResponse;
}
}
The above section shows how the types returned are handled by the Server. However, most of the previous examples are working synchronously. The recommended way is to work asynchronously, for a better performance.
To work asynchronously, you can return a Promise
on your service method. The above rules to handle return types
applies to the returned promise resolved value.
Some examples:
import {Return} from "typescript-rest";
@Path("async")
class TestService {
@POST
test(myObject: MyClass, @ContextRequest request: express.Request): Promise<Return.NewResource> {
return new Promise<Return.NewResource>(function(resolve, reject){
//...
resolve(new Return.NewResource(req.url + "/" + generatedId));
});
}
@GET
testGet() {
return new Promise<MyClass>(function(resolve, reject){
//...
resolve(new MyClass());
});
}
}
It is important to observe that you can inform your return type explicitly or not, as you can see in the above example.
You can also use async
and await
:
@Path('async')
export class MyAsyncService {
@GET
@Path('test')
async test( ) {
let result = await this.aPromiseMethod();
return result;
}
@GET
@Path('test2')
async test2( ) {
try {
let result = await this.aPromiseMethod();
return result;
} catch (e) {
// log error here, if you want
throw e;
}
}
private aPromiseMethod() {
return new Promise<string>((resolve, reject) => {
setTimeout(() => {
resolve('OK');
}, 10);
});
}
}
- Server
- @Path Decorator
- Http Methods
- Request Parameters
- Types and languages
- @BodyOptions Decorator
- Service Context
- Service Return
- @Security Decorator
- Express Middlewares
- @PreProcessor Decorator
- @PostProcessor Decorator
- Server Errors
- Service Factory and IoC
- Inheritance and Abstract Services
- Swagger Documentation