Page Content

Tutorials

How to create a HTTP Server in NodeJS?

Creating an HTTP Server in NodeJS

Without requiring any other libraries, you may establish HTTP servers using Node.js’s built-in http module. Node.js is a strong tool for backend web development because of this.

Usually, the http.createServer() method is used to create a server. This method’s input is a request listener function that runs each time the server receives an HTTP request. Request (commonly shortened to req) and response (often shortened to res) are two essential objects that are passed to this function.

After creating the server, you need to tell it to listen for incoming connections on a specific port and optionally a hostname using server.listen(). Node.js servers are long running processes, meaning they’ll keep running until explicitly stopped (e.g., by pressing Ctrl+C in the terminal) or if they encounter an unhandled error.

HTTP Protocol Basics: The Request/Response Model

The World Wide Web is based on the HyperText Transfer Protocol (HTTP), which uses a simple request/response paradigm. Imagine it like a client placing an order at a counter for food:

  1. Client (Customer): The person who starts the conversation, be it your web browser, a mobile application, or another server. Usually passive, the client waits to send requests to the server instead of reaching out on its own.
  2. Request (Order): The server receives a request from the client. A standard HTTP request consists of the following essential components:
    • URL (Uniform Resource Locator):  Indicates the particular resource the client is requesting (e.g., /home, /api/users).
    • HTTP Method (Verb): Indicates the desired action to be performed on the resource. Common methods include:
      • GET: To retrieve data from the server. For instance, fetching a list of anime or a webpage.
      • POST: To send data to the server. For example, submitting form data.
      • PUT: To update an existing resource.
      • DELETE: To remove a resource from the server.
    • HTTP Headers: Key-value pairs that include extra details about the request, like the Accept-Encoding or Content-Type.
    • Message Body (Optional):  Contains the data being sent with the request; usually used with PUT or POST methods (e.g., JSON payload, form data).
  3. Server (Chef): The machine that waits for requests is known as the server (chef).
  4. Response (Prepared Food): After reviewing the request, the server provides the customer with a response. An HTTP response usually consists of:
    • Status Code:  A three-digit code that indicates the status of a request (e.g., 200 OK for success, 404 Not Found for a missing resource) is known as the status code.
    • HTTP Headers: These include details about the answer, like the data’s Content-Type (text/plain, application/json, text/html, etc.).
    • Message Body (Optional): The actual data being returned, such as an HTML page, JSON object, or plain text, is called the ◦ Message Body (Optional).

The fact that HTTP is stateless that is, each request and answer are autonomous and do not retain any information about prior exchanges should be noted. There is a strong push towards HTTPS (HTTP over TLS/SSL) for safe, encrypted communication, even if HTTP versions like 1.1 are still in use today.

Request () and Response () Objects

You may interact with incoming HTTP requests and create responses primarily using these two objects.

Request Object ()

The incoming client request’s whole contents are contained in the req object.

  • req.url:  This field holds the URL path that the client has requested. Using the URL, you can use this to construct routing logic and determine what content to provide.
  • req.method: The field req.method specifies the HTTP method (GET, POST, etc.) that was applied to the request.
  • req.headers: A collection of all the client-sent HTTP headers.
  • A readable stream is the req object itself. You can use data events to listen for the data in “chunks” that arrive in response to requests that have a body, such as POST or PUT.

Response Object ()

The HTTP response is created using the res object and sent back to the client. The stream can be written.

  1. res.writeHead(statusCode, headers): When sending a response, the first method you usually call is res.writeHead(statusCode, headers). It sets the HTTP response headers (e.g., Content-Type) and the HTTP status code (e.g., 200 for OK, 404 for Not Found).
  2. res.write(data): A portion of the response body is sent to the client by the res.write(data) function. To deliver data progressively, use res.write() more than once.
  3. res.end(data): Every response needs to call res.end(data) to indicate that the response is finished and should be sent to the client by the server. Passing the last piece of data to res.end() is an optional option.

Here’s an example of a basic Node.js web server handling different routes and content types:

// Import the built-in 'http' module 
const http = require('http');

// Define the host and port for the server 
const hostname = '127.0.0.1'; // localhost 
const port = 3000; // Common port for development 

// Create a request listener function 
const requestListener = function (req, res) {
    // Log the incoming request URL and method for debugging 
    console.log(`Request received: ${req.method} ${req.url}`);

    // Basic routing based on req.url 
    if (req.url === '/') {
        // Handle the root path: send HTML 
        res.writeHead(200, { 'Content-Type': 'text/html' }); // Set status code and Content-Type header 
        res.end('<html><body><h1>Welcome to our Node.js Server!</h1><p>Visit /api for JSON data, or /about for plain text.</p></body></html>'); // Send HTML response and close it 
    } else if (req.url === '/api') {
        // Handle '/api' path: send JSON data 
        res.writeHead(200, { 'Content-Type': 'application/json' }); // Set Content-Type for JSON 
        const data = { message: 'Hello from Node.js API!', timestamp: new Date().toISOString() };
        res.end(JSON.stringify(data)); // Convert JS object to JSON string and send 
    } else if (req.url === '/about') {
        // Handle '/about' path: send plain text 
        res.writeHead(200, { 'Content-Type': 'text/plain' }); // Set Content-Type for plain text 
        res.end('This is a simple Node.js web server example. Thanks for visiting!'); // Send plain text 
    } else {
        // Handle any other path: send 404 Not Found 
        res.writeHead(404, { 'Content-Type': 'text/plain' }); // Set 404 status 
        res.end('404 Not Found - The page you are looking for does not exist.'); // Send error message 
    }
};

// Create the server instance using the request listener 
const server = http.createServer(requestListener);

// Start the server and listen on the specified port and hostname 
server.listen(port, hostname, () => {
    console.log(`Server is running on http://${hostname}:${port}`); // Log server startup message 
});

To run this code:

  1. Save it as server.js (or any other .js file).
  2. Open your terminal, navigate to the directory where you saved the file.
  3. Run the command: node server.js.

Example Output in Terminal after running node server.js:

Server is running on http://127.0.0.1:3000

After accessing http://localhost:3000 in a browser:

Request received: GET /

After accessing http://localhost:3000/api in a browser:

Request received: GET /api

After accessing http://localhost:3000/about in a browser:

Request received: GET /about

After accessing http://localhost:3000/nonexistent in a browser:

Request received: GET /nonexistent

You can stop the server by pressing Ctrl+C in the terminal.

Building a web server in Node.js using the http module is like setting up a simple post office. The http module is the building itself, providing the infrastructure. When a client (customer) sends a request (a letter), the server (post office staff) receives it. The req object is the envelope, containing all the sender’s details, address, and what they’re trying to send.

The res object is the blank return envelope and paper; you use res.writeHead() to stamp it with the delivery status and type of content, res.write() to write the message incrementally, and res.end() to seal and send it back to the customer. This enables efficient, event-driven communication, allowing the post office to handle many letters without getting stuck waiting for any single one.

Index