Membaca permintaan HTTP pada modul http berarti mengakses properti dan peristiwa pada objek IncomingMessage yang diberikan ke callback createServer. Permintaan terdiri atas baris awal yang memuat method, URL, dan versi HTTP, daftar header, serta body opsional yang mengalir sebagai potongan data. Modul http tidak mengurai body secara otomatis dan tidak menyediakan struktur jalur atau parameter kueri yang siap pakai, sehingga keduanya perlu ditangani secara eksplisit memakai kelas URL dan stream. Setelah membaca topik ini, pembaca dapat mengambil method, header, dan parameter kueri dari permintaan, serta membaca body permintaan secara aman dengan event stream req.
Method dan URL permintaan#
Properti req.method berisi metode HTTP sebagai string dalam huruf kapital, tanpa perlu dinormalkan sendiri. Properti req.url berisi bagian URL setelah host, yaitu jalur lengkap beserta string kueri, tetapi tanpa skema dan tanpa host. Properti ini nilainya mentah, sehingga /catatan/12?halaman=2 utuh muncul sebagai string yang sama tanpa pemisahan jalur dan kueri. Pemisahan baru dilakukan ketika URL diurai dengan kelas URL.
const http = require('node:http');
const server = http.createServer((req, res) => {
console.log('method:', req.method, '| url:', req.url);
res.writeHead(204);
res.end();
});
server.listen(0, '127.0.0.1', async () => {
const { port } = server.address();
await fetch(`http://127.0.0.1:${port}/catatan/12?halaman=2`, { method: 'GET' });
await fetch(`http://127.0.0.1:${port}/catatan`, { method: 'POST', body: 'satu' });
server.close();
});method: GET | url: /catatan/12?halaman=2
method: POST | url: /catatanProperti req.httpVersion berisi versi HTTP sebagai string seperti 1.1 atau 2.0, dan req.httpVersionMajor serta req.httpVersionMinor menyediakan komponennya sebagai angka. Mayoritas aplikasi tidak perlu memeriksa versi HTTP secara langsung karena Node sudah menangani perbedaan antara HTTP/1.1 dan HTTP/2 pada level transport. Pemakaian properti req.method sebagai dasar percabangan lebih aman daripada memeriksa header X-HTTP-Method-Override yang biasanya merupakan konvensi framework dan bukan bagian dari standar HTTP.
Header permintaan#
Header permintaan diakses melalui req.headers, yaitu objek biasa dengan nama header sudah dinormalkan ke huruf kecil. Normalisasi nama header ke lowercase adalah perilaku bawaan Node, sehingga pengaksesan req.headers['Content-Type'] mengembalikan undefined dan pengaksesan req.headers['content-type'] mengembalikan nilai header. Header yang muncul beberapa kali, seperti Set-Cookie pada respons atau Cookie pada permintaan, digabungkan menjadi satu string yang dipisahkan koma oleh Node.
const http = require('node:http');
const server = http.createServer((req, res) => {
console.log('content-type:', req.headers['content-type'] || '(tidak ada)');
console.log('authorization:', req.headers['authorization'] ? 'ada' : 'tidak ada');
console.log('x-request-id:', req.headers['x-request-id'] || '(tidak ada)');
res.writeHead(204);
res.end();
});
server.listen(0, '127.0.0.1', async () => {
const { port } = server.address();
await fetch(`http://127.0.0.1:${port}/kirim`, {
method: 'POST',
headers: {
'content-type': 'application/json',
'authorization': 'Bearer abc123',
'x-request-id': 'req-001',
},
body: '{}',
});
server.close();
});content-type: application/json
authorization: ada
x-request-id: req-001Pengaksesan header yang sensitif seperti authorization sebaiknya tidak dilakukan pada log produksi, sebab nilai header tersebut berisi token atau kredensial yang bocor bila dicatat begitu saja. Kebijakan penanganan header pada level logging biasanya memisahkan daftar header yang aman dicatat dari header yang harus disaring.
Membaca body permintaan#
Body permintaan tidak otomatis dimuat ke memori oleh modul http. Objek req adalah stream Readable, sehingga body dibaca dengan memasang penerima pada peristiwa data dan menunggu peristiwa end sebelum diproses. Pola yang umum dipakai adalah mengumpulkan potongan Buffer ke sebuah deret, kemudian menggabungkannya dengan Buffer.concat dan mengonversi hasilnya ke string sesuai encoding yang sesuai.
const http = require('node:http');
function bacaBody(req) {
return new Promise((resolve, reject) => {
const potongan = [];
req.on('data', (chunk) => potongan.push(chunk));
req.on('end', () => resolve(Buffer.concat(potongan).toString('utf8')));
req.on('error', reject);
});
}
const server = http.createServer(async (req, res) => {
const body = await bacaBody(req);
console.log('panjang body:', body.length, '| isi:', body);
res.writeHead(204);
res.end();
});
server.listen(0, '127.0.0.1', async () => {
const { port } = server.address();
await fetch(`http://127.0.0.1:${port}/catatan`, {
method: 'POST',
headers: { 'content-type': 'text/plain' },
body: 'belajar modul http',
});
server.close();
});panjang body: 18 | isi: belajar modul httpPembungkusan pola peristiwa ke dalam promise seperti di atas membuat callback createServer dapat memakai async/await, sehingga kode menjadi lurus dan error dapat ditangkap dengan try/catch. Tanpa pembungkusan, pengaksesan req sebagai stream mendorong pola callback bersarang yang sulit dirawat ketika body perlu diurai lebih lanjut sebagai JSON atau form.
Parameter kueri dengan URLSearchParams#
String kueri pada req.url tidak diurai otomatis oleh Node. Penguraian dilakukan dengan membuat objek URL yang memerlukan basis mutlak, sehingga basis dummy sering dipakai hanya agar konstruktor berhasil. Setelah objek URL jadi, properti searchParams menyediakan antarmuka URLSearchParams dengan metode get, has, append, delete, serta keys dan entries untuk iterasi.
const http = require('node:http');
const server = http.createServer((req, res) => {
const url = new URL(req.url, `http://${req.headers.host}`);
console.log('pathname:', url.pathname);
console.log('halaman:', url.searchParams.get('halaman'));
console.log('urut:', url.searchParams.get('urut'));
console.log('aktif:', url.searchParams.get('aktif'));
console.log('semua kunci:', [...url.searchParams.keys()].join(','));
res.writeHead(204);
res.end();
});
server.listen(0, '127.0.0.1', async () => {
const { port } = server.address();
await fetch(`http://127.0.0.1:${port}/catatan?halaman=2&urut=nama&aktif=true`);
server.close();
});pathname: /catatan
halaman: 2
urut: nama
aktif: true
semua kunci: halaman,urut,aktifKonstruktor URL memerlukan URL mutlak agar dapat diurai, dan untuk permintaan HTTP/1.1 host biasanya tersedia pada header host. Pemakaian http://${req.headers.host} sebagai basis menjadikan req.url yang relatif lengkap menjadi URL mutlak yang valid. Parameter kueri yang muncul beberapa kali dengan nama yang sama, misalnya tag=a&tag=b, dapat diambil seluruhnya dengan url.searchParams.getAll('tag') yang mengembalikan deret string.
Kesalahan umum#
Mengabaikan body permintaan pada metode POST atau PUT menyebabkan klien menunggu respons tanpa henti karena Node menahan peristiwa end sampai seluruh body dibaca. Penerima data minimal perlu dipasang agar stream req mengalir, atau lebih baik membaca seluruh body dengan pola promise seperti di atas. Tanpa pemanggilan req.resume() atau pemasangan penerima data, klien yang mengirim body besar akan tergantung sampai timeout.
Memanggil JSON.parse(body) langsung pada body string tanpa try/catch menghentikan proses bila body bukan JSON valid. Pembungkusan dalam try/catch dan respons 400 Bad Request dengan pesan error yang tidak membocorkan detail internal menjadi praktik standar. Pemakaian Buffer.concat(potongan).toString('utf8') mengasumsikan body adalah teks UTF-8, sehingga body biner seperti unggahan berkas perlu ditangani dengan stream langsung ke fs.createWriteStream tanpa konversi string.
Mengakses req.headers.Host dengan huruf kapital mengembalikan undefined karena Node menormalkan nama header ke huruf kecil. Kebiasaan ini sering muncul pada kode yang dipindahkan dari bahasa lain yang memperlakukan header dengan peka huruf besar-kecil. Konsistensi memakai huruf kecil pada seluruh pengaksesan header menghindari kesalahan ini.
Ringkasan#
req.methodberisi metode HTTP dalam huruf kapital danreq.urlberisi jalur beserta string kueri tanpa host, keduanya siap pakai saat callback dipanggil.req.headerssudah menormalkan nama header ke huruf kecil, dan header yang muncul beberapa kali digabungkan menjadi satu string yang dipisahkan koma.- Body permintaan dibaca lewat peristiwa
datadanendpada streamreq, dan pembungkusan pola ini ke promise memungkinkan pemakaianasync/awaitpada callback. - String kueri diurai dengan
new URL(req.url, basis)dan diakses lewatsearchParams, yang menyediakanget,getAll,has, dan iterasikeysatauentries.
Referensi#
- HTTP — Node.js
— Referensi resmi modul
http, termasuk propertiIncomingMessage.method,IncomingMessage.url, danIncomingMessage.headers. - Class URLSearchParams — Node.js
— Daftar metode
get,getAll,has,keys, danentriesuntuk mengakses parameter kueri.