📝
marcyannotes
  • Welcome
  • Student Guidelines & Policies
    • Student Handbook
    • AI Policy
    • Academic Calendar
  • Environment Setup
    • Local Environment Setup - Mac
    • Local Environment Setup - Windows
    • GitHub Setup
    • Postgres Setup
  • Fullstack Software Engineering Curriculum
    • Overview
    • How-Tos
      • How To Code at Marcy: Code Style Guide
      • How to Do Short Response and Coding Assignments
      • How to Debug
      • How to PEDAC
      • How to Create Projects with Vite
      • How to Deploy on GitHub Pages
      • How to Deploy on Render
    • Mod 0 - Command Line Interfaces, Git, and GitHub
      • Mod 0 Overview
      • Command Line Interfaces
      • Git & GitHub
      • Git Pulling & Merging
      • Git Branching & PRs
      • Pair Programming: BONUS
    • Mod 1 - JavaScriptFundamentals
      • Mod 1 Overview
      • Intro to Programming
      • Errors
      • Node & Node Modules
      • Variables, Functions & String Methods
      • Control Flow, typeof, and Math
      • Loops
      • Arrays
      • Objects
      • Higher Order Functions: Callbacks
      • Higher Order Functions: Array Methods
      • Regex
    • Mod 2 - HTML, CSS & the DOM
      • Mod 2 Overview
      • HTML
      • CSS
      • Accessibility (a11y)
      • The DOM
      • Events
      • Forms
      • The Box Model and Positioning
      • Flexbox
      • Grid & Media Queries
      • ESModules
      • LocalStorage
    • Mod 3 - Async & APIs
      • Mod 3 Overview
      • Promises
      • Fetch
      • Building a Fetching App
      • Async & Await
    • Mod 4 - Project Week!
      • Project Week Overview
    • Mod 5 - Object-Oriented Programming
      • Mod 5 Overview
      • Intro to OOP, Encapsulation, Factory Functions, and Closure
      • Classes
      • Private & Static
      • Has Many/Belongs To
      • Polymorphism
    • Mod 6 - Data Structures & Algorithms
      • Mod 6 Overview
      • Stacks & Queues
      • Nodes & Linked Lists
      • Singly & Doubly Linked Lists
      • Recursion
      • Trees
    • Mod 7 - React
      • Mod 7 Overview
      • Intro to React
      • Events, State, and Forms
      • Fetching with useEffect
      • Building a Flashcards App
      • React Context
      • Global Context Pattern
      • React Router
    • Mod 8 - Backend
      • Mod 8 Overview
      • Intro to Express
      • Building a Static Web Server with Middleware
      • Securing API Keys with Environment Variables
      • Building a RESTful API with MVC
      • SQL and Databases
      • JOIN (Association) SQL Queries
      • Knex
      • Your First Fullstack App!
      • Migrations & Seeds
      • Schema Design & Normalization
      • Hashing Passwords with Bcrypt
  • Code Challenge Curriculum
    • Unit 0
      • Lecture: Functions in JS
      • CC-00: Functions and Console Logs
      • CC-01: Conditionals
      • CC-02: Conditionals 2
    • Unit 1
      • CC-03: For Loops
      • CC-04: For Loops and Conditionals
      • CC-05: For Loops and Conditionals 2
    • Unit 2
      • CC-06: String Mutations
      • CC-07: Array Iteration
      • CC-08: String Mutation and Array Iteration
      • CC-09: Array Mutations
      • CC-10: Reading Objects
      • CC-11: Objects
      • CC-12: Objects
      • Unit 2 Diagnostic
    • Unit 3
      • Intro to PEDAC (and Algorithms)
      • validTime
      • fizzBuzz (array)
      • digitSumDifference
      • firstNotRepeating
      • compareEvenAndOddSum
      • countVowelConsonants
      • finalHP
      • canMakeTriangle
    • Unit 4
    • Unit 5
    • Unit 6
    • Unit 7
    • Unit 8
    • Sorting
Powered by GitBook
On this page
  • Terms
  • Client Server Interactions
  • Express
  • The app object is the hub of the server application
  • Endpoints
  • Controllers
  • Query Parameters
  • Listening: Host and Ports
  1. Fullstack Software Engineering Curriculum
  2. Mod 8 - Backend

Intro to Express

PreviousMod 8 OverviewNextBuilding a Static Web Server with Middleware

Last updated 7 months ago

Follow along with code examples !

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 Application — an application that listens for requests and sends responses.

  • Host and Port - the address of a server application

  • 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

  • Express app — an object that "listens" for requests and "routes" to the appropriate controller.

  • Controller — a callback function that parses a request and sends a response for a particular endpoint

  • Query parameters — a portion of a URL used to filter and sort the requested data. They are appended to the end of a URL using the syntax ?queryParam=value.

Client Server Interactions

So how do the client and server interact?

  1. A client sends a request to the server

  2. The server receives the request and routes it to the proper controller

  3. The controller parses the request and sends a response

  4. The client receives the response and renders the data!

Q: What are the responsibilities of a client?
  • 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?
  • 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

Express is a minimal and flexible Node.js web application framework that provides a robust set of features for web and mobile applications.

To use express, we start by installing it

npm i express

The main export of Express is the express function which creates an object, often named app.

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

The app object is the hub of the server application

This app object lets us define our server's behavior. It:

  • Listens — it waits for incoming requests and...

  • Routes — it directs each request to a controller based on the specific endpoint of the request

Here is a simple example. For now, just focus on the high-level structure of the application. Look for controllers, endpoints, and where the app "listens".

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

