Express Routing
#
WhyExpress enables us to build our applications with a minimal interface. It provides us the tools that are required to build our application, without needing to worry about low level protocols, processes, etc.
We can use ExpressJS’s web application framework to build simple API for websites, web apps and servers. A significant benefit for using Express is it’s flexibility. Frameworks such as Rails and Django have an opinionated way of building applications, while Express has no "best way" to do something. It is very flexible and pluggable. There are many modules available on npm that we can directly use alongside Express.
#
WhatExpress is considered a minimal and flexible Node.js web application framework. It comes with easy to use features for web and mobile applications. Express was developed by TJ Holowaychuk and is maintained by the Node.js foundation and numerous open source contributors.
With access to HTTP methods and middleware, Express is a great tool for creating APIs fairly quickly, without disconnecting us from the Node.js features we previously learned.
#
How#
Creating a Simple Express Application and API EndpointFirst, we’ll need to fork and clone the exercise project repository that has basic nodemon and babel configuration for you to be able to use ES6 Modules in Node.
Once you've forked and cloned the exercise repo, following the instructions in the README.md
to install the dependencies and create a .env
file.
Then, create and checkout a new branch called express-lesson
. You can follow along with this document on this branch, then when it's time to complete the exercise, hop back to the main branch.
In our index.js file, we need to import express. Then, we can create an express application by calling the express function that we import from the express module:
Now let’s say that we want to send a response to the client when they request from our main API endpoint “/”. We can easily set up a GET request handler with the following:
Lastly, we need to set our server to listen for requests at a specified port. Let’s do that now:
Now when we start our server with node index.js
, we will create our express application that listens for requests on port 3000.
NOTE: At this point, if the client sends a request to an endpoint that we haven’t specified (i.e. anything other than “/” in our example, the server will respond with “404 not found”).
#
RoutingWith Express, we can use HTTP utility methods to determine how our application responds to an HTTP request.
Above, we created an instance of express and named it ‘app’. Then we used the HTTP utility method ‘get’ to specify a route and request handler function to be executed per request.
Common request types are:
- GET
- POST
- PUT
- DELETE
#
Response MethodsThere are several response methods we can utilize in our request handler callback function.
res.download()
- prompts a file to be downloadedres.end()
- ends the response process, usually without any datares.json()
- sends a json responseres.redirect()
- redirects a request to a new path, default status code 302res.send()
- sends a response of various types, automatically sets “Content-Type”res.sendFile()
- sends a response as an octet stream, param must be an absolute pathres.sendStatus()
- sends a response status code
Example:
For this to work, I’ve imported express and path modules.
I created a variable ‘dataPath’ that holds the absolute path for my index.html file. Then, I used the express module to create an instance for my express app.
Next, I used the GET http method and specified the route and callback function for a request to this endpoint. Inside the callback function, I use a try/catch block to either send a success code along with my index.html file to the client, or server failure code with a json error if the request failed.
#
Using MiddlewaresMiddleware functions allow us to use functions that have access to the request object, the response object, and the next function. The next function is a function that executes the middleware functions and continues execution until the request-response cycle has ended.
How we can use middleware functions:
- Execute code
- Change the request and the response objects.
- End the request-response
- Call the next middleware in the stack with
next()
Let’s look at an example.
Middleware functions follow this syntax:
We can pass the request object, response object, and next callback function as parameters. Look familiar? It should. We’ve used middleware functions with our http utility methods (GET, POST, PUT, and DELETE).
Before, we used a middleware function to end the request-response cycle:
Now let’s use the next()
parameter to use another middleware function that logs request information to the console for each request to our router.
Here we have a requestInfo()
middleware function that logs the pathname and time of the request. The important part is invoking next()
to continue to the next
middleware function until our request-response cycle is complete.
We’ll use our requestInfo()
middleware before our GET http method.
Now, each time a request is made to any of our routes, we can see basic information in the console.
Cool! We can use this information to monitor calls to our API routes.
Let me introduce you to a useful npm http logger called morgan:
Let’s check the console now:
For Morgan’s “dev” option, it logs the http method, url endpoint, response status code, and time for response.
#
Handling Request BodiesNow let’s look at how to receive, parse and use request body data with express. First, we’ll have to add the express.json()
middleware above our routes. This middleware will look for incoming requests with json bodies, and parse them for our use.
Add app.use(express.json())
above your route endpoints:
Then all we have to do is create our POST endpoint.
Above, we created a POST request endpoint for “/contact”. In our request handler, we destructure the body
from the request object, and echo the body back to the client. Wicked easy!
#
Handling Request ParamsThere are many scenarios where we can utilize the url parameters sent with a request. You can access the url parameters through req.params
. Let’s take a look at the following PUT route:
Here, we’ve created a PUT request on “/users/:id”. We can destructure the url parameter id from req
.params to use either in our database queries or on our server.
#
Error HandlingIt is common to use try/catch blocks as we have to catch and account for errors on the server. We also can create a custom error handler middleware to write and send responses to the client when an error is raised. We can pass the error caught in the catch block to next(error)
, then handle the error with our own middleware.
Right above the app.listen()
method, add the following:
Now we have all of our server errors funnelling to our custom error handler middleware.
#
Takeaway- Express.js is a routing framework for Node Servers
- Middlewares are handlers that receive the
IncomingRequest
andServerResponse
objects as parameters, and anext()
function to pass the request/response objects to the next middleware. - Express.js adds helpful methods to the request and response objects for parsing request bodies, query parameters, search parameters, sending json bodies, files, or text.