# Creating Routes and Handling Requests with Express

Node.js has a built-in HTTP module, but writing servers with it is verbose. Express.js simplifies everything. It handles routing, request parsing, and response sending with clean, simple code.

## What is Express?

Express is a lightweight web framework for Node.js. It makes building web applications easier by providing helpful features for routing, middleware, and responses.

Without Express, here's a basic Node.js server:

```javascript
import http from 'http';

const server = http.createServer((req, res) => {
  if (req.url === '/' && req.method === 'GET') {
    res.statusCode = 200;
    res.setHeader('Content-Type', 'text/plain');
    res.end('Home page');
  } else if (req.url === '/about' && req.method === 'GET') {
    res.statusCode = 200;
    res.setHeader('Content-Type', 'text/plain');
    res.end('About page');
  } else {
    res.statusCode = 404;
    res.end('Not found');
  }
});

server.listen(3000);
```

This gets messy quickly. With multiple routes, you'd have many if-else statements.

With Express, the same thing is much simpler:

```javascript
import express from 'express';

const app = express();

app.get('/', (req, res) => {
  res.send('Home page');
});

app.get('/about', (req, res) => {
  res.send('About page');
});

app.listen(3000);
```

Much cleaner. Express handles the complexity.

## Setting Up Express

First, create a project and install Express:

```bash
npm init -y
npm install express
```

Create a file called `server.js`:

```javascript
import express from 'express';

const app = express();

app.listen(3000, () => {
  console.log('Server running on http://localhost:3000');
});
```

Run it:

```bash
node server.js
```

You have a running server. It doesn't do anything yet, but it's listening on port 3000.

## Understanding Routes

A route is a combination of:

*   **HTTP method** (GET, POST, PUT, DELETE, etc.)
    
*   **URL path** (/home, /users, /posts/123, etc.)
    
*   **Handler function** (what to do when this route is called)
    

The basic structure is:

```javascript
app.METHOD(PATH, HANDLER);
```

For example:

```javascript
app.get('/home', (req, res) => {
  res.send('This is the home page');
});
```

This means: "When someone sends a GET request to /home, execute this function."

## GET Requests

GET requests fetch data. They're read-only and don't change anything.

```javascript
import express from 'express';

const app = express();

app.get('/', (req, res) => {
  res.send('Welcome to the home page');
});

app.get('/about', (req, res) => {
  res.send('This is the about page');
});

app.get('/contact', (req, res) => {
  res.send('Contact us at info@example.com');
});

app.listen(3000, () => {
  console.log('Server running');
});
```

Now visit:

*   `http://localhost:3000/` → "Welcome to the home page"
    
*   `http://localhost:3000/about` → "This is the about page"
    
*   `http://localhost:3000/contact` → "Contact us at..."
    

## POST Requests

POST requests send data to the server. They typically create new resources.

For this, you need to parse incoming data. Express provides middleware for this:

```javascript
import express from 'express';

const app = express();

// Parse JSON data
app.use(express.json());

app.get('/', (req, res) => {
  res.send('GET request received');
});

app.post('/submit', (req, res) => {
  const { name, email } = req.body;
  res.send(`Thank you, ${name}. We'll email ${email}`);
});

app.listen(3000, () => {
  console.log('Server running');
});
```

When someone sends a POST request to `/submit` with JSON data, Express parses it and stores it in `req.body`.

To test this, you'd need a tool like Postman or curl:

```bash
curl -X POST http://localhost:3000/submit \
  -H "Content-Type: application/json" \
  -d '{"name":"John","email":"john@example.com"}'
```

Response: "Thank you, John. We'll email john@example.com"

## URL Parameters

Routes can have dynamic parts. Parameters start with a colon:

```javascript
import express from 'express';

const app = express();

app.get('/users/:id', (req, res) => {
  const userId = req.params.id;
  res.send(`Getting user ${userId}`);
});

app.get('/posts/:postId/comments/:commentId', (req, res) => {
  const { postId, commentId } = req.params;
  res.send(`Comment ${commentId} on post ${postId}`);
});

app.listen(3000);
```

Examples:

*   `GET /users/123` → "Getting user 123"
    
*   `GET /posts/456/comments/789` → "Comment 789 on post 456"
    

## Query Parameters

Query parameters come after a question mark and are optional:

```javascript
import express from 'express';

const app = express();

app.get('/search', (req, res) => {
  const query = req.query.q;
  const limit = req.query.limit;
  res.send(`Searching for "${query}", limit ${limit}`);
});

