HTTP Server: Node.js

Harsh Mishra - Oct 9 - - Dev Community

Introduction to Node.js HTTP Library

Node.js's http module is one of the core modules that allows developers to create HTTP servers and clients easily. It is built into Node.js, meaning no additional installation is required to use it. This module is particularly useful for creating web servers, handling HTTP requests, and sending HTTP responses.

The http module provides a straightforward interface for building network-based applications like RESTful APIs or web servers.

Basic Features of the HTTP Module

  1. Creating HTTP Servers: The http module allows you to create web servers that can listen for HTTP requests from clients and send back responses.
  2. Making HTTP Requests: You can also use the http module to make HTTP requests (client-side), sending data to remote servers.
  3. Handling Request/Response: It provides APIs to handle incoming requests (with methods, headers, and bodies) and send back responses.

Basic Example: Creating an HTTP Server

Here's a basic example demonstrating how to create an HTTP server using the http module in Node.js:

// Load the http module
const http = require('http');

// Create a server that responds to incoming requests
const server = http.createServer((req, res) => {
  // Set the HTTP status code and content type
  res.statusCode = 200; // OK
  res.setHeader('Content-Type', 'text/plain');

  // Send a response to the client
  res.end('Hello, World!');
});

// Define the port and hostname
const hostname = '127.0.0.1';
const port = 3000;

// Start the server
server.listen(port, hostname, () => {
  console.log(`Server running at http://${hostname}:${port}/`);
});
Enter fullscreen mode Exit fullscreen mode

Breakdown of the code:

  1. http.createServer(): This method is used to create the server. The callback function inside receives two arguments:

    • req (request): Represents the incoming HTTP request.
    • res (response): Represents the outgoing HTTP response.
  2. res.statusCode = 200: This sets the HTTP status code of the response to 200, which means "OK".

  3. res.setHeader(): Sets the HTTP headers. In this case, we set the Content-Type to text/plain, indicating the response body is plain text.

  4. res.end(): Ends the response and sends the string "Hello, World!" to the client.

  5. server.listen(): The server listens for requests on a specific port and hostname. Here, it listens on localhost (127.0.0.1) on port 3000.

Running the Code:

  1. Save the code in a file, say server.js.
  2. Run the file in your terminal with:
   node server.js
Enter fullscreen mode Exit fullscreen mode
  1. Open a browser and visit http://127.0.0.1:3000/. You should see the text "Hello, World!" displayed.

req Object in Node.js

The req (request) object in Node.js represents the incoming HTTP request and is an instance of the http.IncomingMessage class. It provides several properties and methods to access details about the incoming request, such as headers, status codes, query parameters, and the body.

Key Properties & Methods of req

1. req.headers

This property contains the headers sent by the client. It's an object where the keys are the header names and the values are their corresponding values.

Code:

console.log(req.headers);
Enter fullscreen mode Exit fullscreen mode

Example Output:

{ host: 'localhost:3000', connection: 'keep-alive', ... }
Enter fullscreen mode Exit fullscreen mode

2. req.statusCode

This property holds the HTTP status code for the request, though it's typically used for response. It can be set to inform the server about the status.

Code:

console.log(req.statusCode); // 200 (when server responds)
Enter fullscreen mode Exit fullscreen mode

Example Output:

200
Enter fullscreen mode Exit fullscreen mode

3. req.statusMessage

This is the status message associated with the status code. It provides a short description of the status code.

Code:

console.log(req.statusMessage); // OK (if statusCode is 200)
Enter fullscreen mode Exit fullscreen mode

Example Output:

OK
Enter fullscreen mode Exit fullscreen mode

4. req.url

This property contains the full URL path of the request, including the query string.

Code:

console.log(req.url); // '/search?query=nodejs'
Enter fullscreen mode Exit fullscreen mode

Example Output:

/search?query=nodejs
Enter fullscreen mode Exit fullscreen mode

5. Reading Query Parameters

Query parameters are parsed from the URL. To get them, you need to manually parse the URL or use a library like url or querystring.

Code:

const url = new URL(req.url, `http://${req.headers.host}`);
console.log(url.searchParams.get('query')); // 'nodejs'
Enter fullscreen mode Exit fullscreen mode

Example Output:

nodejs
Enter fullscreen mode Exit fullscreen mode

6. Reading the Body (using Buffer for POST requests)

For HTTP requests like POST, the body of the request can contain data (such as form data or JSON). To read the body, you need to listen to the 'data' event and accumulate the chunks. The Buffer class can be used to handle binary data.

Code:

let body = [];  // Initialize an empty array to accumulate chunks
req.on('data', chunk => {
  body.push(chunk);  // Append each chunk to the body array
});

