In Node.js terms, a route is a binding between a URI and function. The Express framework provides built-in support for routing. An express object instance contains functions named after each HTTP verb: get, post, put, and delete. They have the following syntax: function(uri, handler);.
They are used to bind a handler function to a specific HTTP action executed over a URI. The handler function usually takes two arguments: request and response. Let's see it with a simple Hello route application:
var express = require('express');
var app = express();
app.get('/hello', function(request, response){
response.send('Hello route');
});
app.listen(3000);
Running this sample at localhost and accessing http://localhost:3000/hello will result in calling your handler function and it will respond saying Hello route, but routing can give you much more. It allows you to define a URI with parameters; for example, let's use /hello/:name as a routing string. It tells the framework that the URI used consists of two parts: a static part (hello) and a variable part (the name parameter).
Furthermore, when the routing string and the handler function are defined in line with the get function of an Express instance, a parameter collection is made available directly in the request argument of the handler function. To demonstrate this, let's modify our previous example a bit:
var express = require('express');
var app = express();
app.get('/hello:name', function(request, response){
response.send('Hello ' + request.params.name);
});
app.listen(3000);
As you can see in the preceding code snippet, we used a colon (:) to separate the parameter part of the URI from the static part. You can have multiple parameters in an Express route; for example, /category/:category-id/items/:item-id defines a route for displaying an item that belongs to a category, where the category-id and item-id are parameters.
Now let's try it out. Requesting http://localhost:3000/hello/friend will result in the following output:
hello friend
This is how we can provide parameterized URIs with Express. It is a nice feature, but it is often not enough. In web applications, we are used to providing additional parameters with GET parameters.
Unfortunately, the Express framework is not so good with GET parameters. Thus, we have to utilize the url module. It is built into Node.js to provide an easy way of using URL parsing. Let's use our hello result with other parameters in the application again, but extend it in a way that it outputs hello all when /hello is requested and hello friend when the requested URI is /hello?name=friend:
var express = require('express');
var url = require('url');
var app = express();
app.get('/hello', function(request, response){
var getParams = url.parse(request.url, true).query;
if (Object.keys(getParams).length == 0) {
response.end('Hello all');
} else {
response.end('Hello ' + getParams.name);
}
});
app.listen(3000);
There are a few things worth mentioning here. We used the url module's function parse. It takes a URL as its first argument and a Boolean as an optional second argument, which specifies whether the query string should be parsed or not. The url.parse function returns an associative object. We used Object.keys with it to transform the keys in these associative objects into an array so that we can check its length. This will help us check whether our URI has been called with GET parameters or not. In addition to the routing functions named after each HTTP verb, there is also a function named all. When used, it routes all the HTTP actions to the specified URI.
Now that we know how routing and the GET parameters work within Node.js and the Express environment, we are ready to define a route for the catalog module and bind it in our application. The following is the route as defined in routes/catalog.js.
var express = require('express');
var catalog = require('../modules/catalog.js')
var router = express.Router();
router.get('/', function(request, response, next) {
var categories = catalog.findCategoryies();
response.json(categories);
});
router.get('/:categoryId', function(request, response, next) {
var categories = catalog.findItems(request.params.categoryId);
if (categories === undefined) {
response.writeHead(404, {'Content-Type' : 'text/plain'});
response.end('Not found');
} else {
response.json(categories);
}
});
router.get('/:categoryId/:itemId', function(request, response, next) {
var item = catalog.findItem(request.params.categoryId, request.params.itemId);
if (item === undefined) {
response.writeHead(404, {'Content-Type' : 'text/plain'});
response.end('Not found');
} else {
response.json(item);
}
});
module.exports = router;
First, a Router instance is created from the Express module. Here is a table that nicely describes the routing we just implemented. This will be helpful later when we test our API:
| HTTP method | Route | Catalog's module function |
| GET | /catalog | findCategories() |
| GET | /catalog/:categoryId | findItems(categoryId) |
| GET | /catalog/:categoryId/:itemId | findItem(categoryId, itemId) |