LogoLogo
  • FAC Curriculum
  • archive
    • Node & npm introduction
    • developer
      • Programming Paradigms
    • handbook
      • Asking for help
      • Coaching groups
      • Code review
      • Course rules
      • Debugging
      • Employment schedule and material delivered in FAC20
      • GitHub Workflow
      • Glossary or terms
      • Presentation Guidance
      • Equality, Diversity and Inclusion
      • Installation guide
      • Learning circles
      • Mentoring guidance
      • What to expect from your mentors
      • One-day projects
      • Pair programming
      • Portfolio
      • Questions for problem solving
      • Progress Logs
      • Final project report
      • Managing software projects
      • Project Presentations
      • Project roles
      • Projects
      • Retrospectives
      • Role Circles
      • Safeguarding policy
      • Technical Spikes
      • System requirements
      • Tech for Better
      • User Manuals
      • Wellbeing Support
      • project-docs
        • What makes a mentor?
        • Product Handover
        • Sprint Planning
        • Tech for Better Presentations
        • User Research & Usability Testing
    • foundation
      • full-stack
        • Learning Outcomes
        • project
      • testing
        • project
        • spikes
  • docs
    • Contributing to the curriculum
    • Curriculum intent
    • Curriculum process
  • src
    • About our curriculum
    • course
      • Code of Conduct
      • Docker
      • .NET and Umbraco
      • Getting started
      • Founders and Coders coursebook
      • KSB's
      • Mini projects
      • Revision checklist
      • Svelte
      • TypeScript
      • handbook
        • Software Developer Handbook
        • Software Foundation Handbook
      • precourse
        • Before you start the course
        • Installation List
      • syllabus
        • developer
          • app
            • learning-outcomes
            • project
            • schedule
            • spikes
          • introduction
            • learning-outcomes
            • project
            • resources
            • schedule
          • week00-pre-course
            • We'd like you to spend some time before starting the course working on useful fundamentals.
            • spikes
          • week01-project01-basics
            • Employability introduction
            • Homework
            • learning-outcomes
            • Week of September 9th
            • project
            • resources
            • schedule
            • spikes
          • week02-project02-chatbot
            • employability
            • Homework
            • learning-outcomes
            • Week of September 16th
            • project
            • resources
            • schedule
            • spikes
          • week03-project03-server
            • Learning Outcomes
            • Week of September 23th
            • The Amazin' Quizzer API Backend
            • resources
            • schedule
          • week04-project03-frontend
            • learning-outcomes
            • Week of September 30th
            • UI for Quizzer App
            • resources
            • schedule
          • week05-project03-test-deploy
            • Testing and deployment
            • Week of October 7th
            • project
            • resources
            • schedule
          • week06-project04-databases
            • learning-outcomes
            • Week of October 14th
            • project
            • Databases
            • schedule
          • week07-project04-authentication
            • Learning Outcomes
            • Week of October 21st
            • project
            • resources
            • schedule
          • week08-project04-test-deploy
            • Learning Outcomes
            • Week of October 28th
            • project
            • resources
            • schedule
          • week09-reading-week
            • Learning Outcomes
            • overview
            • Project
            • Resources
            • schedule
          • week10-project05-DOTNET-intro
            • Learning Outcomes
            • overview
            • project
            • Resources
            • schedule
          • week11-project05-DOTNET-testing
            • Testing and deployment
            • Week of November 18th
            • project
            • Resources
            • schedule
          • week12-project05-DOTNET-deploy
            • Learning Outcomes
            • Week of November 25th
            • project
            • Resources
            • schedule
            • Spikes
          • week13-TFB-design
            • Learning Outcomes
            • overview
            • Project
            • Resources
            • schedule
            • Design Week Spikes
          • week14-TFB-build
            • Learning Outcomes
            • overview
            • Project
            • DevOps Resources
            • schedule
            • Spikes
          • week15-TFB-build
            • Learning Outcomes
            • overview
            • Project
            • Resources
            • schedule
            • Spikes
          • projects
            • in-house-design
              • Learning Outcomes
              • Project
              • Resources
              • schedule
              • Design Week Spikes
        • foundation
          • Obsolete-full-stack
            • project
          • post-course
            • Homework
            • schedule
        • portfolio
          • fruit-shop
            • learning-outcomes
            • project
            • resources
          • game
            • learning-outcomes
            • project
            • resources
          • hobby-page
            • learning-outcomes
            • project
            • resources
          • movie-data
            • learning-outcomes
            • project
            • resources
          • project-gallery
            • learning-outcomes
            • project
            • resources
          • website
            • learning-outcomes
            • project
            • JavaScript
        • tfb
          • week 1
            • Introduction (45 minutes)
            • Further reading
          • week 10
            • content
            • resources
          • week 11
            • What will we be doing this week?
            • resources
          • week 12
            • What will we be doing this week?
            • Further reading
          • week 2
            • Discover (90 minutes)
            • resources
          • week 3
            • content
            • resources
          • week 4
            • Mapping the user journey (90 minutes)
            • resources
          • week 5
            • Figma Workshop 1 (90 minutes)
            • Further reading
          • week 6
            • Figma Workshop 2 (90 minutes)
            • resources
          • week 7
            • Product pitches & Selection (90 minutes)
            • resources
          • week 8
            • content
            • resources
          • week 9
            • content
            • resources
    • learn
      • DOTNET
        • Introduction to .NET
      • auth
        • Authenticating web apps
      • database
        • Persisting data with SQLite and Node
      • dotnet-two
        • Dependency injections and interfaces in .NET
      • form-validation
        • Form validation
      • react
        • Building client-side apps with React
      • server
        • HTTP servers with Node & Express
      • typescript
        • TypeScript
    • mentoring
      • design-week
        • Analysis Workshop
        • Code planning
        • Definition Workshop
        • Discovery Workshop
        • Figma introduction
        • Usability testing
        • User Research
    • resources
      • http
        • introduction
    • workshops
      • cookie-auth
        • index
      • creating-promises
        • index
      • css-layout
        • index
      • cypress-testing
        • index
      • database-testing
        • index
      • dev-tooling
        • Developer tooling
      • dom-challenge
        • index
      • dom-rendering
        • index
      • es-modules
        • index
      • express-middleware
        • Express middleware
      • first-class-functions
        • index
      • form-validation
        • index
      • functions-callbacks-async
        • Functions, callbacks, & async JavaScript
      • git-intro
        • Introduction to Git
      • git-terminal
        • Using Git in the terminal
      • git-workflow
        • Git workflow
      • github-projects
        • GitHub Projects Workflow Workshop
      • heroku-sql-challenge
        • index
      • html-forms
        • index
      • learn-a11y
        • index
        • starter-files
          • solution
            • Accessibility solution explanation
      • learn-fetch
        • index
      • learn-integration-testing
        • index
      • learn-testing
        • Learn testing in JavaScript
      • learn-unit-testing
        • index
      • node-error-handling
        • Node error-handling
      • node-express-server
        • Node and Express HTTP server
      • node-npm-intro
        • Node & npm introduction
      • node-postgres
        • Learn Postgres with Node
      • node-scripting-challenge
        • index
      • password-security
        • index
      • promise-practice
        • index
      • react-components
        • React components
      • react-fetch
        • index
      • react-forms
        • React forms
      • react-refactor-classes
        • index
      • react-state-effects
        • React state & effects
      • real-world-fetch
        • index
      • scope-challenge
        • Scope debugging challenge
      • semantic-html
        • index
      • server-side-forms
        • Server-side forms
      • session-auth
        • Session authentication
      • sql-intro
        • index
      • tdd-array-methods
        • index
