HTTP Server Dasar — Node.js

Node.js bisa membuat web server tanpa framework apapun. Server paling sederhana: import http from "http"; const server = http.createServer((req, res) => {…

Server adalah program yang menunggu pertanyaan dan menjawabnya. Bayangin loket informasi di stasiun: petugas duduk di loket nomor 3000 dan menunggu. Tiap orang datang membawa pertanyaan, petugas menjawab, lalu menutup dengan "sudah ya". Di Node, pertanyaan itu request, jawabannya response, nomor loketnya port, dan "sudah ya" adalah res.end(). Semua itu ada di modul bawaan http.

🧪 Tebakan cepat: handler-mu memanggil res.writeHead(200, ...) tapi lupa res.end(). Apa yang dialami browser atau curl yang bertanya? Tebak dulu, jawabannya ada di bagian "res.end(): jawabannya selesai".

Membuat server dengan http.createServer

Proyek catatan-api sekarang menjawab lewat jaringan. Buat file server.js:

const http = require("node:http");

const catatan = [
  { id: 1, judul: "Belanja", isi: "beli beras 5 kg" },
  { id: 2, judul: "Belajar", isi: "bab Node.js" },
];

const server = http.createServer((req, res) => {
  console.log(req.method + " " + req.url);
  if (req.method === "GET" && req.url === "/catatan") {
    res.writeHead(200, { "Content-Type": "application/json" });
    res.end(JSON.stringify(catatan));
    return;
  }
  res.writeHead(404, { "Content-Type": "application/json" });
  res.end(JSON.stringify({ error: "Tidak ditemukan" }));
});

server.listen(3000, () => {
  console.log("Server jalan di http://localhost:3000");
});

Mencoba server-nya

Jalankan node server.js. Bedanya dengan script biasa: program ini gak selesai, dia terus menunggu request sampai kamu menekan Ctrl+C. Buka terminal kedua dan tanya dengan curl -i (-i ikut menampilkan header):

$ curl -i http://localhost:3000/catatan
HTTP/1.1 200 OK
Content-Type: application/json
Date: Thu, 08 Oct 2026 03:00:00 GMT
Connection: keep-alive
Keep-Alive: timeout=5
Transfer-Encoding: chunked

[{"id":1,"judul":"Belanja","isi":"beli beras 5 kg"},{"id":2,"judul":"Belajar","isi":"bab Node.js"}]

Baris pertama adalah status: 200 OK. Lalu header: Content-Type dari kodemu, sisanya ditambahkan Node sendiri. Setelah baris kosong, body-nya. Di terminal pertama, server mencetak GET /catatan. Membuka http://localhost:3000/catatan di browser juga memberi JSON yang sama.

Membaca method dan URL

Server ini cuma menjawab GET /catatan. Sisanya dapat 404:

Request req.method req.url Status
GET /catatan "GET" "/catatan" 200
POST /catatan "POST" "/catatan" 404
GET /catatan?urut=judul "GET" "/catatan?urut=judul" 404

Baris terakhir sering bikin bingung: req.url membawa query string (bagian setelah ?), jadi gak sama dengan "/catatan". Ambil path-nya saja dengan new URL(req.url, "http://localhost").pathname, hasilnya "/catatan".

res.end(): jawabannya selesai

Tanpa res.end(), jawabannya gak pernah dikirim. Node bahkan menahan status dan header-nya, jadi yang bertanya gak menerima apa pun dan terus menunggu: request-nya menggantung. Browser memutar ikon loading, dan curl yang dibatasi 5 detik menyerah:

$ curl -i -m 5 http://localhost:3000/catatan
curl: (28) Operation timed out after 5002 milliseconds with 0 bytes received

Itu jawaban tebakannya. Tiap jalur di handler harus berakhir dengan tepat satu res.end().

Di latihan: server tanpa request sungguhan

Simulator latihan gak mengirim request ke server-mu, jadi baris jawabannya dicetak dari object yang sama. Yang kamu tulis: require("http"), http.createServer, di dalam callback res.writeHead(200, { "Content-Type": "application/json" }) lalu res.end(JSON.stringify({ message: "Halo dari Node.js!" })). Output-nya:

Server dibuat!
Response: {"message":"Halo dari Node.js!"}

Kenapa nanti pakai Express

Server ini baru punya satu route, dan sudah butuh if untuk method, path, dan query. Puluhan route berarti puluhan if, ditambah membaca body JSON sendiri. Express, di pelajaran berikutnya, mengurus semua itu di atas modul http yang sama.

⚠️ Jebakan yang sering ketemu

TL;DR: http.createServer((req, res) => {...}) membuat server yang memanggil handler sekali untuk tiap request, dan server.listen(3000) mulai menunggu di port 3000. Baca req.method dan req.url (ingat, req.url ikut membawa query string). Jawab dengan res.writeHead(status, { "Content-Type": "application/json" }) lalu res.end(JSON.stringify(data)). Tanpa res.end(), request menggantung. Tiap jalur menjawab tepat sekali, jadi return setelah menjawab, kalau gak, ERR_HTTP_HEADERS_SENT mematikan server.

Yang akan kamu pelajari