Skip to content

Instantly share code, notes, and snippets.

@ReaganS94
Created October 20, 2025 10:13
Show Gist options
  • Select an option

  • Save ReaganS94/756361ba10c311e37e419b24f81e3af9 to your computer and use it in GitHub Desktop.

Select an option

Save ReaganS94/756361ba10c311e37e419b24f81e3af9 to your computer and use it in GitHub Desktop.

Route-level middleware exercises for the MVC starter

Context: you already have the MVC starter shown in the prompt. For these tasks, make changes only in routes/student_routes.js. Do not modify controllers, schemas, or server.js. Keep changes minimal and focused on route-level middleware.

Ground rules

  1. Do not remove existing functionality. You can change how routes are declared to attach middleware, but keep the same endpoints working.

  2. Define new middleware functions inside routes/student_routes.js above the route registrations.

  3. Register middleware on specific routes only.

  4. Use Postman for checks. Steps are provided.


Exercise 1: Validate :id before hitting the controller

Goal: add a route-level middleware that verifies the :id path parameter looks like a MongoDB ObjectId beforecalling the controller. If the format is wrong, respond with 400 Bad Request and a short JSON message. Otherwise call next().

What to build

  • A function validateObjectId(req, res, next) that checks req.params.id.

  • If id is not a 24-character hex string, immediately return res.status(400).json({ msg: "Invalid id format" }).

  • If valid, call next().

  • Attach this middleware only to GET /api/students/:id.

Where to put it

  • Add the middleware function above your route definitions in routes/student.js.

  • Replace the existing api.route(":id").get(getOneStudent); with a route that includes the middleware.

Starter scaffold (paste in routes/student.js and fill the TODOs)

// Route-level middleware: validateObjectId
function validateObjectId(req, res, next) {
  // TODO 1: read id from req.params
  // TODO 2: check that it is 24 hex chars (0-9, a-f, A-F)
  //   Hint: use a simple regex or length + hex test
  // TODO 3: if invalid, return res.status(400).json({ msg: "Invalid id format" })
  // TODO 4: otherwise, next()
}

// Attach it to the :id GET route (replace your current line for :id)
// api.get(":id", validateObjectId, getOneStudent);

Quick checks (Postman)

Valid id case

  1. In Postman, create a GET request to http://localhost:5000/api/students/<put-a-real-24-hex-id-here>.

  2. Send the request. If the id exists, you should get 200 OK with the student. If it does not exist, your controller will return 404 as before. In both cases, the middleware should allow the request through.

Invalid id case

  1. Send a GET to http://localhost:5000/api/students/123.

  2. Expected: 400 Bad Request and JSON { "msg": "Invalid id format" }.

  3. Your controller should not run for this case.


Exercise 2: Compose multiple route-level middlewares on POST /api/students

Goal: show that route-level middleware can be composed. Add two middlewares to the POST route only: one that enforces an API key in a custom header, and one that normalizes request data before it reaches the controller.

Small primer: custom header and simple API key

  • An API key is just a shared secret checked by the server.

  • For this exercise, the key will be read from the x-api-key request header.

  • You can hardcode a value like classroom-secret or read from process.env.API_KEY if you prefer.

  • If the header is missing or wrong, respond with 401 Unauthorized and do not call next().

What to build

  1. enforceApiKey(req, res, next)

    • Read the header with req.header("x-api-key").

    • Compare it to the expected key.

    • If missing or mismatched, respond 401 with { msg: "Missing or invalid API key" }.

    • Otherwise call next().

  2. normalizeStudentBody(req, res, next)

    • Trim whitespace on first_name and last_name if they exist in req.body.

    • Optionally uppercase the first letter of each name for consistency.

    • If age exists, ensure it is a number (e.g., convert with Number(...)) but do not add new validation rules beyond that.

    • Call next().

  3. Attach both middlewares to only the POST route, in this order: enforceApiKey then normalizeStudentBody, then your existing controller createStudent.

Where to put it

  • Add both middleware functions above your route definitions in routes/student_routes.js.

  • Update the POST registration to include both functions.

Starter scaffold (paste in routes/student.js and fill the TODOs)

// Route-level middleware: enforce API key via x-api-key header
function enforceApiKey(req, res, next) {
  // TODO 1: read the key from req.header("x-api-key")
  // TODO 2: compare to expected value (e.g., process.env.API_KEY or "classroom-secret")
  // TODO 3: if missing or invalid, return res.status(401).json({ msg: "Missing or invalid API key" })
  // TODO 4: otherwise next()
}

// Route-level middleware: normalize incoming student data
function normalizeStudentBody(req, res, next) {
  // TODO 1: if req.body.first_name exists, trim it and normalize casing
  // TODO 2: if req.body.last_name exists, trim it and normalize casing
  // TODO 3: if req.body.age exists, convert it to a Number
  // TODO 4: next()
}

// Attach them to the POST route (replace your current "/" POST line)
// api.post("/", enforceApiKey, normalizeStudentBody, createStudent);

Quick checks (Postman)

Positive path

  1. Create a new POST request to http://localhost:5000/api/students.

  2. In Headers, add Content-Type: application/json and x-api-key: classroom-secret (or your chosen key).

  3. In Body, choose raw and JSON, then paste:

{
  "first_name": "  ada  ",
  "last_name": "  lovelace ",
  "email": "ada@love.com",
  "age": "28"
}
  1. Send the request. Expected: 201 Created. The controller runs. Your normalizer should trim names and coerce age to a number before it reaches the controller.

Missing or wrong key

  1. Remove or change the x-api-key header and resend.

  2. Expected: 401 Unauthorized and { "msg": "Missing or invalid API key" }. The controller should notrun.


Done criteria

  • Exercise 1 blocks bad :id formats with a clear 400 response. Valid formats pass through to the controller.

  • Exercise 2 composes two middlewares on the POST route. Requests with a valid key proceed, and data is normalized before the controller.

  • Changes are limited to routes/student_routes.js. Controllers, schemas, and server.js remain untouched.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment