Implement API endpoints in Node.js server for greeting and notes management, and update README with new endpoint details.
This commit is contained in:
@@ -9,7 +9,7 @@ Edit di Cursor di Mac, commit, lalu `git push`. Deploy ke `ubuntu-vm` terpisah (
|
||||
| Folder | Pelajaran | Port di VM |
|
||||
|--------|-----------|------------|
|
||||
| `pelajaran-1/` | Nginx + HTML statis | `8088` |
|
||||
| `pelajaran-2/` | Node.js di Docker | `8091` |
|
||||
| `pelajaran-2/` | Node.js di Docker — lihat `pelajaran-2/PELAJARAN-2.md` | `8091` |
|
||||
|
||||
## Git remote
|
||||
|
||||
|
||||
+187
-6
@@ -1,13 +1,112 @@
|
||||
const http = require('http');
|
||||
|
||||
|
||||
const notes = [];
|
||||
|
||||
// fungsi ini dipanggil ketika ada request
|
||||
function handleRequest(request, response) {
|
||||
console.log('Ada yang minta:', request.url);
|
||||
|
||||
const waktu = new Date().toISOString("id-ID");
|
||||
|
||||
// --- CABANG API ---
|
||||
if (request.url === '/api/hello') {
|
||||
response.writeHead(200, {
|
||||
"Content-Type": "text/html; charset=utf-8",
|
||||
'Content-Type': 'application/json; charset=utf-8'
|
||||
})
|
||||
response.end(
|
||||
JSON.stringify({
|
||||
message: 'Halo dari API Node',
|
||||
waktu: waktu,
|
||||
})
|
||||
)
|
||||
return; // penting: berhenti disini, jangan kirim HTML juga.
|
||||
}
|
||||
|
||||
if (request.url === '/api/greet' && request.method === 'POST') {
|
||||
let body = '';
|
||||
|
||||
request.on('data', function(chunk) {
|
||||
body += chunk;
|
||||
})
|
||||
|
||||
request.on('end', function() {
|
||||
let name = 'teman';
|
||||
try {
|
||||
const parsed = JSON.parse(body);
|
||||
if (parsed.name) {
|
||||
name = String(parsed.name)
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('Gagal membaca body:', err);
|
||||
}
|
||||
|
||||
response.writeHead(200, {
|
||||
'Content-Type': 'application/json; charset=utf-8'
|
||||
})
|
||||
response.end(
|
||||
JSON.stringify({
|
||||
sapaan: `Halo, ${name}!`,
|
||||
waktu: new Date().toISOString(),
|
||||
})
|
||||
)
|
||||
})
|
||||
return;
|
||||
}
|
||||
|
||||
if (request.url === '/api/notes' && request.method === 'GET') {
|
||||
response.writeHead(200, {
|
||||
'Content-Type': 'application/json; charset=utf-8',
|
||||
})
|
||||
response.end(JSON.stringify(notes));
|
||||
return;
|
||||
}
|
||||
|
||||
if (request.url === '/api/notes' && request.method === 'POST') {
|
||||
let body = '';
|
||||
|
||||
request.on('data', function(chunk) {
|
||||
body += chunk;
|
||||
})
|
||||
request.on('end', function() {
|
||||
let teks = '';
|
||||
try {
|
||||
const parsed = JSON.parse(body);
|
||||
if (parsed.teks) {
|
||||
teks = String(parsed.teks).trim();
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('Gagal membaca body:', err);
|
||||
}
|
||||
|
||||
if (!teks) {
|
||||
response.writeHead(400, {
|
||||
'Content-Type': 'application/json; charset=utf-8',
|
||||
})
|
||||
response.end(JSON.stringify({
|
||||
error: 'Teks tidak boleh kosong',
|
||||
}))
|
||||
return;
|
||||
}
|
||||
|
||||
const note = {
|
||||
id: Date.now(),
|
||||
teks: teks,
|
||||
waktu: new Date().toISOString(),
|
||||
}
|
||||
notes.push(note);
|
||||
|
||||
response.writeHead(201, {
|
||||
'Content-Type': 'application/json; charset=utf-8',
|
||||
})
|
||||
response.end(JSON.stringify(note));
|
||||
return;
|
||||
})
|
||||
return;
|
||||
}
|
||||
// --- CABANG HTML ---
|
||||
response.writeHead(200, {
|
||||
'Content-Type': 'text/html; charset=utf-8'
|
||||
});
|
||||
|
||||
response.end(`<!DOCTYPE html>
|
||||
@@ -18,13 +117,95 @@ function handleRequest(request, response) {
|
||||
</head>
|
||||
<body>
|
||||
<h1>Halo dari Node</h1>
|
||||
<p>Ini dibuat ulang setiap request, bukan file HTML diam.</p>
|
||||
<p>Waktu server: <strong>${waktu}</strong></p>
|
||||
<p>Path yang diminta: <code>${request.url}</code></p>
|
||||
</body>
|
||||
</html>`);
|
||||
<p>Halaman ini dari server. Tombol di bawah memanggil API dari browser.</p>
|
||||
<p>Waktu saat halaman dibuat: <strong>${waktu}</strong></p>
|
||||
<button type="button" id="tombol">Panggil /api/hello</button>
|
||||
<p id="hasil">Belum dipanggil.</p>
|
||||
<hr />
|
||||
<h2>Coba POST</h2>
|
||||
<label>
|
||||
Nama: <br />
|
||||
<input type="text" id="nama" placeholder="namamu" /><br />
|
||||
</label>
|
||||
<button type="button" id="kirim">Kirim ke /api/greet</button>
|
||||
<p id="sapaan">Belum ada sapaan.</p>
|
||||
<hr />
|
||||
<h2>Caatan (memori server)</h2>
|
||||
<ul id='daftar-notes'></ul>
|
||||
<input type='text' id='teks-note' placeholder='Tulis catatan baru...' />
|
||||
<button type='button' id='tambah-note'>Tambah</button>
|
||||
<script>
|
||||
const tombol = document.getElementById("tombol");
|
||||
const hasil = document.getElementById("hasil");
|
||||
tombol.addEventListener("click", async function () {
|
||||
hasil.textContent = "Memuat...";
|
||||
try {
|
||||
const response = await fetch("/api/hello");
|
||||
const data = await response.json();
|
||||
hasil.textContent = data.message + " | " + data.waktu;
|
||||
} catch (err) {
|
||||
hasil.textContent = "Gagal: " + err.message;
|
||||
}
|
||||
});
|
||||
|
||||
const inputNama = document.getElementById("nama");
|
||||
const tombolKirim = document.getElementById("kirim");
|
||||
const teksSapaan = document.getElementById("sapaan");
|
||||
tombolKirim.addEventListener("click", async function () {
|
||||
teksSapaan.textContent = "Mengirim...";
|
||||
try {
|
||||
const response = await fetch("/api/greet", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
},
|
||||
body: JSON.stringify({
|
||||
nama: inputNama.value,
|
||||
}),
|
||||
});
|
||||
const data = await response.json();
|
||||
teksSapaan.textContent = data.sapaan + " (" + data.waktu + ")";
|
||||
} catch (err) {
|
||||
teksSapaan.textContent = "Gagal: " + err.message;
|
||||
}
|
||||
});
|
||||
|
||||
const daftarNotes = document.getElementById("daftar-notes");
|
||||
const inputNote = document.getElementById("teks-note");
|
||||
const tombolNote = document.getElementById("tambah-note");
|
||||
|
||||
async function muatNotes() {
|
||||
const response = await fetch("/api/notes");
|
||||
const data = await response.json();
|
||||
daftarNotes.innerHTML = "";
|
||||
data.forEach(function (note) {
|
||||
const li = document.createElement("li");
|
||||
li.textContent = note.teks + " (" + note.waktu + ")";
|
||||
daftarNotes.appendChild(li);
|
||||
});
|
||||
}
|
||||
|
||||
tombolNote.addEventListener("click", async function () {
|
||||
await fetch("/api/notes", {
|
||||
method: "POST",
|
||||
headers: { "Content-Type": "application/json" },
|
||||
body: JSON.stringify({ teks: inputNote.value }),
|
||||
});
|
||||
inputNote.value = "";
|
||||
await muatNotes();
|
||||
});
|
||||
|
||||
// saat halaman dibuka, ambil daftar yang sudah ada
|
||||
muatNotes();
|
||||
</script>
|
||||
</body>
|
||||
</html>`);
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
// --- Mulai server ---
|
||||
const server = http.createServer(handleRequest);
|
||||
|
||||
server.listen(3000, function() {
|
||||
|
||||
Reference in New Issue
Block a user