Skip to content

Beginner · APIs and request handling · topic 9 of 54 · 30 min

Handling requests: a full CRUD API

Explanation

A handler reads a request and returns a response. With a list of records kept in memory, you can build the four basic actions of almost every app: create, read, update and delete, called CRUD. Each action has its own method, status code and a 404 when the record does not exist.

CRUD: the four basic actions

CRUD stands for Create, Read, Update, Delete. Nearly every app is built from these four actions: a shop adds products, shows them, changes prices and removes old ones. In a REST API, they map to POST, GET, PATCH or PUT, and DELETE.

Think of it like this: Think of the shopkeeper at a kirana store with a stock register. A new item comes in: they write a new line (create). A customer asks the price: they look it up (read). The price changes: they correct the line (update). An item is discontinued: they strike it out (delete). If you ask for an item that is not in the register, they say "we do not have it" (404).

An in-memory store

A store is where the data lives. For now we use a plain array in memory. Each product gets an id from a counter called nextId, which goes up by one for every new product, so two products never share an id.

javascript
const products = [
  { id: 1, name: 'Basmati rice 1kg', price: 120, stock: 40 },
  { id: 2, name: 'Toor dal 1kg', price: 160, stock: 25 },
];
let nextId = 3;

function findProduct(id) {
  return products.find((p) => p.id === id);
}

console.log(findProduct(2));  // the toor dal object
console.log(findProduct(99)); // undefined
The store: an array of objects and a counter for new ids.

One handler, many actions

javascript
const items = [{ id: 1, name: 'Sugar 1kg', price: 45 }];
let nextId = 2;

function handle(request) {
  const parts = request.path.split('/').filter(Boolean);
  const id = Number(parts[1]);

  if (request.method === 'GET' && parts.length === 1) {
    return { status: 200, body: items };
  }
  if (request.method === 'POST' && parts.length === 1) {
    const item = { id: nextId++, name: request.body.name, price: request.body.price };
    items.push(item);
    return { status: 201, body: item };
  }
  const index = items.findIndex((p) => p.id === id);
  if (index === -1) return { status: 404, body: { error: 'Product not found' } };
  if (request.method === 'GET') return { status: 200, body: items[index] };
  if (request.method === 'DELETE') {
    items.splice(index, 1);
    return { status: 204, body: null };
  }
  return { status: 405, body: { error: 'Method not allowed' } };
}

console.log(handle({ method: 'POST', path: '/products', body: { name: 'Tea 250g', price: 140 } }));
console.log(handle({ method: 'GET', path: '/products/2' }));
console.log(handle({ method: 'DELETE', path: '/products/2' }).status); // 204
console.log(handle({ method: 'GET', path: '/products/2' }).status);    // 404
Create (201), read (200), delete (204), and 404 when the id is not found.

Step by step for each request

  1. Read the method and path; find the id if there is one.
  2. For an item, look it up. If it is not there, return 404 straight away.
  3. Do the action: push a new object, change fields, or splice it out.
  4. Return the right status: 200 for reads and updates, 201 for create, 204 for delete.
  5. Return the record in the body (except after delete), so the app can show it.
RequestStore changeResponse
GET /productsnone200 with the array
GET /products/2none200 with one product, or 404
POST /productspush a new object with nextId201 with the new product
PATCH /products/2change only the fields sent200 with the updated product, or 404
DELETE /products/2splice it out204 with no body, or 404
Tip: Return the created product, with its new id, in the 201 response. The app needs the id to show, edit or delete it later, and should not have to make a second request to find it.
Careful: Data in a JavaScript array is lost when the server restarts, and each server copy has its own array. Real apps keep data in a database, which you will learn in module 4. Arrays are only for learning and tests.

Need help?

Stuck on a word or an idea? Search this course, or every course, and jump straight to the explanation or a worked question.

Try:

Watch the lesson

Handling requests: a full CRUD API · 1/6

Create Read Update Delete

