-
-
Notifications
You must be signed in to change notification settings - Fork 2
Added new docs for Back-end #248
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
122 changes: 121 additions & 1 deletion
122
absolute-beginners/full-stack/backend/error-handling.mdx
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1 +1,121 @@ | ||
| <ComingSoon /> | ||
| --- | ||
| title: "Error Handling in Express" | ||
| sidebar_label: "5. Error Handling" | ||
| sidebar_position: 5 | ||
| description: "Learn how to catch and handle errors in your Node.js and Express applications to prevent crashes." | ||
| tags: ["Error Handling", "Express.js", "Node.js", "Backend Development"] | ||
| keywords: ["Error Handling", "Express.js", "Node.js", "Try...Catch", "Error Middleware", "Custom Errors", "404 Handling"] | ||
| --- | ||
|
|
||
| In a basic script, if an error happens, the program stops. In a backend server, if the program stops, your entire website goes offline for everyone! Error handling is the art of catching those "oops" moments and responding gracefully. | ||
|
|
||
| ## 1. The Try...Catch Block | ||
|
|
||
| The most basic way to handle errors in JavaScript is the `try...catch` block. You "try" to run some code, and if it fails, the "catch" block takes over. | ||
|
|
||
| ```javascript title="server.js" | ||
| app.get('/api/data', async (req, res) => { | ||
| try { | ||
| const data = await someDatabaseCall(); | ||
| res.json(data); | ||
| } catch (error) { | ||
| console.error(error); // Log it for the developer | ||
| res.status(500).send("Something went wrong on our end!"); | ||
| } | ||
| }); | ||
| ``` | ||
|
|
||
| ## 2. Express Error Middleware | ||
|
|
||
| Express has a special type of middleware specifically for errors. While normal middleware has three arguments `(req, res, next)`, error middleware has **four**: `(err, req, res, next)`. | ||
|
|
||
| If you place this at the very bottom of your `server.js` (after all your routes), it will catch every error that happens in your app. | ||
|
|
||
| ```javascript title="server.js" | ||
| // Universal Error Handler | ||
| app.use((err, req, res, next) => { | ||
| console.error(err.stack); | ||
| res.status(500).json({ | ||
| success: false, | ||
| message: "Internal Server Error", | ||
| error: err.message // Optional: only show in development | ||
| }); | ||
| }); | ||
| ``` | ||
|
|
||
| ## 3. Throwing Custom Errors | ||
|
|
||
| Sometimes, the code isn't "broken," but the user did something wrong (like entering the wrong password). In these cases, you can "throw" your own error to trigger the catch block. | ||
|
|
||
| ```javascript title="server.js" | ||
| app.post('/login', (req, res, next) => { | ||
| const { password } = req.body; | ||
|
|
||
| if (password !== "12345") { | ||
| const error = new Error("Wrong Password!"); | ||
| error.status = 401; | ||
| return next(error); // Passes the error to the error middleware | ||
| } | ||
|
|
||
| res.send("Logged in!"); | ||
| }); | ||
| ``` | ||
|
|
||
| ## 4. Handling 404 (Not Found) | ||
|
|
||
| What happens if a user visits a URL that doesn't exist? By default, Express sends a plain text message. At the Hub, we prefer to send a clean JSON response or a custom 404 page. | ||
|
|
||
| **Add this right before your error middleware:** | ||
|
|
||
| ```javascript title="server.js" | ||
| app.use((req, res) => { | ||
| res.status(404).json({ message: "Requested resource not found" }); | ||
| }); | ||
| ``` | ||
|
|
||
| ## 5. Best Practices for Error Messages | ||
|
|
||
| When an error occurs, you must be careful about what you tell the user: | ||
|
|
||
| | Scenario | Good Response | Bad Response | | ||
| | :--- | :--- | :--- | | ||
| | **Database Failed** | "Service temporarily unavailable." | "Error: Cannot connect to MongoDB at 192.168..." | | ||
| | **Wrong Input** | "Please enter a valid email." | "Internal logic failed at line 42." | | ||
| | **Security** | "Invalid credentials." | "That email exists, but the password is wrong." | | ||
|
|
||
| :::tip | ||
| Never reveal your database structure or file paths in an error message. It gives hackers a map of your server! | ||
| ::: | ||
|
|
||
| ## Practice: The "Safe Divider" | ||
|
|
||
| Build a route `/divide/:a/:b` that: | ||
| 1. Takes two numbers from the URL. | ||
| 2. Divides `a` by `b`. | ||
| 3. **Error Check:** If `b` is `0`, throw an error (you can't divide by zero!). | ||
| 4. **Error Check:** If `a` or `b` are not numbers, throw an error. | ||
|
|
||
| ```javascript title="server.js" | ||
| app.get('/divide/:a/:b', (req, res, next) => { | ||
| const a = parseFloat(req.params.a); | ||
| const b = parseFloat(req.params.b); | ||
|
|
||
| if (isNaN(a) || isNaN(b)) { | ||
| const error = new Error("Both parameters must be numbers."); | ||
| error.status = 400; | ||
| return next(error); | ||
| } | ||
|
|
||
| if (b === 0) { | ||
| const error = new Error("Cannot divide by zero."); | ||
| error.status = 400; | ||
| return next(error); | ||
| } | ||
|
|
||
| res.json({ result: a / b }); | ||
| }); | ||
| ``` | ||
|
|
||
| :::info Async Wrapper | ||
| In modern Express, catching errors in `async` functions can be repetitive. Many developers use a "Catch-Async" helper function or a library like `express-async-errors` to automatically catch errors and send them to the global error handler. | ||
| ::: | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1 +1,118 @@ | ||
| <ComingSoon /> | ||
| --- | ||
| title: "Express.js Framework" | ||
| sidebar_label: "3. Express.js" | ||
| sidebar_position: 3 | ||
| description: "Learn how to build a web server quickly using Express.js, the most popular Node.js framework. Understand routing, middleware, and how to handle requests and responses. Get hands-on experience creating your first API endpoints." | ||
| tags: ["Express.js", "Backend", "Node.js", "Web Server", "API"] | ||
| keywords: ["Express.js", "Web Framework", "Routing", "Middleware", "API Endpoints", "Node.js"] | ||
| --- | ||
|
|
||
| If Node.js is the "Environment," then **Express.js** is the "Framework." It is designed to make building web applications and APIs much easier and faster. At **CodeHarborHub**, we use Express because it is the industry standard for JavaScript backends. | ||
|
|
||
| ## 1. Why use Express? | ||
|
|
||
| Building a server using only built-in Node.js `http` module is like building a house by making your own bricks. Express gives you the bricks already made: | ||
| * **Easy Routing:** Define what happens when a user visits `/home` vs `/profile`. | ||
| * **Middleware Support:** Add extra features like logging or security with one line of code. | ||
| * **JSON Friendly:** Perfect for talking to React frontends. | ||
|
|
||
| ## 2. Setting Up Express | ||
|
|
||
| First, create a folder for your project, initialize it, and install Express: | ||
|
|
||
| ```bash | ||
| mkdir my-server | ||
| cd my-server | ||
| npm init -y | ||
| npm install express | ||
| ``` | ||
|
|
||
| ## 3. The "Hello World" Server | ||
|
|
||
| Create a file named `server.js` and add this code. This is the simplest Express server possible: | ||
|
|
||
| ```javascript title="server.js" | ||
| const express = require('express'); | ||
| const app = express(); | ||
| const PORT = 3000; | ||
|
|
||
| // This is a "Route" | ||
| app.get('/', (req, res) => { | ||
| res.send('Welcome to the CodeHarborHub Server!'); | ||
| }); | ||
|
|
||
| app.listen(PORT, () => { | ||
| console.log(`Server is running at http://localhost:${PORT}`); | ||
| }); | ||
| ``` | ||
|
|
||
| To start it, run `node server.js` in your terminal. Open your browser and go to `http://localhost:3000`. | ||
|
|
||
| ## 4. Understanding Request and Response | ||
|
|
||
| Every route handler in Express gives you two important objects: | ||
|
|
||
| 1. **`req` (Request):** Information coming *from* the user (e.g., what they typed in a search bar). | ||
| 2. **`res` (Response):** What the server sends *back* to the user (e.g., text, HTML, or an image). | ||
|
|
||
| ## 5. Handling Routes (The Roadmap) | ||
|
|
||
| A "Route" is a combination of a **URL** and an **HTTP Method**. The most common methods are: | ||
| * **GET:** To "Get" data (e.g., reading a blog post). | ||
| * **POST:** To "Send" data (e.g., creating a new user account). | ||
| * **PUT:** To "Update" data (e.g., changing your profile picture). | ||
| * **DELETE:** To "Remove" data. | ||
|
|
||
| ```javascript title="server.js" | ||
| const express = require('express'); | ||
| const app = express(); | ||
| app.use(express.json()); | ||
|
|
||
| app.get('/api/cricket', (req, res) => { | ||
| res.json({ player: "MS Dhoni", shot: "Helicopter Shot" }); | ||
| }); | ||
|
|
||
| app.post('/api/login', (req, res) => { | ||
| res.send("Processing login..."); | ||
| }); | ||
| ``` | ||
|
|
||
| ## 6. Nodemon: The Developer's Best Friend | ||
|
|
||
| Normally, every time you change your code, you have to stop and restart the server manually. **Nodemon** does this for you automatically! | ||
|
|
||
| **Install it:** | ||
|
|
||
| ```bash | ||
| npm install -g nodemon | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
| ``` | ||
|
|
||
| **Run your server with it:** | ||
|
|
||
| ```bash | ||
| nodemon server.js | ||
| ``` | ||
|
|
||
| ## Practice: The Dynamic Greeter | ||
|
|
||
| Let's use **URL Parameters** to greet users by name! | ||
|
|
||
| ```javascript title="server.js" | ||
| const express = require('express'); | ||
| const app = express(); | ||
|
|
||
| app.get('/greet/:name', (req, res) => { | ||
| const userName = req.params.name; | ||
| res.send(`Hello ${userName}, welcome to the backend!`); | ||
| }); | ||
| ``` | ||
|
|
||
| *If you visit `http://localhost:3000/greet/Ajay`, the page will say "Hello Ajay, welcome to the backend!"* | ||
|
|
||
| :::info Middleware | ||
| Middleware functions are functions that have access to the request and response objects. They run *before* your route handler. A very common one is `express.json()`, which allows your server to read JSON data sent from the frontend. | ||
|
|
||
| ```javascript title="server.js" | ||
| app.use(express.json()); | ||
| ``` | ||
| ::: | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1 +1,117 @@ | ||
| <ComingSoon /> | ||
| --- | ||
| title: "Understanding Middleware in Express" | ||
| sidebar_label: "6. Middleware" | ||
| sidebar_position: 6 | ||
| description: "Learn how to use and create middleware to process requests before they reach your routes." | ||
| tags: ["Middleware", "Express.js", "Node.js", "Backend Development"] | ||
| keywords: ["Middleware", "Express.js", "Node.js", "Custom Middleware", "Built-in Middleware", "Third-Party Middleware", "next() Function"] | ||
| --- | ||
|
|
||
| In Express, **Middleware** is a function that runs **after** the incoming request is received and **before** the final response is sent. It has access to the Request (`req`), Response (`res`), and the next function in the cycle. | ||
|
|
||
| ## 1. How Middleware Works | ||
|
|
||
| Think of Middleware as a series of checkpoints. Each middleware can: | ||
| 1. Execute any code. | ||
| 2. Make changes to the `req` and `res` objects. | ||
| 3. End the request-response cycle (e.g., if a user isn't logged in). | ||
| 4. Call the **`next()`** function to pass control to the next middleware. | ||
|
|
||
| ```javascript title="server.js" | ||
| app.use((req, res, next) => { | ||
| console.log("This runs for every request!"); | ||
| next(); // Passes control to the next middleware or route handler | ||
| }); | ||
| ``` | ||
|
|
||
| ## 2. Types of Middleware | ||
|
|
||
| ### 1. Built-in Middleware | ||
| Express comes with some tools already included. The most common one is `express.json()`, which helps your server understand JSON data sent by a frontend (like a React app). | ||
|
|
||
| ```javascript title="server.js" | ||
| app.use(express.json()); // Essential for modern apps! | ||
| ``` | ||
|
|
||
| ### 2. Third-Party Middleware | ||
| The community has built amazing tools that you can install via NPM. | ||
| * **Morgan:** Logs every request so you can see who is visiting your site. | ||
| * **Cors:** Allows your frontend to talk to your backend safely. | ||
| * **Dotenv:** Helps manage "secret" environment variables. | ||
|
|
||
| ```bash | ||
| npm install morgan | ||
| ``` | ||
|
|
||
| Now, let's use it in our `server.js`: | ||
|
|
||
| ```javascript title="server.js" | ||
| const morgan = require('morgan'); | ||
| app.use(morgan('dev')); // Now every request shows up in your terminal! | ||
| ``` | ||
|
|
||
| ### 3. Custom Middleware | ||
| You can write your own middleware to do anything you want! This is great for things like checking if a user is an admin or logging the time of a request. | ||
|
|
||
| ## 3. Building Your First Custom Middleware | ||
|
|
||
| Let's create a "Logger" that prints the URL and the current time whenever someone visits our site. | ||
|
|
||
| ```javascript title="server.js" | ||
| const myLogger = (req, res, next) => { | ||
| const currentTime = new Date().toLocaleTimeString(); | ||
| console.log(`[${currentTime}] Request made to: ${req.url}`); | ||
|
|
||
| // CRITICAL: You must call next() or the browser will hang forever! | ||
| next(); | ||
| }; | ||
|
|
||
| // Apply it to the whole app | ||
| app.use(myLogger); | ||
| ``` | ||
|
|
||
| ## 4. Global vs. Specific Middleware | ||
|
|
||
| At **CodeHarborHub**, we teach you to be precise with your code. You don't always want middleware to run on *every* page. | ||
|
|
||
| ### Global Middleware | ||
|
|
||
| Runs for every single route in your app. | ||
|
|
||
| ```javascript title="server.js" | ||
| app.use(express.json()); | ||
| ``` | ||
|
|
||
| ### Specific Middleware | ||
|
|
||
| Only runs for a specific route. This is perfect for "Protected Routes" (e.g., only users who are logged in can see `/dashboard`). | ||
|
|
||
| ```javascript title="server.js" | ||
| const checkAuth = (req, res, next) => { | ||
| const isAuthorized = true; // In real life, check for a token | ||
| if (isAuthorized) { | ||
| next(); | ||
| } else { | ||
| res.status(401).send("Access Denied!"); | ||
| } | ||
| }; | ||
|
|
||
| app.get('/dashboard', checkAuth, (req, res) => { | ||
| res.send("Welcome to your secret dashboard!"); | ||
| }); | ||
| ``` | ||
|
|
||
| ## 5. The Importance of `next()` | ||
|
|
||
| If you forget to call `next()`, your request will get "stuck" in that middleware. The user's browser will show a spinning loading icon until it eventually times out. Always remember: **Middleware is a relay race—you must pass the baton!** | ||
|
|
||
| ## Practice: The "Maintenance Mode" Challenge | ||
|
|
||
| Try to create a middleware that prevents anyone from visiting your site. | ||
| 1. Create a middleware function. | ||
| 2. Instead of calling `next()`, it should send a message: `"Site under maintenance. Check back later!"`. | ||
| 3. Apply it to your app and try to visit any route. | ||
|
|
||
| :::info Order Matters! | ||
| Express runs middleware in the order you write them in your code. If you put your error-handling middleware at the top, it won't catch any errors from the routes below it. Always place global middleware and routes first, and error handlers last. | ||
| ::: |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Exposing the error message directly to the client can leak sensitive information about the server's internal state. It is safer to only include detailed error information when the application is running in a development environment.