Full Stack Development

REST APIs



by Tomas Trescak t.trescak@westernsydney.edu.au

Next.js

/

What's REST API?

  • What’s a REST API?
  • REST Powers everyday apps
  • It's everywhere you look
  • REST APIs are not just URLs!

REST

/

API Basics

  • Stateless : No memory between requests
  • Uniform : Standard HTTP methods
  • Resources : Everything’s a URL
  • Type Unsafe ;(

REST

/

Building APIs in Next.js

    import { NextRequest, NextResponse } from "next/server";

interface Post {
  id: number;
  title: string;
  tag: string;
  content?: string;
}

let posts: Post[] = [{ id: 1, title: "Learn REST", tag: "coding", content: "Fun!" }];

export async function GET(request: NextRequest) {
  const { searchParams } = new URL(request.url);
  const tag = searchParams.get("tag");
  const filtered = tag ? posts.filter(p => p.tag === tag) : posts;
  return NextResponse.json(filtered);
}

export async function POST(request: NextRequest) {
  const newPost: Post = await request.json();
  const postWithId = { ...newPost, id: posts.length + 1 };
  posts.push(postWithId);
  return NextResponse.json({ id: postWithId.id, message: "Post added" }, { status: 201 });
}
  
/app/api/posts/route.ts

REST

/

Fetching data from APIs

    interface Post {
  id: number;
  title: string;
  tag: string;
  content?: string;
}

async function fetchPostsByTag(tag: string): Promise<Post[]> {
  const response = await fetch(`http://localhost:3000/api/posts?tag=${tag}`);
  if (!response.ok) throw new Error("Fetch failed");
  const posts: Post[] = await response.json();
  return posts;
}

// [{ id: 1, title: "Learn REST", tag: "coding", content: "Fun!" }]
fetchPostsByTag("coding")
  .then(posts => console.log(posts)) 
  .catch(err => console.error(err));
  

REST

/

POSTing data to API

    async function createPost(newPost: Omit<Post, "id">): Promise<{ 
  id: number; message: string 
}> {
  const response = await fetch("http://localhost:3000/api/posts", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify(newPost),
  });
  if (!response.ok) throw new Error("Create failed");
  return response.json();
}

const post = { title: "My API Journey", tag: "coding", content: "Wow!" };
createPost(post)
  .then(result => console.log(result)) // { id: 2, message: "Post added" }
  .catch(err => console.error(err));
  

Next.js

/

APIs

    // Update (PUT)
async function updatePost(id: number, updatedPost: Post): 
  Promise<{ message: string }> {
  const response = await fetch(`http://localhost:3000/api/posts/${id}`, {
    method: "PUT",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify(updatedPost),
  });
  if (!response.ok) throw new Error("Update failed");
  return response.json();
}

const updated = { 
  id: 1, 
  title: "REST Rocks", 
  tag: "coding", 
  content: "Updated!" 
};
updatePost(1, updated).then(result => console.log(result));

// Patch (PATCH)
async function updatePost(id: number, updatedPost: Partial<Post>): 
  Promise<{ message: string }> {
  const response = await fetch(`http://localhost:3000/api/posts/${id}`, {
    method: "PUT",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify(updatedPost),
  });
  if (!response.ok) throw new Error("Update failed");
  return response.json();
}

const updated = { 
  id: 1, 
  title: "REST Rocks"
};
updatePost(1, updated).then(result => console.log(result));

// Delete (DELETE)
async function deletePost(id: number): Promise<{ message: string }> {
  const response = await fetch(`http://localhost:3000/api/posts/${id}`, {
    method: "DELETE",
  });
  if (!response.ok) throw new Error("Delete failed");
  return response.json();
}

deletePost(1).then(result => console.log(result));
  

REST

/

Best Practices

  • Clear URLs: /api/posts , not /api/getPosts
  • Status Codes: 201 for POST success
  • Handle Errors: Check response.ok
  • Pros - Scales
  • Cons - Overfetching