req.on('end', () => {
  // Concatenate all the chunks and convert the Buffer to a string
  const bodyString = Buffer.concat(body).toString();
  console.log('Body:', bodyString);  // 'name=John&age=30'
});
Enter fullscreen mode Exit fullscreen mode

Example Output (when sending data like name=John&age=30 in the body):

Body: name=John&age=30
Enter fullscreen mode Exit fullscreen mode

Full Example Code for req Object

Here's the full code that demonstrates how to use the req object in a Node.js HTTP server. This code handles the headers, status, URL, query parameters, and body using buffers.

const http = require('http');

const server = http.createServer((req, res) => {
  // 1. Log headers
  console.log('Headers:', req.headers);

  // 2. Log status code (normally used for response, but shown here for reference)
  console.log('Status Code:', req.statusCode);

  // 3. Log status message (again, for response handling)
  console.log('Status Message:', req.statusMessage);

  // 4. Log requested URL
  console.log('URL:', req.url);

  // 5. Read query parameters
  const url = new URL(req.url, `http://${req.headers.host}`);
  console.log('Query Parameter (query):', url.searchParams.get('query'));

  // 6. Read the body (for POST requests)
  let body = [];  // Initialize an empty array to accumulate chunks
  req.on('data', chunk => {
    body.push(chunk);  // Append each chunk to the body array
  });
  req.on('end', () => {
    // Concatenate all the chunks and convert the Buffer to a string
    const bodyString = Buffer.concat(body).toString();
    console.log('Body:', bodyString);
    res.end('Request processed!');
  });

  // Respond to the client
  res.statusCode = 200;
  res.setHeader('Content-Type', 'text/plain');
});

server.listen(3000, () => {
  console.log('Server running at http://127.0.0.1:3000/');
});
Enter fullscreen mode Exit fullscreen mode

Full Output Example

When the server is running, and you visit http://127.0.0.1:3000/search?query=nodejs, the output in your terminal would look something like this:

Headers: { host: 'localhost:3000', connection: 'keep-alive', ... }
Status Code: 200
Status Message: OK
URL: /search?query=nodejs
Query Parameter (query): nodejs
Body:
Enter fullscreen mode Exit fullscreen mode

If you send a POST request (e.g., using Postman with body data name=John&age=30), the output would be:

Headers: { host: 'localhost:3000', connection: 'keep-alive', ... }
Status Code: 200
Status Message: OK
URL: /search?query=nodejs
Query Parameter (query): nodejs
Body: name=John&age=30
Enter fullscreen mode Exit fullscreen mode

res Object in Node.js

The res (response) object in Node.js represents the outgoing HTTP response. It is an instance of the http.ServerResponse class and provides methods to set headers, status codes, and send data back to the client.

Key Properties & Methods of res

1. res.statusCode

This property is used to get or set the HTTP status code of the response. By default, it is set to 200, indicating a successful request.

Code:

res.statusCode = 404;  // Set status code to 404 (Not Found)
console.log(res.statusCode); // 404
Enter fullscreen mode Exit fullscreen mode

Example Output:

404
Enter fullscreen mode Exit fullscreen mode

2. res.statusMessage

This is the status message that corresponds to the status code. It is typically a short description of the HTTP status.

Code:

res.statusMessage = 'Not Found';  // Set the status message
console.log(res.statusMessage);  // 'Not Found'
Enter fullscreen mode Exit fullscreen mode

Example Output:

Not Found
Enter fullscreen mode Exit fullscreen mode

3. res.setHeader(name, value)

This method is used to set a specific header in the response. You provide the header name and its corresponding value.

Code:

res.setHeader('Content-Type', 'text/html');
console.log(res.getHeader('Content-Type'));  // 'text/html'
Enter fullscreen mode Exit fullscreen mode

Example Output:

text/html
Enter fullscreen mode Exit fullscreen mode

4. res.getHeader(name)

This method retrieves the value of a specified header.

Code:

res.setHeader('Content-Type', 'application/json');
console.log(res.getHeader('Content-Type'));  // 'application/json'
Enter fullscreen mode Exit fullscreen mode

Example Output:

application/json
Enter fullscreen mode Exit fullscreen mode

5. res.getHeaders()

This method retrieves all the headers set for the response in an object, where each header name is a key and its value is the corresponding header value.

Code:

res.setHeader('Content-Type', 'application/json');
res.setHeader('Cache-Control', 'no-store');
console.log(res.getHeaders());
Enter fullscreen mode Exit fullscreen mode

Example Output:

{
  'content-type': 'application/json',
  'cache-control': 'no-store'
}
Enter fullscreen mode Exit fullscreen mode

6. res.getHeaderNames()

This method returns an array of all header names that have been set in the response.

