Body Parser Middleware
We'll start where we left off in the previous post. In that post we added the Express package using npm. For this app we also need to add the Express body-parser module. This module is a middleware component for Express that parses the body of HTTP requests so we can get data that has been sent via a POST request. To add it right click on "npm" in the project tree, select "Install new npm Packages", then search for "body-parser" and install it.
Now we need the type definition file for body-parser so we get intellisense in our TypeScript files. We'll have to get that from the Node command line using "typings". Make sure you're in the project folder then execute the following:
Now we can start to write our main module, app.ts and include body-parser.
First we import express and create our app. Then we import body-parser and tell our app to use its urlencoded middlware component. This middleware takes incoming POST requests where the body uses x-www-form-urlencoded format and parses the form data into name/value pairs which can be accessed through the request.body object. We'll see more about that later.
The Data Model
Before we go any further we need to define our todo item model. So let's create a folder in our project called models and add a new TypeScript file called todoModel.js.
Inside there we define an ITodoItem interface, then we define a TodoItemModel class that implements it. I like to have an interface for each model so that we don't always need to use the class, especially if we're getting objects from JSON.
Notice that the interface and class are exported so we can use them outside of the module. Notice also the variable named nextId. This is used in the constructor to create a unique ID for each todo item that is created. We don't want this variable to be visible outside of the module so we don't export it.
The Data Repository
Now we need a repository to save our todo items in. Let's create a folder called repositories and add a TypeScript file called TodoItemRepo.ts.
First we import our todo item model, then define an interface for our todo item repository. We need a way to add, remove and find items in the repository. Then we implement a repository for that interface called TodoItemList that merely stores the items in an array. In a real app our repository would probably interact with a database, but that's beyond the scope of this post.
Defining the Routes
Now that we have our model and a place to store our data we can create our routes. First thing we want to do is create a folder called routes and create a new TypeScript file called todoAPI.ts. This module will hold all of our routes and the implementation of those routes. By placing them in their own file we keep them out of our main file app.ts to keep it clean.
First we import the model and repository modules. Then we create a new TodoItemList to hold our items. Next is the only function that will be visible outside of the module, initRoutes(). This function takes our app that we created in app.ts and adds the routes for our API to it.
All of the routes start with "/todo" and a few have "/:id" appended. By placing a colon at the beginning of a route part it tells the express router that this is a parameter. All route parameters will be map it to the request.params object. So in this case we should be able to access request.params.id.
Each route is mapped to a function that is defined in the module. Note that none of the handler functions are exported. They don't need to be because we are setting up the routes inside the module.
- The list() function merely returns the todo list object.
- The create() function first gets name of the new todo item from the request.body object using request.body.name (The body-parser middleware put it there for us). Then it creates a new instance of a TodoItemModel and adds it to the list. Finally it returns the updated list.
- The getById() function gets the id parameter from the request.params and returns the matching todo item. If one isn't found it returns a 400 HTTP status.
- The update() function gets the id of the item to update from the request.params and the new name of the todo item from the request.body object and updates it. Then it returns the item.
- And finally the del() function gets the id of the item to delete from the request.params and removes the item from the list then sends back the updated list.
Starting the Service
That's it for our todo API! Now we need to go back into our main file, app.ts and tell it to use our routes and start the service. We add the following to that file:
First we import our todoAPI module, then call its initRoutes() function passing in our application. Then lastly we start the service by calling app.listen().
Let's go run it now and test it out. From the Node command line we start the service.
We should get the message, "Listening on port 8080" if all went well. Now we need to test it.
Testing the API
In order to test our API we'll need a tool to test REST web services. We're not creating the front end as part of this post so we'll need another way to test it. I like to use the Postman extension in Chrome (http://www.getpostman.com/). It allows you to specify any REST verb as well as specify parameters in the body of the request.
First let's add a todo item. To do that we will set the verb to POST and use the URL: http://localhost:8080/todo. We also need to specify the todo item name in the body. We need to use x-www-form-urlencoded as the body type.
Now click the Send button and it adds a new item named Task1. It also returns the todo list which we see in the response body. That means it worked. Now let's test some other routes.
- Set the verb to GET and call http://localhost:8080/todo. This will hit return the list of all items.
- Set the verb to GET and call http://localhost:8080/todo/1. This will get the item with the id of 1.
- Set the verb to PUT, add a name parameter to the request body, and call http://localhost:8080/todo/1. This will change the name of the item with id of 1.
- Set the verb to DELETE and call http://localhost:8080/todo/1. This will delete the item with id of 1.
In this way you can play around with the todo service API adding, removing and changing todo items.
No we have a working web service with CRUD operations for managing a list of todo items. From here we could write a front end app that consumes these APIs. Look for a future post to implement that.