app.listen(3000);
```

Examples:

*   `GET /search?q=javascript` → "Searching for 'javascript', limit undefined"
    
*   `GET /search?q=node&limit=10` → "Searching for 'node', limit 10"
    

## Response Methods

Express provides several ways to send responses:

```javascript
import express from 'express';

const app = express();

// Send plain text
app.get('/text', (req, res) => {
  res.send('This is plain text');
});

// Send JSON
app.get('/json', (req, res) => {
  res.json({ message: 'This is JSON', status: 'success' });
});

// Send HTML
app.get('/html', (req, res) => {
  res.send('<h1>This is HTML</h1>');
});

// Send with status code
app.get('/error', (req, res) => {
  res.status(404).send('Not found');
});

// Redirect
app.get('/old-path', (req, res) => {
  res.redirect('/new-path');
});

app.listen(3000);
```

## Handling All HTTP Methods

Express supports all standard HTTP methods:

```javascript
import express from 'express';

const app = express();

app.use(express.json());

app.get('/users', (req, res) => {
  res.json({ message: 'Get all users' });
});

app.post('/users', (req, res) => {
  res.json({ message: 'Create new user' });
});

app.put('/users/:id', (req, res) => {
  res.json({ message: `Update user ${req.params.id}` });
});

app.delete('/users/:id', (req, res) => {
  res.json({ message: `Delete user ${req.params.id}` });
});

app.listen(3000);
```

## Handling 404 Errors

When a route doesn't exist, Express returns a 404 error by default. You can customize this:

```javascript
import express from 'express';

const app = express();

app.get('/', (req, res) => {
  res.send('Home');
});

// Catch all unmatched routes
app.use((req, res) => {
  res.status(404).send('Page not found');
});

app.listen(3000);
```

The order matters. This "catch-all" route must be last, otherwise it will intercept all requests.

## A Complete Example

Let's build a simple blog API:

```javascript
import express from 'express';

const app = express();
app.use(express.json());

// Sample data
let posts = [
  { id: 1, title: 'First Post', content: 'Hello world' },
  { id: 2, title: 'Second Post', content: 'Another post' }
];

// GET all posts
app.get('/posts', (req, res) => {
  res.json(posts);
});

// GET single post
app.get('/posts/:id', (req, res) => {
  const post = posts.find(p => p.id === parseInt(req.params.id));
  if (!post) {
    return res.status(404).send('Post not found');
  }
  res.json(post);
});

// CREATE new post
app.post('/posts', (req, res) => {
  const newPost = {
    id: posts.length + 1,
    title: req.body.title,
    content: req.body.content
  };
  posts.push(newPost);
  res.status(201).json(newPost);
});

// UPDATE post
app.put('/posts/:id', (req, res) => {
  const post = posts.find(p => p.id === parseInt(req.params.id));
  if (!post) {
    return res.status(404).send('Post not found');
  }
  post.title = req.body.title || post.title;
  post.content = req.body.content || post.content;
  res.json(post);
});

// DELETE post
app.delete('/posts/:id', (req, res) => {
  const index = posts.findIndex(p => p.id === parseInt(req.params.id));
  if (index === -1) {
    return res.status(404).send('Post not found');
  }
  const deleted = posts.splice(index, 1);
  res.json(deleted);
});

app.listen(3000, () => {
  console.log('Blog API running on port 3000');
});
```

This simple API lets you create, read, update, and delete posts.

## Common Mistakes

**Mistake 1: Forgetting middleware**

```javascript
// Wrong - won't parse JSON
app.post('/data', (req, res) => {
  console.log(req.body); // undefined
});

// Correct
app.use(express.json());
app.post('/data', (req, res) => {
  console.log(req.body); // has data
});
```

**Mistake 2: Forgetting to return after sending response**

```javascript
app.get('/users/:id', (req, res) => {
  if (!id) {
    res.status(400).send('Invalid ID');
    // BUG: continues executing below
  }
  res.send('User data');
});

// Better
app.get('/users/:id', (req, res) => {
  if (!id) {
    return res.status(400).send('Invalid ID');
  }
  res.send('User data');
});
```

## Key Takeaways

*   Express simplifies building web servers with Node.js
    
*   Routes combine HTTP method, path, and handler function
    
*   GET requests fetch data, POST requests send data
    
*   URL parameters (`:id`) capture dynamic values
    
*   Query parameters (`?key=value`) pass optional filters
    
*   Middleware processes requests before they reach handlers
    
*   Always return after sending a response
    
*   Use appropriate HTTP status codes
    

Express makes building web applications enjoyable. These fundamentals are the foundation for all Express applications.