Most apps do four basic things with data: create, read, update and delete. We call it CRUD.

Prefer a video by a teacher? Find free videos on “build crud rest api javascript beginners” on YouTube ↗

In real life: A kirana shop billing app

A shop owner in Nagpur uses a phone app to manage stock. Adding a new brand of biscuits sends POST /products and gets back 201 with id 57. When the price changes, the app sends PATCH /products/57 with {"price": 30}. When stock runs out for good, it sends DELETE /products/57. If a staff member's old phone still shows product 57 and tries to open it, the backend answers 404 and the app shows "This product was removed".

Practice (0/3 done)

Task 1 · Code · Javascript

The products array is given. Write a function getProduct(id) that returns { status: 200, body: product } when a product with that id exists, and { status: 404, body: { error: "Product not found" } } when it does not.

Task 2 · Code · Javascript

Write a function createProduct(body). If body.name is a non-empty string and body.price is a number, add { id, name, price, stock } to products (id from nextId, which then goes up by one; stock is body.stock or 0) and return { status: 201, body: newProduct }. Otherwise return { status: 400, body: { error: "name and price are required" } } and add nothing.

Task 3 · Code · Javascript

Write handle(request) for request { method, path, body }. GET /products returns 200 with the whole array. For /products/:id: if the id is not found return 404 with { error: "Product not found" }; GET returns 200 with the product; PATCH changes only price and/or stock if they are in the body and returns 200 with the product; DELETE removes it and returns { status: 204, body: null }. Anything else returns 404 with { error: "Not found" }.

Quick quiz

Question 1

1.What does CRUD stand for?

Question 2

2.A POST /products request adds a new product. What should the response contain?

Question 3

3.PATCH /products/8 arrives but there is no product 8. What do you return?

Question 4

4.Why is a JavaScript array not enough to store a real shop's data?

Question 5

5.Why use a nextId counter instead of products.length + 1 for new ids?

Read more (free)

Open a question to see the answer and why. The first ones are this topic's own quiz, so try the quiz above before you peek.

What does CRUD stand for?

Answer: Create, Read, Update, Delete

CRUD names the four basic actions almost every app performs on its data.

A POST /products request adds a new product. What should the response contain?

Answer: Status 201 and the new product with its id

201 Created, with the new record, so the app knows the new id.

PATCH /products/8 arrives but there is no product 8. What do you return?

Answer: 404 with an error message

The resource does not exist, so 404 Not Found.

Why is a JavaScript array not enough to store a real shop's data?

Answer: The data is lost when the server restarts

Memory is wiped on restart, and each server copy has its own array. Real apps use a database.

Why use a nextId counter instead of products.length + 1 for new ids?

Answer: After a delete, length + 1 can repeat an id that was already used

If product 3 of 3 is deleted, length + 1 gives 3 again. A counter never goes back.

What does "stateless" mean for a REST API?Related

Answer: Each request carries everything needed, such as the token; the server does not remember earlier requests

Stateless means no memory of earlier requests, so every request includes its own authentication and data.

From REST APIs and JSON

Why put a request id in both the log and the error message?Related

Answer: So support can find the exact log line when a user reports a problem

The user quotes the reference, and engineers search the logs for it.

From Handling errors well

Why make handlers depend on a Store interface?Related

Answer: The storage can change and tests can use a fake without touching handlers

This is the "accept interfaces" idea applied to APIs.

From REST API design and JSON handlers

With a GET request, data usually goes in the…Related

Answer: URL

GET carries data in the URL (query string).

From How web requests work (and why that matters)

Pass the quiz (60% or more) or mark this topic as done when you are ready.

Your progress is saved on this device only.

Next steps

  1. 2 more topics in “APIs and request handling” before its exam: Validating input, Handling errors well.
  2. Exam: APIs and request handling · 13 questions · 30 min, without help. 5 topics of this module still to finish first.
  3. Then the next module, Node.js and Express. 54 topics left in the course before the final exam.

← Previous: Routing: sending each request to the right code