Lab - Simple Todo List and curl

Need a bare app for quick reference and experiments.

Preparation

  • Node.js, optionally yarn

Todo App

Create a project folder and setup a dummy todo-list Express app:

mkdir todo
cd todo
yarn init -y
yarn add express

with the file app.js

const express = require('express');

const PORT = 3000;

let nextId = 4;
let todos = [
    { id: 1, title: 'Exercise', done: true, },
    { id: 2, title: 'Learn Python', done: false, },
    { id: 3, title: 'Lunch', done: false, },
];

function findTodo(id) {
    return todos.find(todo => todo.id === id);
}
function addTodo({ title, done }) {
    const todo = { id: nextId++, title, done };
    todos.push(todo);
    return todo;
}
function deleteTodo(id) {
    todos = todos.filter(t => t.id !== id);
}

const app = express();
app.use(express.json());
app.set('json spaces', 2);

app.get('/', (req, res) => {
    res.json({ message: 'ok' });
});

app.get('/todo', (req, res) => {
    res.json(todos);
});

app.post('/todo', (req, res) => {
    const { title = '', done = false } = req.body;
    const todo = addTodo({ title, done });
    res.json(todo);
});

app.get('/todo/:id(\\d+)', (req, res) => {
    const id = parseInt(req.params.id);
    const todo = findTodo(id);
    if (!todo) return res.status(404).send('Not Found');

    res.json(todo);
});
app.put('/todo/:id(\\d+)', (req, res) => {
    const id = parseInt(req.params.id);
    const { title, done } = req.body;

    const todo = findTodo(id);
    if (!todo) return res.status(404).send('Not Found');

    if (title !== undefined) todo.title = title;
    if (done !== undefined) todo.done = done;

    res.json(todo);
});

app.delete('/todo/:id(\\d+)', (req, res) => {
    const id = parseInt(req.params.id);
    deleteTodo(id);
    res.end();
});

app.get('/_bad', (req, res) => {
    throw Error('This is bad');
});

app.all('*', (req, res, next) => {
    res.status(400).send('Bad Request');
});

app.use((err, req, res, next) => {
    res.status(500).send('Something wrong!');
});

app.listen(PORT, () => {
   console.log(`Service at http://localhost:${PORT}`);
});

Then run it

$ node app.js
Service at http://localhost:3000

Using curl

Let's use curl to interact with the app:

$ curl http://localhost:3000
{"message":"ok"}

$ curl -i http://localhost:3000
HTTP/1.1 200 OK
X-Powered-By: Express
Content-Type: application/json; charset=utf-8
Content-Length: 21
ETag: W/"15-FCv+/NlfTgD7mX/4JeAWgb2wmko"
Date: Tue, 08 Oct 2024 03:37:43 GMT
Connection: keep-alive
Keep-Alive: timeout=5

{
  "message": "ok"
}

For the todo list part:

$ curl http://localhost:3000/todo
[
  {
    "id": 1,
    "title": "Exercise",
    "done": true
  },
  {
    "id": 2,
    "title": "Learn Python",
    "done": false
  },
  {
    "id": 3,
    "title": "Lunch",
    "done": false
  }
]

Now for a given item withid 2

$ curl http://localhost:3000/todo/2
{
  "id": 2,
  "title": "Learn Python",
  "done": false
}

To see actual response:

$ curl -i localhost:3000/todo/2
HTTP/1.1 200 OK
X-Powered-By: Express
Content-Type: application/json; charset=utf-8
Content-Length: 57
ETag: W/"39-4iEWOhMKMHfAB97MzK2B0SENTfw"
Date: Mon, 07 Oct 2024 01:55:18 GMT
Connection: keep-alive
Keep-Alive: timeout=5

{
  "id": 2,
  "title": "Learn Python",
  "done": false
}

404 and 400

But for unknown id 5:

$ curl http://localhost:3000/todo/5
Not Found

And for mis-spelled URL:

$ curl localhost:3000/todos
Bad Request

500 Error

To trigger system error:

$ curl localhost:3000/_bad
Something wrong!

POST - Create New Item

To post via curl, we have

$ curl --header "Content-Type: application/json" \
    --request POST \
    --data '{"title":"Dinner","done":false}' \
    http://localhost:3000/todo
{
  "id": 4,
  "title": "Dinner",
  "done": false
}

Or shorter command

curl -X POST -H "Content-Type: application/json" \
    -d '{"title":"Dinner","done":false}' \
    http://localhost:3000/todo

PUT - Update an Item

To update a todo item:

$ curl -X PUT -H "Content-Type: application/json" \
    -d '{"done":true}' \
    http://localhost:3000/todo/2
{
  "id": 2,
  "title": "Learn Python",
  "done": true
}

DELETE - Remote an Item

$ curl -X DELETE http://localhost:3000/todo/3

$ curl http://localhost:3000/todo
[
  {
    "id": 1,
    "title": "Exercise",
    "done": true
  },
  {
    "id": 2,
    "title": "Learn Python",
    "done": true
  },
  {
    "id": 4,
    "title": "Dinner",
    "done": false
  }
]