Powered by GitBook
On this page
  • Middleware
  • Setup
  • Our first middleware
  • Authentication middleware
Export as PDF
  1. src
  2. workshops
  3. express-middleware

Express middleware

Learn how to create your own middleware for Express servers

Learn how to write your own Express middleware to do logging and authentication.

Middleware

Express is built around middleware. Middleware are functions that receive a request, do something with it, then either pass the request on to the next middleware or send a response (ending the chain).

Technically all route handlers are middleware, since they fit the above definition. However middleware usually transform the request in some way and don't actually send a response.

For example the built in express.urlencoded middleware grabs the HTTP request body, turns it into an object, then attaches it to the request object. This allows subsequent handlers to easily access it at request.body. The 3rd party cookie-parser middleware does the same for cookies. We're going to learn how to create our own middleware functions.

Setup

  1. Download the starter files and cd in

  2. Run npm install to install all the dependencies

  3. Run npm run dev to start the development server

Visit http://localhost:3000 to see the workshop app. You can "log in" by entering an email, which will be saved as a cookie so the server can identify you.

Our first middleware

It would be useful if our server logged each incoming request to our terminal. That way we can see a log of what's happening as we use our server locally.

Usually we match our handlers to specific routes (e.g. server.get("/about", ...). However we can run a handler for every route by using server.use:

server.use((req, res) => {
  console.log(`${req.method} ${req.url}`);
});

This will log the method and URL for every request the server receives (e.g. GET / or POST /submit). Unfortunately that's all it will do, as this handler never tells the next handler in the chain to run. This will cause all requests to time out, since the server never sends a response using response.send.

We can fix this with the third argument all handlers receive: next. This is a function you call inside a handler when you want Express to move on to the next one.

server.use((req, res, next) => {
  console.log(`${req.method} ${req.url}`);
  next();
});

This tells Express to run the logger handler before every request, then move on to whatever handler is queued for that route. E.g. if the user requests the home page (GET /) this handler will run, log the method/URL, then pass on to the next handler that matches GET /, which will send an HTML response.


Authentication middleware

Note: we are just storing all the session info about the user in an object in-memory. In a real app you'd want this to live in a persistent store like a database.

Accessing the user

Currently we are accessing the user cookie in three handlers (GET /, GET /profile and GET /profile/settings). We have to grab the session ID from the signed cookies, then look the session info up in the sessions object. This ends up being quite a lot of code repeated whenever we want to find out info about which user is currently logged in. We can create a middleware to handle this repeated task.

We don't know which routes will want to access the logged in user value so we'll set this middleware on the whole app using server.use. We'll mimic the other middleware we're using and add the user value to the req object. This lets us pass values down through the request chain to later handlers.

Challenge 1.1

  1. Create a new middleware that runs before every request.

  2. It should read the sid cookie and find the session info in the sessions object

  3. Then create a "session" property on the request object containing that info

  4. Finally call the next function to tell Express to move on to the next handler.

  5. Change each handler that currently gets the session cookie to instead grab the info from req.session.

server.use((req, res, next) => {
  const sid = req.signedCookies.sid;
  const sessionInfo = sessions[sid];
  if (sessionInfo) {
    req.session = sessionInfo;
  }
  next();
});

server.get("/", (req, res) => {
  const user = req.session;
  // ...
});

server.get("/profile", (req, res) => {
  const user = req.session;
  // ...
});

server.get("/profile/settings", (req, res) => {
  const user = req.session;
  // ...
});

Protecting routes

Currently our GET /profile route is broken. If the user isn't logged in we get an error trying to access user.email (since req.session is undefined). It would be better to show a "Please log in" page for unauthenticated users.

Challenge 1.2

  1. Amend the GET /profile handler to check whether there is a session.

  2. If not send a 401 HTML response with an error message in the h1 and a link to the /log-in page.

server.get("/profile", (req, res) => {
  const user = req.session;
  if (!user) {
    res.status(401).send(`
      <h1>Please log in to view this page</h1>
      <a href="/log-in">Log in</a>
    `);
  } else {
    res.send(`<h1>Hello ${user.email}</h1>`);
  }
});

Now you should see the "please log in" page if you visit /profile when you aren't logged in. However the GET /profile/settings route has the same problem.

We could copy paste the above code, but it would be better to avoid the duplication and move this logic into a middleware that makes sure users are logged in.

Challenge 1.3

  1. Create a new middleware function named checkAuth that takes req, res and next as arguments.

  2. If there is no req.session respond with the 401 HTML.

  3. If there is a req.session call next to move on to the next handler.

  4. Add this middleware in front of the handler for any route we want to protect. We don't want this middleware running on all routes, since some of them are public.

Hint: you can set multiple middleware/handlers for a route by passing multiple arguments.

server.get("/example", doSomething, anotherHandler, (req, res) => {
  // ...
});
function checkAuth(req, res, next) {
  const user = req.session;
  if (!user) {
    res.status(401).send(`
      <h1>Please log in to view this page</h1>
      <a href="/log-in">Log in</a>
    `);
  } else {
    next();
  }
}

server.get("/profile", checkAuth, (req, res) => {
  // ...
});

server.get("/profile/settings", checkAuth, (req, res) => {
  // ...
});
Previousexpress-middlewareNextfirst-class-functions

Last updated 3 years ago