Code:

res.setHeader('Content-Type', 'application/json');
res.setHeader('Cache-Control', 'no-store');
console.log(res.getHeaderNames());
Enter fullscreen mode Exit fullscreen mode

Example Output:

[ 'content-type', 'cache-control' ]
Enter fullscreen mode Exit fullscreen mode

7. res.hasHeader(name)

This method checks if a particular header has been set in the response. It returns true if the header exists, otherwise false.

Code:

res.setHeader('Content-Type', 'application/json');
console.log(res.hasHeader('Content-Type'));  // true
console.log(res.hasHeader('Authorization'));  // false
Enter fullscreen mode Exit fullscreen mode

Example Output:

true
false
Enter fullscreen mode Exit fullscreen mode

8. res.removeHeader(name)

This method removes a specific header from the response.

Code:

res.setHeader('Content-Type', 'application/json');
res.removeHeader('Content-Type');
console.log(res.getHeader('Content-Type'));  // undefined
Enter fullscreen mode Exit fullscreen mode

Example Output:

undefined
Enter fullscreen mode Exit fullscreen mode

9. res.end([data])

This method signals the end of the response. It sends the data (if provided) to the client and ends the response.

Code:

res.statusCode = 200;
res.setHeader('Content-Type', 'text/plain');
res.end('Hello, World!');
Enter fullscreen mode Exit fullscreen mode

Example Output:

Response sent to the client: "Hello, World!"
Enter fullscreen mode Exit fullscreen mode

Full Example Code for res Object

Here's the full code demonstrating how to use the res object in a basic HTTP server. This code handles setting headers, checking headers, sending a response, and more.

const http = require('http');

const server = http.createServer((req, res) => {
  // 1. Set response status code and message
  res.statusCode = 200;
  res.statusMessage = 'OK';

  // 2. Set response headers
  res.setHeader('Content-Type', 'application/json');
  res.setHeader('Cache-Control', 'no-store');

  // 3. Get response headers
  console.log('Headers:', res.getHeaders());  // { 'content-type': 'application/json', 'cache-control': 'no-store' }

  // 4. Get specific header
  console.log('Content-Type:', res.getHeader('Content-Type'));  // 'application/json'

  // 5. Get header names
  console.log('Header Names:', res.getHeaderNames());  // [ 'content-type', 'cache-control' ]

  // 6. Check if header exists
  console.log('Has Content-Type:', res.hasHeader('Content-Type'));  // true
  console.log('Has Authorization:', res.hasHeader('Authorization'));  // false

  // 7. Remove a header
  res.removeHeader('Cache-Control');
  console.log('Headers after removal:', res.getHeaders());  // { 'content-type': 'application/json' }

  // 8. End the response
  res.end('Response sent to the client');
});

server.listen(3000, () => {
  console.log('Server running at http://127.0.0.1:3000/');
});
Enter fullscreen mode Exit fullscreen mode

Full Output Example

When you run the server and visit http://127.0.0.1:3000/, the output in your terminal would look something like this:

Headers: { 'content-type': 'application/json', 'cache-control': 'no-store' }
Content-Type: application/json
Header Names: [ 'content-type', 'cache-control' ]
Has Content-Type: true
Has Authorization: false
Headers after removal: { 'content-type': 'application/json' }
Response sent to the client
Enter fullscreen mode Exit fullscreen mode

Final Project: Real-Life Node.js HTTP Server with Full req and res Functionality

In this final project, we will build a real-life HTTP server using Node.js. The server will demonstrate the usage of all the req (request) and res (response) functionalities that we've discussed.

Project Overview:

This project will include:

  • Handling different HTTP methods (GET, POST).
  • Logging and interacting with various req properties (headers, status codes, query parameters, request body).
  • Manipulating response properties like status codes, headers, and sending responses with different formats.

Full Project Code

const http = require('http');
const url = require('url');

