1. Intro to Express

Follow along with code examples here!

In this first lesson, we're going to learn the basics of Express and build and deploy a simple server application.

Table of Contents:

Terms

  • Server / Client — a server is a computer that provides a service to another computer and its user, called the client.

  • HTTP Server Application — a computer program that enables a computer to listen for and respond to HTTP requests.

  • Express — the most popular Node framework for building HTTP server applications

  • Express app — an object generated by Express that configures the http server application.

  • Host and Port - the address of a server application

  • http://localhost — the host when running a server application on your own computer

  • Endpoint — a specific URL path of a server that clients can "hit" (send requests to) to create/read/update/delete data. For example: /api/data or /api/users/:id

  • Controller — a callback function invoked asynchronously when the associated endpoint is targeted. It parses the request and sends back a response.

  • Query parameters — a portion of a URL used to filter and sort the requested data.

    • Query Parameters are appended to the end of a URL with a ? and separated with &

    • e.g. /api/clothing/search?category=tops&sort=ascending

What is an HTTP Server Application?

A server is a computer that provides a service to another computer and its user, called the client. Every website that you visit and every web API that you've used is powered by a server and your computer is the client!

But how do they know what to do when a request comes in?

To handle incoming requests, web servers run a HTTP server application — a computer program that enables the computer to listen for and respond to HTTP requests coming from clients.

  • Send a request to https://dog.ceo/api/breeds/image/random and there is an HTTP server application running on the Dog API's servers that will send back a dog image.

  • Send a request to https://www.google.com/ and there is an HTTP server application running on Google's servers that sends back the HTML, CSS, and JavaScript that make Google run on your browser.

  • Log in to your account on Instagram and the frontend application sends a request on your behalf to the Instagram's servers to confirm your login information.

You too can build HTTP server applications that can do all of this and today, we'll begin learning about Express, the most popular Node framework for building HTTP server applications.

Client Server Interactions Review

So how do the client and server interact?

  1. A client sends a request to the server

  2. The server receives the request and determines what kind of response to send

  3. The client receives the response and does something using the data!

express diagram
Q: What are the responsibilities of a client application?
  • Rendering HTML, CSS, and JS

  • Request information from a server (get requests)

  • Providing information to a server (post/patch/delete requests)

  • Reading data received from a server

Q: What are the responsibilities of a server application?
  • Serving static files that live on the server (HTML, CSS, and JS files)

  • Fetching and serving data from a third-party API that requires an API key

  • Managing and serving data from the server's own database

Express

To build our HTTP server application, we will use Express. Express is the most popular Node framework for building HTTP server applications.

To use express, we start by installing it as a dependency:

npm i express

The main export of Express is the express function which returns an object that we can use to configure the server application, often named app.

We typically start by setting the port on which the server will be "listening" with app.listen():

// index.js
const express = require('express');
const app = express();

const port = 8080; 

// run the server application on port 8080 of the current host (http://localhost during development)
app.listen(port); 

During development, the host is http://localhost so the server is listening at http://localhost:8080.

Connecting to your Server

Try visiting http://localhost:8080 in your browser and you'll see that the site can't be reached. That's because we haven't turned our server on!

Run node index.js to start the server and visit http://localhost:8080 again. This time, you'll connect to your server! But nothing is being served yet — that's what we'll do next!

When we deploy this application on a server hosting service, our code stays the same but our host will change! The deployment service typically will handle assigning the application a port.

Endpoints and Controllers

When we send a request to an API, we typically will send the request to a specific endpoint, such as https://dog.ceo/api/breeds/image/random. The API may provide multiple endpoints that each respond differently, such as https://dog.ceo/api/breeds/list/all.

When we send a request to an API, say https://dog.ceo, the API's server application defines

  1. The endpoints that clients can send requests to (api/breeds/image/random or /api/breeds/list/all)

  2. How each endpoint will respond (with a random image or a list of all dog breeds)

When designing our own API's with express, we add endpoints and controllers using the app.get(endpoint, controller) method.

  • The endpoint parameter is a string that determines where on the server the client can send a request to

  • The controller parameter is a callback function that is invoked asynchronously when the associated endpoint is requested. They determine how the server responds.

const express = require('express');
const app = express();

// All endpoints start at `/` which is the "root" of the server
app.get('/', (req, res, next) => {
  res.send('You are connected!');
})

// Typically, we start endpoints with `/api` to separate data endpoints from static asset endpoints
app.get('/api/hello', (req, res, next) => {
  res.send('Hello');
})

const port = 8080; 
app.listen(port); 

All endpoints are appended to the host and port.

  • When the server is listening at http://localhost:8080, the / endpoint is accessible at http://localhost:8080/

  • When the server is listening at http://localhost:8080, the /api/hello endpoint is accessible at http://localhost:8080/api/hello

When you visit http://localhost:8080, you are technically hitting the / endpoint (the / is implied)

Controllers

A Controller is a callback function invoked asynchronously when the associated endpoint is targeted. It parses the request and sends back a response.

To keep things organized, it is a best practice to write controllers as named functions.

Every controller is provided with three values (req, res, and next) though all three aren't always used by the controller:

const serveHello = (req, res, next) => {
  res.send('hello');
}
const serveData = (req, res, next) => {
  const data = [{ name: 'ben' }, { name: 'zo' }, { name: 'carmen' }];
  res.send(data);
}
const serveStatus = (req, res, next) => {
  res.sendStatus(200);
}

app.get('/api/hello', serveHello);
app.get('/api/data', serveData);
app.get('/api/ping', serveStatus);

The res parameter is an object with methods for configuring the response we want to send to the client.

  • The res.send method allows us to send data to the client.

  • The res.sendStatus method lets us send just a status code without data.

These controllers are quite simple as they just send back a pre-defined response, but controllers can do quite complex tasks!

The next parameter will be discussed in the next lesson, but what about the req parameter?

Query Parameters

The req parameter is an object containing information about the incoming request. One way we can make use of the request object req is by accepting query parameters.

Query parameters are added to the end of request URL to tell the server to modify the requested data in some way. They are often used for search queries or to filter results. Google adds a q query parameter when you provide a search query:

https://www.google.com/search?q=express+node

Query parameters are added in key=value pairs to the end of a URL following a ?. In the example above q is the name of the query parameter with the value express+node (the + is just used to indicate a space).

When multiple query parameters are needed, they are each separated by an ampersand &. For example, if we wanted to include a first and last name to the /api/hello endpoint, we could write:

localhost:8080/api/hello?first=ben&last=spector

Using req.query

In the controller code, each key=value query parameter will show up in the req.query object with a string value.

So, we can modify our serveHello controller like so:

const serveHello = (req, res, next) => {
  console.log(req.query); // { first: "ben", last: "spector" }

  const { first, last} = req.query;
  if (!first || !last) {
    return res.send(`hello stranger!`);
  }
  res.send(`hello ${first} ${last}!`);
}

app.get('/api/hello', serveHello);
  • In this example, we get the first and last values by destructuring the req.query object.

  • Before sending a response, we make sure to check that both query parameters are provided, otherwise we just send 'hello stranger!'.

Query Parameter Challenge

How can we modify the serveData function so that it filters the array of objects by the .name property using a ?filter=value query parameter?

Solution
const serveData = (req, res, next) => {
  const filter = req.query.filter
  const data = [{ name: 'ben' }, { name: 'zo' }, { name: 'carmen' }];

  if (!filter) res.send(data);
  const filteredData = data.filter((item) => item.name === filter);
  res.send(filteredData);
}

Listening: Host and Ports

The last lines of code "turn on" the server. That is, they make the server start listening for requests.

const port = 8080;
app.listen(port, () => console.log(`listening at http://localhost:${port}`)); 
  • The first argument defines the port number

  • The second argument is a callback that gets executed when the server starts listening. It is often used to print out the host and port.

host port

The host is like our home address.

  • localhost is a hostname that refers to the current device used to access it.

  • localhost is an alias for 127.0.0.1 which is the standard address used.

  • localhost === 127.0.0.1

Ports are the "front doors" of our application. (There are a lot of doors!)

  • :8080 is considered as a different "door" from :5500

Which port should you use? It doesn't really matter, but here are some ones that our instructors like to use and some standards that are used:

  • 8080 (What I use)

  • 4321 (Mike's favorite because it is fun)

  • 3000 (What other people use)

  • 5500 (What other other people use)

  • 80 (Standard unencrypted HTTP port)

  • 443 (Standard encrypted HTTPS port)

Just pick one that isn't being used!

How do you know which ones aren't being used? Your computer will likely tell you if one is currently in use — just use a different one (or kill the process that is currently using that port).

Last updated