Express Flashcards
LEARN EXPRESS ROUTES
Introduction
A huge portion of the Internet’s data travels over HTTP/HTTPS through request-response cycles between clients and servers. Every time that you use a website, your browser sends requests to one or many servers requesting resources. Every image, meme, post, and video is requested by a client and sent in a response from a server.
Express is a powerful but flexible Javascript framework for creating web servers and APIs. It can be used for everything from simple static file servers to JSON APIs to full production servers.
In this lesson, you will be fixing a machine called Express Yourself in the browser. The machine is supposed to provide functionality for clients to interact with various Expressions: JavaScript objects each containing ids, names, and emojis. Currently, it looks nice, but nothing works since there is no server in place! You will be learning all the necessary skills to implement an API allowing clients to Create, Read, Update, and Delete Expressions. These four functionalities together are known as CRUD, and they form the backbone of many real-life APIs.
LEARN EXPRESS ROUTES
Express is a Node module, so in order to use it, we will need to import it into our program file. To create a server, the imported express function must be invoked.
const express = require('express'); const app = express();
On the first line, we import the Express library with require. When invoked on the second line, it returns an instance of an Express application. This application can then be used to start a server and specify server behavior.
The purpose of a server is to listen for requests, perform whatever action is required to satisfy the request, and then return a response. In order for our server to start responding, we have to tell the server where to listen for new requests by providing a port number argument to a method called app.listen(). The server will then listen on the specified port and respond to any requests that come into it.
The second argument is a callback function that will be called once the server is running and ready to receive responses.
const PORT = 4001; //const PORT = process.env.PORT || 4001; app.listen(PORT, () => { console.log(`Server is listening on port ${PORT}`); });
In this example, our app.listen() call will start a server listening on port 4001, and once the server is started it will log ‘Server is listening on port 4001’.
LEARN EXPRESS ROUTES
Once the Express server is listening, it can respond to any and all requests. But how does it know what to do with these requests? To tell our server how to deal with any given request, we register a series of routes. Routes define the control flow for requests based on the request’s path and HTTP verb.
For example, if your server receives a GET request at /monsters, we will use a route to define the appropriate functionality for that HTTP verb (GET) and path (/monsters).
The path is the part of a request URL after the hostname and port number, so in a request to localhost:4001/monsters, the path is /monsters (in this example, the hostname is localhost, the port number is 4001).
The HTTP verb is always included in the request, and it is one of a finite number of options used to specify expected functionality. GET requests are used for retrieving resources from a server, and we will discuss additional request types in later exercises.
Express uses app.get() to register routes to match GET requests. Express routes (including app.get()) usually take two arguments, a path (usually a string), and a callback function to handle the request and send a response.
const moods = [{ mood: 'excited about express!'}, { mood: 'route-tastic!' }]; app.get('/moods', (req, res, next) => { // Here we would send back the moods array in response });
The route above will match any GET request to ‘/moods’ and call the callback function, passing in two objects as the first two arguments. These objects represent the request sent to the server and the response that the Express server should eventually send to the client.
If no routes are matched on a client request, the Express server will handle sending a 404 Not Found response to the client.
LEARN EXPRESS ROUTES
Express tries to match requests by route, meaning that if we send a request to <server>:<port>/api-endpoint, the Express server will search through any registered routes in order and try to match /api-endpoint.</port></server>
Express searches through routes in the order that they are registered in your code. The first one that is matched will be used, and its callback will be called.
In the example to the right, you can see two .get() routes registered at /another-route and /expressions. When a GET /expressions request arrives to the Express server, it first checks /another-route‘s path because it is registered before the /expressions route. Because /another-route does not match the path, Express moves on to the next registered middleware. Since the route matches the path, the callback is invoked, and it sends a response.
If there are no matching routes registered, or the Express server has not sent a response at the end of all matched routes, it will automatically send back a 404 Not Found response, meaning that no routes were matched or no response was ultimately sent by the registered routes.
LEARN EXPRESS ROUTES
Routes become much more powerful when they can be used dynamically. Express servers provide this functionality with named route parameters. Parameters are route path segments that begin with : in their Express route definitions. They act as wildcards, matching any text at that path segment. For example /monsters/:id will match both/monsters/1 and /monsters/45.
Express parses any parameters, extracts their actual values, and attaches them as an object to the request object: req.params. This object’s keys are any parameter names in the route, and each key’s value is the actual value of that field per request.
LEARN EXPRESS ROUTES
Express allows us to set the status code on responses before they are sent. Response codes provide information to clients about how their requests were handled. Until now, we have been allowing the Express server to set status codes for us. For example, any res.send() has by default sent a 200 OK status code.
LEARN EXPRESS ROUTES
Parameters are extremely helpful in making server routes dynamic and able to respond to different inputs. Route parameters will match anything in their specific part of the path, so a route matching /monsters/:name would match all the following request paths:
~~~
/monsters/hydra
/monsters/jörmungandr
/monsters/manticore
/monsters/123
~~~
In order for a request to match a route path, it must match the entire path, as shown in the diagram to the right. The request arrives for /expressions/1. It first tries to match the /expressions route, but because it has additional path segments after /expressions, it does not match this route and moves on to the next. It matches /expressions/:id because :id will match any value at that level of the path segment. The route matches, so the Express server calls the callback function, which in turn handles the request and sends a response.
LEARN EXPRESS ROUTES
HTTP Protocol defines a number of different method verbs with many use cases. So far, we have been using the GET request which is probably the most common of all. Every time your browser loads an image, it is making a GET request for that file!
This course will cover three other important HTTP methods: PUT, POST, and DELETE. Express provides methods for each one: app.put(), app.post(), and app.delete().
PUT requests are used for updating existing resources. In our Express Yourself machine, a PUT request will be used to update the name or emoji of an expression already saved in our database. For this reason, we will need to include a unique identifier as a route parameter to determine which specific resource to update.
LEARN EXPRESS ROUTES
Matching By HTTP Verb
Express matches routes using both path and HTTP method verb. In the diagram to the right, we see a request with a PUT verb and /expressions (remember that the query is not part of the route path). The path for the first route matches, but the method verb is wrong, so the Express server will continue to the next registered route. This route matches both method and path, and so its callback is called, the necessary updating logic is executed, and the response is sent.
LEARN EXPRESS ROUTES
POST is the HTTP method verb used for creating new resources. Because POST routes create new data, their paths do not end with a route parameter, but instead end with the type of resource to be created.
For example, to create a new monster, a client would make a POST request to /monsters. The client does not know the id of the monster until it is created and sent back by the server, therefore POST /monsters/:id doesn’t make sense because a client couldn’t know the unique id of a monster before it exists.
Express uses .post() as its method for POST requests. POST requests can use many ways of sending data to create new resources, including query strings.
The HTTP status code for a newly-created resource is 201 Created.
LEARN EXPRESS ROUTES
DELETE is the HTTP method verb used to delete resources. Because DELETE routes delete currently existing data, their paths should usually end with a route parameter to indicate which resource to delete.
Express uses .delete() as its method for DELETE requests.
Servers often send a 204 No Content status code if deletion occurs without error.
LEARN EXPRESS ROUTES
Adding Animals Routes
1.In your app.js file, Create a GET /animals route to return an array of all animals.
2.Create a GET /animals/:id route to respond with a single animal.
3.Create a PUT /animals/:id route to update an animal in animals and send back the updated animal.
4.Create a POST /animals route to add new animals to the animals and respond with the new animal.
5.Create a DELETE /animals/:id route to delete animals by ID.
LEARN EXPRESS ROUTES
const express = require('express'); const app = express(); const PORT = process.env.PORT || 4001; const battlefields = { fortSumter: { state: 'SC', }, manassas: { state: 'VA', }, gettysburg: { state: 'PA', }, antietam: { state: 'MD', } } app.listen(PORT, () => { console.log(`Server is listening on port ${PORT}`); }); app.get('/battlefields/:name', (req, res, next) => { const battlefieldName = req.params.name; const battlefield = battlefields[battlefieldName] if (battlefield) { res.send(battlefield); } else { res.status(404).send(); } });