WeCodeAcademy

Step 3: Create to-dos with POST

To create a to-do the client sends a JSON body. Reading a request body in Node is asynchronous: the data arrives in chunks. A readBody helper collects them and parses the JSON, returning a promise so the route can simply await it.

ExampleNode.js
const http = require("http");

const todos = [];
let nextId = 1;

function send(res, status, data) {
  res.writeHead(status, { "Content-Type": "application/json" });
  res.end(JSON.stringify(data));
}
function readBody(req) {
  return new Promise((resolve, reject) => {
    let raw = "";
    req.on("data", (chunk) => (raw += chunk));
    req.on("end", () => {
      try {
        resolve(raw ? JSON.parse(raw) : {});
      } catch (err) {
        reject(new Error("Invalid JSON"));
      }
    });
  });
}

async function handle(req, res) {
  if (req.method === "GET" && req.url === "/todos") return send(res, 200, todos);

  if (req.method === "POST" && req.url === "/todos") {
    const body = await readBody(req);
    const todo = { id: nextId++, title: body.title, done: false };
    todos.push(todo);
    return send(res, 201, todo);
  }
  send(res, 404, { error: "Not found" });
}

// ---- demo: start on a free port, make a few requests, stop ----
const server = http.createServer(handle);
server.listen(0, async () => {
  const base = `http://localhost:${server.address().port}`;
  const call = async (method, path, body) => {
    const res = await fetch(base + path, { method, body: body ? JSON.stringify(body) : undefined });
    const text = await res.text();
    console.log(method, path, "->", res.status, text || "(empty)");
  };
  await call("POST", "/todos", { title: "Learn Node" });
  await call("POST", "/todos", { title: "Build an API" });
  await call("GET", "/todos");
  server.close();
});
Output
POST /todos -> 201 {"id":1,"title":"Learn Node","done":false}
POST /todos -> 201 {"id":2,"title":"Build an API","done":false}
GET /todos -> 200 [{"id":1,"title":"Learn Node","done":false},{"id":2,"title":"Build an API","done":false}]

Each new to-do gets the next id, done: false, and the response status is 201 Created. The list now shows both.

Quick check

Why does readBody return a promise?

Finish the quick check (and any code exercise) to complete this lesson, or mark it done yourself.

Tip: use the left and right arrow keys to move between lessons.