// Create an HTTP server
const server = http.createServer((req, res) => {

  // 1. Log Request Headers
  console.log('Request Headers:', req.headers);

  // 2. Log Request Status Code and Message
  console.log('Request Status Code:', req.statusCode);  // typically used for response
  console.log('Request Status Message:', req.statusMessage);  // typically used for response

  // 3. Log Requested URL
  console.log('Requested URL:', req.url);

  // 4. Handle Query Parameters
  if (req.method === 'GET' && req.url.startsWith('/greet')) {
    const queryObject = url.parse(req.url, true).query;
    const name = queryObject.name || 'Guest';
    console.log('Query Parameter (name):', name);

    // Sending response with query parameter
    res.statusCode = 200;
    res.setHeader('Content-Type', 'application/json');
    res.end(JSON.stringify({ message: `Hello, ${name}!` }));

  // 5. Handle POST request to /submit
  } else if (req.method === 'POST' && req.url === '/submit') {
    let body = [];  // Initialize an empty array to accumulate chunks

    // Collecting body data chunks
    req.on('data', chunk => {
      body.push(chunk);  // Append each chunk to the body array
    });

    req.on('end', () => {
      // Concatenate all the chunks and convert the Buffer to a string
      const bodyString = Buffer.concat(body).toString();
      console.log('Received Body:', bodyString);  // Log the raw body data

      // Try parsing the body if it's JSON
      try {
        const parsedBody = JSON.parse(bodyString);
        const name = parsedBody.name || 'No name provided';
        const age = parsedBody.age || 'No age provided';

        // Set response headers and status code
        res.statusCode = 200;
        res.setHeader('Content-Type', 'application/json');

        // Send JSON response back
        res.end(JSON.stringify({ name, age }));

      } catch (error) {
        // If the body is not in valid JSON format, respond with a 400 error
        res.statusCode = 400;
        res.setHeader('Content-Type', 'application/json');
        res.end(JSON.stringify({ error: 'Invalid JSON format' }));
      }
    });

  // Handle Invalid Routes
  } else {
    res.statusCode = 404;
    res.setHeader('Content-Type', 'text/plain');
    res.end('Not Found');
  }

  // 6. Set Response Headers (Examples)
  res.setHeader('X-Powered-By', 'Node.js');
  res.setHeader('Cache-Control', 'no-store');

  // Log the response headers
  console.log('Response Headers:', res.getHeaders());

  // 7. Log the Status Code and Message for Response
  res.statusCode = 200;
  res.statusMessage = 'OK';
  console.log('Response Status Code:', res.statusCode);  // 200
  console.log('Response Status Message:', res.statusMessage);  // OK

  // 8. Check if a header exists and remove it
  console.log('Has Content-Type header?', res.hasHeader('Content-Type'));  // true
  res.removeHeader('Content-Type');
  console.log('Content-Type after removal:', res.getHeader('Content-Type'));  // undefined

  // Send response
  res.end('Response Sent!');
});

// Start the server
server.listen(3000, () => {
  console.log('Server running at http://127.0.0.1:3000/');
});
Enter fullscreen mode Exit fullscreen mode

Detailed Explanation:

  1. Request Handling and req Object:

    • req.headers: Logs all headers sent by the client.
    • req.statusCode & req.statusMessage: Logs status code and message (though typically used for response, we log here for demonstration).
    • req.url: Logs the full URL path of the incoming request.
    • Query Parameters: Extracts and logs query parameters from the URL using url.parse() method.
    • Body Reading (using Buffer): Handles POST requests by collecting data chunks, concatenating them, and parsing the body using Buffer.concat() to handle the body efficiently.
  2. Response Handling and res Object:

    • res.statusCode & res.statusMessage: Sets and logs the status code and message for the response.
    • res.setHeader(name, value): Sets response headers.
    • res.getHeaders(): Logs all headers set for the response.
    • res.getHeader(name): Retrieves and logs specific headers like Content-Type.
    • res.hasHeader(name): Checks if a particular header is set.
    • res.removeHeader(name): Removes a header from the response.
    • res.end([data]): Ends the response and sends the data to the client.

Example Requests and Responses

  1. Test the GET /greet Route:
  • Request: GET http://127.0.0.1:3000/greet?name=John
  • Response:
   {
     "message": "Hello, John!"
   }
Enter fullscreen mode Exit fullscreen mode
  1. Test the POST /submit Route with Valid JSON:
  • Request: POST http://127.0.0.1:3000/submit with body:
   {
     "name": "Alice",
     "age": 25
   }
Enter fullscreen mode Exit fullscreen mode
  • Response:
   {
     "name": "Alice",
     "age": 25
   }
Enter fullscreen mode Exit fullscreen mode
  1. Test the POST /submit Route with Invalid JSON:
  • Request: POST http://127.0.0.1:3000/submit with body:
   name=John&age=30
Enter fullscreen mode Exit fullscreen mode
  • Response:
   {
     "error": "Invalid JSON format"
   }
Enter fullscreen mode Exit fullscreen mode
  1. Test Invalid Route (404):
  • Request: GET http://127.0.0.1:3000/unknown
  • Response: Not Found

Conclusion

This full project demonstrates how to handle incoming requests and responses using the req and res objects in Node.js. It includes:

  • Logging request properties like headers, status codes, and query parameters.
  • Handling request bodies using buffers and parsing them.
  • Managing response headers, status codes, and sending appropriate responses.

By combining all these functionalities, you get a robust foundation for building more advanced APIs or web servers in Node.js.

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .