📖 Scenario: You are creating a simple web server in Deno that uses middleware functions to process HTTP requests step-by-step. Middleware helps add features like logging, authentication, or modifying requests before sending a response.
🎯 Goal: Build a Deno server that uses middleware functions to log requests and add a custom header before sending a response.
📋 What You'll Learn
Create an array called middlewares to hold middleware functions
Create a variable called requestCount initialized to 0
Write a function called applyMiddlewares that runs all middleware functions in order
Add a final middleware that sends a response with a custom header
💡 Why This Matters
🌍 Real World
Middleware is used in real web servers to add features like logging, authentication, and data parsing without cluttering the main server code.
💼 Career
Understanding middleware patterns is essential for backend developers working with web frameworks and servers in Deno, Node.js, or other environments.
Progress0 / 4 steps
1
Setup Middleware Array
Create an array called middlewares that will hold middleware functions.
Deno
Hint
Use const middlewares = [] to create an empty array.
2
Add Request Counter Variable
Create a variable called requestCount and set it to 0 to count incoming requests.
Deno
Hint
Use let requestCount = 0 to create a counter variable.
3
Create Middleware Runner Function
Write a function called applyMiddlewares that takes req and res as parameters and runs each middleware function in middlewares in order, passing req, res, and a next callback to each.
Deno
Hint
Use an async function with an inner next function to call each middleware in order.
4
Add Middleware and Start Server
Add two middleware functions to middlewares: one that increments requestCount and logs the request URL, and a final one that sets a custom header X-Custom-Header with value MiddlewareDemo and sends a response with text Hello from Deno Middleware!. Then create a Deno server that calls applyMiddlewares for each request.
Deno
Hint
Add middleware functions to middlewares array and use serve from Deno standard library to start the server.
Practice
(1/5)
1. What is the main purpose of middleware in a Deno web application?
easy
A. To compile TypeScript code into JavaScript
B. To store data permanently in a database
C. To run code step-by-step for each incoming request
D. To create user interface components
Solution
Step 1: Understand middleware role
Middleware processes each request in order, allowing code to run before sending a response.
Step 2: Compare options
Only To run code step-by-step for each incoming request describes this step-by-step request handling. Other options describe unrelated tasks.
Final Answer:
To run code step-by-step for each incoming request -> Option C
Quick Check:
Middleware = step-by-step request code [OK]
Hint: Middleware runs code for each request in order [OK]
Common Mistakes:
Confusing middleware with database operations
Thinking middleware builds UI components
Assuming middleware compiles code
2. Which of the following is the correct way to call the next middleware in Deno?
easy
A. next.await()
B. next()
C. call next()
D. await next()
Solution
Step 1: Recall async middleware pattern
Middleware functions are async and must await next() to continue the chain.
Step 2: Check syntax correctness
Only 'await next()' correctly waits for the next middleware to finish before continuing.
Final Answer:
await next() -> Option D
Quick Check:
Use await next() to proceed [OK]
Hint: Always use await before next() in async middleware [OK]
Common Mistakes:
Calling next() without await causing unexpected behavior
What will be printed to the console when a request is handled?
medium
A. Before\nAfter
B. After\nBefore
C. Before
D. After
Solution
Step 1: Analyze middleware flow
Logger prints 'Before', then awaits next middleware (handler), then prints 'After'.
Step 2: Understand order of prints
Since handler runs between the two console.logs, output order is 'Before' then 'After'.
Final Answer:
Before\nAfter -> Option A
Quick Check:
Middleware logs before and after next() [OK]
Hint: Middleware logs before and after await next() [OK]
Common Mistakes:
Assuming 'After' prints before 'Before'
Thinking only 'Before' or 'After' prints
Ignoring await causing wrong order
4. Identify the error in this Deno middleware code:
async function auth(ctx, next) {
if (!ctx.request.headers.get('Authorization')) {
ctx.response.status = 401;
ctx.response.body = 'Unauthorized';
}
await next();
}
medium
A. Missing await before ctx.request.headers.get
B. Should return after setting 401 to stop middleware chain
C. ctx.response.body must be a JSON object
D. next() should not be awaited
Solution
Step 1: Understand middleware flow control
If authorization header is missing, response is set to 401, but code still calls await next(), continuing the chain.
Step 2: Identify fix to stop chain
To prevent further middleware running, function should return immediately after setting 401 response.
Final Answer:
Should return after setting 401 to stop middleware chain -> Option B
Quick Check:
Return early to stop middleware chain [OK]
Hint: Return after response to stop middleware chain [OK]
Common Mistakes:
Not returning causes next middleware to run anyway
Thinking await is missing on header get
Believing response body must be JSON always
5. You want to create a middleware in Deno that measures how long each request takes and adds a custom header X-Response-Time with the duration in milliseconds. Which of the following middleware implementations correctly achieves this?
hard
A. async function responseTime(ctx, next) {
const start = performance.now();
await next();
const ms = performance.now() - start;
ctx.response.headers.set('X-Response-Time', ms.toFixed(2));
}
B. async function responseTime(ctx, next) {
const start = Date.now();
const ms = Date.now() - start;
ctx.response.headers.set('X-Response-Time', `${ms}ms`);
await next();
}
C. async function responseTime(ctx, next) {
const start = Date.now();
next();
const ms = Date.now() - start;
ctx.response.headers.set('X-Response-Time', `${ms}ms`);
}
D. async function responseTime(ctx, next) {
await next();
const ms = Date.now();
ctx.response.headers.set('X-Response-Time', ms);
}
Solution
Step 1: Measure time before and after next()
Start timer before await next(), then calculate duration after it finishes.
Step 2: Use precise timer and set header correctly
performance.now() gives better precision than Date.now(). Setting header with ms.toFixed(2) formats nicely.
Final Answer:
Middleware using performance.now(), await next(), and setting header after next() -> Option A
Quick Check:
Use performance.now() and await next() then set header [OK]
Hint: Start timer before await next(), set header after [OK]
Common Mistakes:
Calculating time before await next() runs
Using Date.now() which is less precise
Setting header before next() completes
Recommended
Ready to prove it?
Pass the test and this pattern moves unknownstrongwhile earning +1 Grip toward your certificate.