Building REST APIs

Back

Loading concept...

🍕 Building REST APIs: The Pizza Delivery Service

Imagine you run the world’s best pizza delivery service. Customers call you, tell you what they want, and you deliver delicious pizzas. REST APIs work exactly the same way – they’re how apps “order” and “deliver” data!


🎯 What You’ll Learn

  1. RESTful Design Principles – The golden rules of pizza ordering
  2. API Versioning – When your menu changes
  3. PUT vs PATCH – Replace the whole pizza vs. fix one topping
  4. Pagination & Sorting – Showing the menu 10 items at a time
  5. Filtering – “Show me only vegetarian pizzas”

1️⃣ RESTful Design Principles

🍕 The Pizza Analogy

Think of REST like a well-organized pizza shop:

Pizza Shop REST API
Menu items (pizzas) Resources (data)
Order counter Endpoints (URLs)
“I want to order” HTTP Methods
Your order slip Request
Pizza box Response

The 5 Golden Rules

Rule 1: Everything is a Resource

Resources are like items on your menu. Each has a unique name (URL).

/pizzas          → All pizzas
/pizzas/42       → Pizza #42 (Margherita)
/customers/7     → Customer #7 (You!)

Rule 2: Use Nouns, Not Verbs

✅ Good: GET /pizzas
❌ Bad:  GET /getPizzas

✅ Good: POST /orders
❌ Bad:  POST /createOrder

Rule 3: HTTP Methods = Actions

graph TD A["HTTP Methods"] --> B["GET = Read"] A --> C["POST = Create"] A --> D["PUT = Replace"] A --> E["PATCH = Update"] A --> F["DELETE = Remove"]
Action Method Example
See menu GET GET /pizzas
Order pizza POST POST /orders
Replace order PUT PUT /orders/1
Add topping PATCH PATCH /orders/1
Cancel order DELETE DELETE /orders/1

Rule 4: Stateless = No Memory

Every request must contain ALL the information needed. The server doesn’t remember you between requests.

❌ Server: "What pizza did you want again?"
✅ Client: "I want pizza #42, I'm customer #7,
   deliver to 123 Main St"

Rule 5: Use Proper Status Codes

200 OK         → "Here's your pizza! 🍕"
201 Created    → "Order placed! 📝"
400 Bad Request → "We don't have that topping 🤔"
404 Not Found   → "Pizza #999? Never heard of it 🔍"
500 Server Error → "Kitchen on fire! 🔥"

2️⃣ API Versioning

🍕 The Menu Update Problem

Imagine your pizza shop changes its menu:

  • Old Menu: Small = 8", Medium = 10"
  • New Menu: Small = 10", Medium = 12"

Old customers expecting an 8" pizza would be confused!

Versioning = Keeping old menus available while introducing new ones.

Three Ways to Version

Way 1: URL Path (Most Popular! ⭐)

/v1/pizzas    → Old menu
/v2/pizzas    → New menu
@RestController
@RequestMapping("/v1/pizzas")
public class PizzaControllerV1 { }

@RestController
@RequestMapping("/v2/pizzas")
public class PizzaControllerV2 { }

Way 2: Query Parameter

/pizzas?version=1    → Old menu
/pizzas?version=2    → New menu

Way 3: Header

GET /pizzas
Header: API-Version: 2

🎯 Best Practice

graph TD A["New API?"] --> B{Breaking changes?} B -->|Yes| C["New version v2"] B -->|No| D["Keep current version"] C --> E["Keep v1 running"] E --> F["Sunset v1 after 6 months"]

3️⃣ PUT vs PATCH: The Big Difference

🍕 Pizza Topping Story

You ordered a pizza with:

  • Cheese ✓
  • Tomatoes ✓
  • Mushrooms ✓

But you want to add pepperoni

PUT = “Replace the ENTIRE pizza”

PUT /orders/1

{
  "cheese": true,
  "tomatoes": true,
  "mushrooms": true,
  "pepperoni": true
}

You must send EVERYTHING, even things that didn’t change!

PATCH = “Just change what’s different”

PATCH /orders/1

{
  "pepperoni": true
}

Only send what you’re changing!

When to Use Each

graph TD A["Need to update?"] --> B{Changing everything?} B -->|Yes, all fields| C["Use PUT"] B -->|No, just some| D["Use PATCH"] C --> E["Send complete object"] D --> F["Send only changes"]
Scenario Use
Update user profile completely PUT
Change just the email PATCH
Replace entire document PUT
Toggle a setting on/off PATCH

Code Example

// PUT - Replace entire pizza
@PutMapping("/pizzas/{id}")
public Pizza replacePizza(
    @PathVariable Long id,
    @RequestBody Pizza newPizza) {
    return pizzaService.replace(id, newPizza);
}

// PATCH - Update specific fields
@PatchMapping("/pizzas/{id}")
public Pizza updatePizza(
    @PathVariable Long id,
    @RequestBody Map<String, Object> updates) {
    return pizzaService.patch(id, updates);
}

4️⃣ Pagination and Sorting

🍕 The 1000 Pizza Problem

Your shop has 1000 pizzas. Would you show ALL of them at once?

NO! That’s like printing a 100-page menu. 😵

Pagination = Showing items in small groups (pages).

How Pagination Works

GET /pizzas?page=1&size=10

Returns pizzas 1-10

GET /pizzas?page=2&size=10

Returns pizzas 11-20

graph LR A["1000 Pizzas"] --> B["Page 1: 1-10"] A --> C["Page 2: 11-20"] A --> D["Page 3: 21-30"] A --> E["... 97 more pages"]

Pagination Response

{
  "content": [
    {"id": 1, "name": "Margherita"},
    {"id": 2, "name": "Pepperoni"}
  ],
  "page": 1,
  "size": 10,
  "totalElements": 1000,
  "totalPages": 100,
  "hasNext": true,
  "hasPrevious": false
}

Adding Sorting

GET /pizzas?sort=price,asc

→ Cheapest first 💰

GET /pizzas?sort=name,desc

→ Z to A alphabetically

Spring Boot Code

@GetMapping("/pizzas")
public Page<Pizza> getPizzas(
    @RequestParam(defaultValue = "0") int page,
    @RequestParam(defaultValue = "10") int size,
    @RequestParam(defaultValue = "id") String sortBy,
    @RequestParam(defaultValue = "asc") String order) {

    Sort sort = order.equals("asc")
        ? Sort.by(sortBy).ascending()
        : Sort.by(sortBy).descending();

    Pageable pageable = PageRequest.of(
        page, size, sort);

    return pizzaRepository.findAll(pageable);
}

5️⃣ Filtering

🍕 “I Only Want Veggie Pizzas!”

Filtering = Asking for specific items only.

GET /pizzas?vegetarian=true

→ Only veggie pizzas 🥬

GET /pizzas?price_max=15

→ Pizzas under $15 💵

GET /pizzas?vegetarian=true&price_max=15

→ Cheap veggie pizzas! 🥬💵

Common Filter Patterns

Pattern Example Meaning
Exact match ?status=available Only available
Range ?price_min=5&price_max=20 $5-$20
Contains ?name_like=cheese Has “cheese”
Multiple values ?size=small,medium Small OR medium

Spring Boot Filtering

@GetMapping("/pizzas")
public List<Pizza> getPizzas(
    @RequestParam(required = false)
        Boolean vegetarian,
    @RequestParam(required = false)
        Double priceMax,
    @RequestParam(required = false)
        String size) {

    Specification<Pizza> spec =
        Specification.where(null);

    if (vegetarian != null) {
        spec = spec.and(
            (root, q, cb) ->
            cb.equal(root.get("vegetarian"),
                     vegetarian));
    }

    if (priceMax != null) {
        spec = spec.and(
            (root, q, cb) ->
            cb.lessThanOrEqualTo(
                root.get("price"), priceMax));
    }

    return pizzaRepository.findAll(spec);
}

Combining Everything!

GET /v2/pizzas
    ?vegetarian=true
    &price_max=20
    &page=1
    &size=10
    &sort=price,asc

Translation: “From version 2 of the API, show me the first 10 vegetarian pizzas under $20, sorted by price from cheapest to most expensive.”


🎉 Congratulations!

You now understand REST APIs like a pizza delivery pro!

graph LR A["REST API Master"] --> B["RESTful Principles"] A --> C["Versioning"] A --> D["PUT vs PATCH"] A --> E["Pagination &amp; Sorting"] A --> F["Filtering"] B --> G["Resources + Methods + Status Codes"] C --> H["v1, v2 in URLs"] D --> I["Replace vs Update"] E --> J["page + size + sort"] F --> K["Query parameters"]

Quick Reference

Concept Remember
REST Resources Nouns in URLs (/pizzas)
HTTP Methods GET, POST, PUT, PATCH, DELETE
Versioning /v1/, /v2/ in URL path
PUT Replace EVERYTHING
PATCH Update SOME things
Pagination ?page=1&size=10
Sorting ?sort=price,asc
Filtering ?vegetarian=true

🍕 “REST APIs are just polite conversations between apps. Be clear about what you want, and you’ll always get the right pizza!”

Loading story...

Story - Premium Content

Please sign in to view this story and start learning.

Upgrade to Premium to unlock full access to all stories.

Stay Tuned!

Story is coming soon.

Story Preview

Story - Premium Content

Please sign in to view this concept and start learning.

Upgrade to Premium to unlock full access to all content.