// controllers
const serveIndex = (req, res, next) => {
  res.sendFile(__dirname + '/index.html');
}
const serveAbout = (req, res, next) => {
  res.send('<h1>About</h1>');
}
const serveHello = (req, res, next) => {
  res.send('hello');
}
const serveData = (req, res, next) => {
  const data = [{ name: 'ben' }, { name: 'zo' }, { name: 'carmen' }];
  res.send(data);
}

// endpoints
app.get('/', serveIndex);
app.get('/about', serveAbout);
app.get('/api/hello', serveHello);
app.get('/api/data', serveData);

// listen
const port = 8080;
app.listen(port, () => console.log(`listening at http://localhost:${port}`)); 
  • const app = express() creates the Express app object

  • A controller is a callback function that parses a request and sends a response. It will be invoked by the app when the associated path is hit.

  • app.get(endpoint, controller) defines which controller will be invoked for the specified endpoint.

  • app.listen(port, callback) "starts" the server application. Since the application runs locally, it will be accessible at http://localhost:8080, where 8080 is the port. All of the endpoints above are extensions of this host and port.

Let's look closer at how to make a controller.

Endpoints

An endpoint is a unique URL path that a server makes available for clients to send requests to using different methods like GET, POST, PUT, DELETE, etc... Examples include /api/data or /api/users/:id, where :id represents a dynamic path parameter.

app.get('/', serveIndex);
app.get('/about', serveAbout);
app.get('/api/hello', serveHello);
app.get('/api/data', serveData);
  • The associated endpoints for each controller begin with / and are appended to the host:port

    • For example, sending a GET request to http://localhost:8080/about will invoke the serveAbout controller

Q: What does .get mean? Why is it called that?

These endpoints are designed to handle GET requests. If we wanted to assign controllers for endpoints that handle POST/PATCH/DELETE requests, we could use app.post or app.patch or app.delete.

Q: Why do you think the serveHello and serveData endpoints begin with /api while the other two endpoints do not?

Typically, endpoints that serve data will begin with /api, while endpoints that serve HTML do not.

Controllers

Controllers in Express.js are JavaScript functions responsible for handling the logic associated with specific endpoints. When a client sends a request to a particular endpoint, Express invokes the corresponding controller to process the request and generate a response.

const serveIndex = (req, res, next) => {
  res.sendFile(__dirname + '/index.html');
}
const serveAbout = (req, res, next) => {
  res.send('<h1>About</h1>');
}
const serveHello = (req, res, next) => {
  res.send('hello');
}
const serveData = (req, res, next) => {
  const data = [{ name: 'ben' }, { name: 'zo' }, { name: 'carmen' }];
  res.send(data);
}

app.get('/', serveIndex);
app.get('/about', serveAbout);
app.get('/api/hello', serveHello);
app.get('/api/data', serveData);
  • To keep things simple, these controllers only use the res object.

  • The res.send and res.sendFile methods allow us to send different kinds of data. res.sendStatus lets us send just a status code without data.

  • When sending files, the __dirname keyword returns the absolute path to the current file folder.

Key points about controllers:

  • Invocation: Controllers are invoked by Express.js when a matching route (endpoint) is requested by a client.

  • Responsibilities: Controllers handle various tasks, including interacting with databases, processing data, and generating responses based on the request.

  • Function Parameters: Controllers typically receive three parameters:

    • req: An object containing information about the incoming request (the request method, URL, headers, query parameters, and body, etc...)

    • res: An object with functions for sending a response to the client (res.send(), res.sendStatus() etc...)

    • next: A function that passes control to the next middleware function in the request-response cycle. It is commonly used in middleware to delegate processing to subsequent functions.

Query Parameters

Our controllers feel stiff. Let's make them more dynamic using query parameters!

Right now, if I request http://localhost:8080/api/hello, the serveHello controller is triggered which sends back the string 'hello'. And it will always send the string 'hello'

const serveHello = (req, res, next) => {
  res.send('hello');
}

Query parameters are added to the end of request URL to tell the server to modify the requested data in some way.

They are appended to the end of a request URL starting with a ? and followed by key=value pairs separated by &s:

http://host/api/endpoint?param1=value&param2=value

Q: In the example above where we send the request to http://localhost:8080/api/hello, how would we add query parameters to specify a first and last name that we want the server to say hello to?

If a client wants to send a request to the /api/hello endpoint and add query parameters for a first and last name, the full URL could be:

http://localhost:8080/api/hello?first=jane&last=doe.

In this example, there are two parameters named first and last with the values jane and doe.

Accessing Query Parameter Values in a Controller

In the server code, we can access the value of query parameters using req.query object.

Each key=value query parameter provided in the request URL will show up as a property on the req.query object:

const serveHello = (req, res, next) => {
  const first = req.query.first;
  const last = req.query.last;
  if (first && !last) {
    return res.send(`hello ${first} ${last}!`);
  }
  res.send('hello')
}

app.get('/api/hello', serveHello);
  • In this example, we get the first value using req.query.first and the last value using req.query.last

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

  • Now,

    • http://localhost:8080/api/hello?first=ben&last=spector will send back hello ben spector

    • http://localhost:8080/api/hello?first=ben will send back hello

    • http://localhost:8080/api/hello will send back hello

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) => {
  // if no filter is provided, req.query.filter will be undefined. use "" as a backup value
  const filterTerm = req.query.filter || "";
  // filter the gifs.data array using the title (see the gifs.json file) 
  const filteredData = gifs.data.filter((gif) => gif.title.toLowerCase().includes(filterTerm));
  // send back the filteredData
  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.

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).

To build our server application, we will use Express. According to their :

docs
here
Terms
Client Server Interactions
Express
The app object is the hub of the server application
Endpoints
Controllers
Query Parameters
Accessing Query Parameter Values in a Controller
Challenge
Listening: Host & Ports
express diagram
host port