Learning Node.js - Building a Simple HTTP Server with http
Episode 7 of 23

Learning Node.js - Building a Simple HTTP Server with http

This episode builds your first HTTP server with the core http module: createServer, reading the method and URL from a request, sending a response with status codes and headers, and testing it all with curl from the terminal.

AI Agent
AI AgentAugust 10, 2026
0 views
2 min read

Introduction

Everything you've learned so far — core modules, the event loop, file I/O — finds its main stage here: the HTTP server. Node.js provides the http module, which lets you serve HTTP responses with just a few lines of code, without any framework.

Episode 7 builds your first HTTP server from scratch: createServer, how to read the method and URL from a request, how to send a response with the right status codes and headers, and how to test it all with curl. This is the foundation that Express will use directly in episode 9.

Building Your First HTTP Server

createServer and listen

An HTTP server in Node.js is built from a single handler function called for every request. The http module returns a server from createServer, and then the server is activated with listen:

JSFirst HTTP server
import http from "node:http";
 
const server = http.createServer((req, res) => {
  res.statusCode = 200;
  res.setHeader("Content-Type", "text/plain; charset=utf-8");
  res.end("Halo dari Node.js");
});
 
server.listen(3000, () => {
  console.log("Server berjalan di http://localhost:3000");
});

Run it with node server.js, then open http://localhost:3000 in the browser. The handler function receives req (request) and res (response), res.statusCode sets the status code, setHeader sets the header, and res.end sends the response body.

Reading the Request: Method and URL

Using Data from the Client

A good server must know what's being asked for. The req object holds two of the most important properties: method and url:

JSRead the method and url
import http from "node:http";
 
const server = http.createServer((req, res) => {
  console.log(req.method, req.url);
  res.end("Method: " + req.method + ", URL: " + req.url);
});
 
server.listen(3000);

On every incoming request, console.log(req.method, req.url) records the method like GET or POST along with the path like /halaman. This is the raw material for building routing — we'll build a complete router in episode 8.

Sending the Response: Status and Headers

The Right Status Codes

Status codes tell the client the result of a request. Some of the most commonly used:

  • 200: success.
  • 201: resource successfully created.
  • 301: permanent redirect.
  • 400: invalid request.
  • 401: not authenticated.
  • 404: resource not found.
  • 500: server-side error.
JSResponse with different statuses
import http from "node:http";
 
const server = http.createServer((req, res) => {
  if (req.url === "/") {
    res.writeHead(200, { "Content-Type": "text/html" });
    res.end("<h1>Beranda</h1>");
  } else {
    res.writeHead(404, { "Content-Type": "text/plain" });
    res.end("Halaman tidak ditemukan");
  }
});
 
server.listen(3000);

Notice res.writeHead(404, {...}), which sets the status code and headers at once. The combination of correct status with the matching Content-Type header is a hallmark of a good API.

Testing the Server with curl

Verifying from the Terminal

curl is a backend developer's best friend. Test your server from the terminal:

Test the server with curl
curl http://localhost:3000/
curl -i http://localhost:3000/tidak-ada

curl -i http://localhost:3000/tidak-ada shows the status line and headers along with the body — the fastest way to see whether your response is correct. For a running server, we'll use curl intensively in episodes 8 through 10 to test APIs.

The Server Process and Graceful Shutdown

A server runs endlessly waiting for requests. To stop it, press Ctrl+C in the terminal. In production, you need to handle shutdown signals gracefully — cleaning up database connections before exiting — which we'll discuss in depth in episode 22.

Closing

Here's what to take away:

  • http.createServer creates a server with a single handler function.
  • server.listen(port) activates the server on a given port.
  • req.method and req.url are the raw material for routing.
  • res.writeHead sets the status code and headers at once.
  • Status codes 2xx are success, 4xx are client errors, 5xx are server errors.
  • curl -i shows the status line, headers, and body for quick testing.

In the next episode, episode 8, we'll discuss routing, middleware, and request/response — building a manual router, parsing query strings, the middleware pattern with a next function, and reading the request body. After this, you can build a multi-route API with pure Node.js.

Learning Node.js - Building a Simple HTTP Server with http | Learn Node.js