Understanding Server Request/Response in JavaScript

Building Your First Server

Imagine you're opening a restaurant. Just as a restaurant needs a building where customers can come in and place their orders, a web application needs a server where clients can send their requests. Let's create our first server using Node.js's built-in http package.


const http = require('http');

const server = http.createServer((request, response) => {
    console.log('A customer has arrived!');
    response.end('Welcome to our restaurant!');
});

server.listen(3000, () => {
    console.log('Server is ready to take orders on port 3000');
});
                

Think of this server as a restaurant host who's always ready to greet customers and handle their requests. The createServer function is like hiring this host, and the listen method is like opening the restaurant's doors for business.

Understanding Request and Response Objects

In our restaurant analogy, the Request object is like a customer's order ticket, containing all the details about what they want. The Response object is like the plate of food we send back to their table.

The Request Object: Your Customer's Order

The request object contains crucial information about what the client wants:


const server = http.createServer((request, response) => {
    console.log('Method (type of order):', request.method);
    console.log('URL (specific dish):', request.url);
    console.log('Headers (special instructions):', request.headers);
});
                

The Response Object: Your Service Back to the Client

The response object is how we send back what was requested:


const server = http.createServer((request, response) => {
    // Set the status code (like confirming order status)
    response.statusCode = 200; // "Your order was successful!"

    // Set headers (like placing utensils and napkins)
    response.setHeader('Content-Type', 'application/json');

    // Send the response (serving the food)
    response.end(JSON.stringify({ message: 'Your order is ready!' }));
});
                

Reading Request Components

Just as a waiter needs to understand different types of orders, your server needs to handle different types of requests.


const server = http.createServer((request, response) => {
    // Reading the method (GET, POST, etc.)
    if (request.method === 'GET') {
        // Customer is asking for menu items
        handleGetRequest(request, response);
    } else if (request.method === 'POST') {
        // Customer is placing an order
        handlePostRequest(request, response);
    }

    // Reading the URL (what specifically they want)
    if (request.url === '/menu') {
        // Show the menu
        sendMenu(response);
    } else if (request.url === '/order') {
        // Take their order
        takeOrder(request, response);
    }
});

function handleGetRequest(request, response) {
    // Implementation details for handling GET requests
    response.setHeader('Content-Type', 'application/json');
    response.end(JSON.stringify({ message: 'Here is our menu!' }));
}
                

Sending Static Assets

Sometimes you need to serve static files like images, CSS, or JavaScript files. Think of this like having pre-prepared meals ready to serve:


const fs = require('fs');
const path = require('path');

const server = http.createServer((request, response) => {
    if (request.url === '/menu-image.jpg') {
        // Read the image file
        fs.readFile(path.join(__dirname, 'menu-image.jpg'), (error, content) => {
            if (error) {
                response.statusCode = 500;
                response.end('Error loading the image');
                return;
            }
            
            response.setHeader('Content-Type', 'image/jpeg');
            response.end(content);
        });
    }
});
                

Debugging Server Issues

When your server isn't responding as expected, it's like having a kitchen that's backed up. Here are common issues and solutions:

Hanging Server

If your server seems frozen, check these common causes:


// Always end your response!
const server = http.createServer((request, response) => {
    if (request.url === '/menu') {
        response.write('Here is our menu');
        response.end(); // Don't forget this!
    }
    // Missing else block could cause hanging
    else {
        response.statusCode = 404;
        response.end('Not found');
    }
});
                

Using Postman for Testing

Postman is like a food critic who helps you test your restaurant's service. You can use it to:

Real-World Applications

Here's a practical example of a simple API endpoint for a restaurant ordering system:


const http = require('http');

const menu = {
    appetizers: ['Salad', 'Soup'],
    mainCourse: ['Steak', 'Fish'],
    desserts: ['Cake', 'Ice Cream']
};

const server = http.createServer((request, response) => {
    response.setHeader('Content-Type', 'application/json');

    if (request.url === '/api/menu' && request.method === 'GET') {
        response.statusCode = 200;
        response.end(JSON.stringify(menu));
    }
    else if (request.url === '/api/order' && request.method === 'POST') {
        let body = '';
        
        request.on('data', chunk => {
            body += chunk.toString();
        });

        request.on('end', () => {
            const order = JSON.parse(body);
            // Process the order
            response.statusCode = 201;
            response.end(JSON.stringify({
                message: 'Order received!',
                orderNumber: Math.floor(Math.random() * 1000)
            }));
        });
    }
    else {
        response.statusCode = 404;
        response.end(JSON.stringify({ error: 'Not found' }));
    }
});

server.listen(3000, () => {
    console.log('Restaurant server is open for business!');
});
                

Topics to Explore Further

To deepen your understanding of server-side programming, consider exploring: