Next.js API Routes POST, PUT, DELETE Sinhala Tutorial | Nextjs REST API

Next.js API Routes POST, PUT, DELETE Sinhala Tutorial | Nextjs REST API

Next.js API Routes: Handling POST, PUT, DELETE Sinhala Guide

හායි යාළුවනේ, කොහොමද? 😃 අද අපි කතා කරන්න යන්නේ Web Development ලෝකයේ ගොඩක් වැදගත් මාතෘකාවක් ගැන. ඒ තමයි Next.js API Routes හරහා POST, PUT, DELETE වගේ HTTP requests හසුරුවන හැටි. Next.js කියන්නේ React Application හදන්න තියෙන සුපිරි Framework එකක් කියලා ඔයාලා දන්නවානේ. මේකේ තියෙන API Routes කියන Feature එක නිසා අපිට පුළුවන් Front-end එකයි Back-end එකයි එකම Project එකක් ඇතුළේ හදාගන්න. ඒක ගොඩක් පහසුයි!

සාමාන්‍යයෙන් Front-end එකට විතරක් සීමා වෙනවා නම් Next.js හොදයි. හැබැයි අපි ගොඩක් වෙලාවට Data Save කරන්න, Update කරන්න, Delete කරන්න වගේ දේවල් වලට Back-end එකක් හදන්න වෙනවා. එතකොට Next.js API Routes කියන්නේ හරිම කදිම විසඳුමක්. මේකෙන් අපිට පුළුවන් Express.js වගේ Framework එකක් නැතුවම Server-side Logic ලියන්න.

මේ ලිපියෙන් ඔයාට මොනවද ඉගෙනගන්න පුළුවන්?

  • Next.js API Routes කියන්නේ මොනවද?
  • ඒවා ඇතුළේ HTTP Methods (POST, PUT, DELETE) හසුරුවන හැටි.
  • දත්ත එකතු කරන්න, Update කරන්න, Delete කරන්න Practical Examples.
  • API Routes හදනකොට මතක තියාගන්න ඕන Good Practices.
  • පොදු ගැටළු හඳුනාගෙන ඒවාට විසඳුම්.

හරි එහෙනම්, අපි පටන් ගමු! 🚀

Next.js API Routes: පොඩි හැඳින්වීමක්

Next.js වල API Routes කියන්නේ Client-side JavaScript එකෙන් Server-side Code execute කරන්න පුළුවන් ක්‍රමයක්. හරියට Node.js API Endpoint එකක් වගේ. මේවා හදන්නෙ pages/api ෆෝල්ඩර් එක ඇතුළේ (Next.js 13+ වල නම් app/api ෆෝල්ඩර් එකත් තියෙනවා, හැබැයි මේ ටියුටෝරියට අපි pages/api පාවිච්චි කරමු). මේ ෆෝල්ඩර් එක ඇතුළේ ඔයා හදන ඕනම JavaScript file එකක් (.js, .ts, .tsx) API Endpoint එකක් වෙනවා.

උදාහරණයක් විදියට, pages/api/hello.js කියලා file එකක් හැදුවොත්, ඒක /api/hello කියන URL එකෙන් Access කරන්න පුළුවන් වෙනවා. මේ API Routes වලට එන හැම Request එකක්ම Next.js මඟින් req (Request) object එකයි, res (Response) object එකයි එක්ක Function එකකට යොමු කරනවා. මේක හරියට Node.js/Express.js වල වගේමයි.

මෙන්න පොඩි උදාහරණයක්:

// pages/api/hello.js

export default function handler(req, res) {
  res.status(200).json({ name: 'Next.js API' });
}

මේ Code එකෙන් වෙන්නේ /api/hello කියන URL එකට Request එකක් ආවම { name: 'Next.js API' } කියන JSON Object එක Response කරන එක.

POST Requests: දත්ත Save කරමු (Create Operation)

අපි හිතමු අපිට 'todo' list එකක් හදන්න ඕන කියලා. ඒකට අලුතින් 'todo' item එකක් එකතු කරන්න අපිට POST Request එකක් ඕන වෙනවා. POST කියන HTTP Method එක පාවිච්චි කරන්නේ අලුත් Resource එකක් Create කරන්න නැත්නම් Server එකට Data යවන්න.

මුලින්ම අපි අපේ todo items ටිකක් In-memory Array එකක තියාගමු. (හැබැයි මතක තියාගන්න, Real Application එකකදී මේ දත්ත Database එකක තමයි තියෙන්නේ. මේක Simple Example එකක් නිසා අපි Array එකක් පාවිච්චි කරනවා.)

pages/api/todos.js කියලා file එකක් හදමු.

// pages/api/todos.js

let todos = [
  { id: 1, text: 'Next.js API Routes ඉගෙනගන්න', completed: false },
  { id: 2, text: 'රෑට කන්න මොනවද බලන්න', completed: false },
];

export default function handler(req, res) {
  if (req.method === 'GET') {
    // Get all todos
    res.status(200).json(todos);
  } else if (req.method === 'POST') {
    // Create a new todo
    const { text } = req.body; // Client side එකෙන් එවන data request body එකේ තියෙනවා

    if (!text) {
      return res.status(400).json({ message: 'Todo text is required.' });
    }

    const newTodo = {
      id: todos.length > 0 ? Math.max(...todos.map(t => t.id)) + 1 : 1,
      text,
      completed: false,
    };
    todos.push(newTodo);
    res.status(201).json(newTodo); // 201 Created status code එක යවනවා
  } else {
    // Other methods not allowed
    res.status(405).json({ message: 'Method Not Allowed' });
  }
}

Code එක පැහැදිලි කිරීම:

  • if (req.method === 'POST'): මේකෙන් අපි බලනවා ආපු Request එක POST ද කියලා.
  • const { text } = req.body;: POST Request එකකදී Client එකෙන් යවන Data තියෙන්නේ req.body object එක ඇතුළේ. මෙතනදී අපි text කියන Property එක Destructure කරලා ගන්නවා.
  • if (!text) { ... }: මෙතනදී අපි පොඩි Validation එකක් කරනවා. text එක නැත්නම් 400 Bad Request status එකක් එක්ක Error Message එකක් යවනවා. මේක ගොඩක් වැදගත් Best Practice එකක්.
  • const newTodo = { ... };: අලුත් Todo Object එකක් හදනවා. id එක Unique වෙන්න අපි පොඩි Logic එකක් පාවිච්චි කරනවා.
  • todos.push(newTodo);: අලුත් Todo එක Array එකට එකතු කරනවා.
  • res.status(201).json(newTodo);: Request එක සාර්ථකව සිදු වුණාම 201 Created කියන HTTP Status Code එක යවනවා. ඒ කියන්නේ අලුත් Resource එකක් සාර්ථකව Create කළා කියලා. ඒ වගේම අලුතින් හදපු Todo Object එක Response එක විදියට යවනවා.

Test කරමු:

මේ POST Endpoint එක Test කරන්න Postman, Insomnia වගේ Tools පාවිච්චි කරන්න පුළුවන්. නැත්නම් curl පාවිච්චි කරන්නත් පුළුවන්.

Terminal එකේදී:

curl -X POST -H "Content-Type: application/json" \n     -d '{"text": "නෙට්ෆ්ලික්ස් එකේ අලුත් කතාව බලන්න"}' \n     http://localhost:3000/api/todos

මේක Run කළාම ඔයාට මේ වගේ Response එකක් එන්න ඕන:

{
  "id": 3,
  "text": "නෙට්ෆ්ලික්ස් එකේ අලුත් කතාව බලන්න",
  "completed": false
}

දැන් http://localhost:3000/api/todos වලට Browser එකෙන් GET Request එකක් යවලා බලන්න. අලුත් Todo එක එකතු වෙලාද කියලා.

PUT Requests: දත්ත Update කරමු (Update Operation)

දැන් අපි බලමු කොහොමද දැනට තියෙන Todo item එකක් Update කරන්නේ කියලා. ඒකට අපි PUT Request එකක් පාවිච්චි කරනවා. PUT කියන HTTP Method එක පාවිච්චි කරන්නේ දැනට තියෙන Resource එකක් සම්පූර්ණයෙන්ම Replace කරන්න නැත්නම් Update කරන්න.

අපි Update කරන්න ඕන Todo එක Identify කරගන්න id එකක් ඕන වෙනවා. ඒක අපිට Query Parameter එකක් විදියට ගන්න පුළුවන්. ඒ වගේම Update කරන්න ඕන Data එක req.body එකෙන් ගන්නවා.

අපි pages/api/todos.js file එකම Update කරමු:

// pages/api/todos.js (Updated)

let todos = [
  { id: 1, text: 'Next.js API Routes ඉගෙනගන්න', completed: false },
  { id: 2, text: 'රෑට කන්න මොනවද බලන්න', completed: false },
];

export default function handler(req, res) {
  if (req.method === 'GET') {
    // Get all todos
    res.status(200).json(todos);
  } else if (req.method === 'POST') {
    // Create a new todo
    const { text } = req.body;

    if (!text) {
      return res.status(400).json({ message: 'Todo text is required.' });
    }

    const newTodo = {
      id: todos.length > 0 ? Math.max(...todos.map(t => t.id)) + 1 : 1,
      text,
      completed: false,
    };
    todos.push(newTodo);
    res.status(201).json(newTodo);
  } else if (req.method === 'PUT') {
    // Update an existing todo
    const { id } = req.query; // Query parameter එකෙන් ID එක ගන්නවා
    const { text, completed } = req.body; // Update කරන්න ඕන data body එකෙන් ගන්නවා

    if (!id || (!text && typeof completed === 'undefined')) {
      return res.status(400).json({ message: 'ID and update data are required.' });
    }

    const todoId = parseInt(id);
    const todoIndex = todos.findIndex(t => t.id === todoId);

    if (todoIndex === -1) {
      return res.status(404).json({ message: 'Todo not found.' });
    }

    // Update the todo item
    if (text) {
      todos[todoIndex].text = text;
    }
    if (typeof completed !== 'undefined') {
      todos[todoIndex].completed = completed;
    }

    res.status(200).json(todos[todoIndex]); // Updated todo එක Response කරනවා
  } else {
    // Other methods not allowed
    res.status(405).json({ message: 'Method Not Allowed' });
  }
}

Code එක පැහැදිලි කිරීම:

  • else if (req.method === 'PUT'): මෙතනින් අපි PUT Request එක හසුරුවනවා.
  • const { id } = req.query;: PUT Request එකකදී අපි URL එකට ?id=1 වගේ Query Parameter එකක් විදියට id එක යවනවා. ඒක req.query object එකෙන් අපිට ගන්න පුළුවන්.
  • const { text, completed } = req.body;: Update කරන්න ඕන Data (text, completed status) req.body එකෙන් ගන්නවා.
  • if (!id || (!text && typeof completed === 'undefined')) { ... }: ID එක සහ Update කරන්න Data තියෙනවද කියලා Validation කරනවා.
  • const todoId = parseInt(id);: Query parameter එකෙන් එන id එක String එකක් නිසා parseInt කරලා Number එකක් බවට පත් කරනවා.
  • const todoIndex = todos.findIndex(t => t.id === todoId);: Update කරන්න ඕන Todo එක Array එකේ කොහෙද තියෙන්නේ කියලා හොයාගන්නවා.
  • if (todoIndex === -1) { ... }: අදාල ID එකට Todo එකක් නැත්නම් 404 Not Found Status Code එකක් යවනවා.
  • if (text) { ... } සහ if (typeof completed !== 'undefined') { ... }: මේකෙන් බලනවා Client එකෙන් text එකක් හෝ completed status එකක් එව්වද කියලා. එව්වා නම් ඒ අදාල දේවල් විතරක් Update කරනවා. (මේක Partial Update එකක් වගේ. සම්පූර්ණ Replace එකක් නම් අපි req.body එකෙන් එන දේම Assign කරන්න පුළුවන්.)
  • res.status(200).json(todos[todoIndex]);: Update කළාට පස්සේ 200 OK Status Code එකක් එක්ක Update කරපු Todo Object එක Response කරනවා.

Test කරමු:

curl -X PUT -H "Content-Type: application/json" \n     -d '{"completed": true}' \n     "http://localhost:3000/api/todos?id=1"

මේකෙන් වෙන්නේ ID 1 තියෙන Todo එකේ completed status එක true කරන එක. Response එක මේ වගේ එන්න ඕන:

{
  "id": 1,
  "text": "Next.js API Routes ඉගෙනගන්න",
  "completed": true
}

ඔයාට text එකත් Update කරන්න පුළුවන්:

curl -X PUT -H "Content-Type: application/json" \n     -d '{"text": "Next.js API Routes ඉගෙනගෙන ඉවරයි!"}' \n     "http://localhost:3000/api/todos?id=1"

DELETE Requests: දත්ත මකමු (Delete Operation)

දැන් අපි බලමු කොහොමද Todo item එකක් Delete කරන්නේ කියලා. ඒකට අපි DELETE Request එකක් පාවිච්චි කරනවා. DELETE කියන HTTP Method එක පාවිච්චි කරන්නේ දැනට තියෙන Resource එකක් Server එකෙන් අයින් කරන්න.

අපි Delete කරන්න ඕන Todo එක Identify කරගන්න id එක Query Parameter එකක් විදියට ගන්නවා. (මේක Path Parameter එකක් විදියටත් ගන්න පුළුවන්, pages/api/todos/[id].js වගේ file එකක් හැදුවොත්. හැබැයි මේ ටියුටෝරියට අපි Query Parameter එකම පාවිච්චි කරමු.)

අපි pages/api/todos.js file එකටම Delete Logic එකත් එකතු කරමු:

// pages/api/todos.js (Final Update)

let todos = [
  { id: 1, text: 'Next.js API Routes ඉගෙනගන්න', completed: false },
  { id: 2, text: 'රෑට කන්න මොනවද බලන්න', completed: false },
];

export default function handler(req, res) {
  if (req.method === 'GET') {
    res.status(200).json(todos);
  } else if (req.method === 'POST') {
    const { text } = req.body;

    if (!text) {
      return res.status(400).json({ message: 'Todo text is required.' });
    }

    const newTodo = {
      id: todos.length > 0 ? Math.max(...todos.map(t => t.id)) + 1 : 1,
      text,
      completed: false,
    };
    todos.push(newTodo);
    res.status(201).json(newTodo);
  } else if (req.method === 'PUT') {
    const { id } = req.query;
    const { text, completed } = req.body;

    if (!id || (!text && typeof completed === 'undefined')) {
      return res.status(400).json({ message: 'ID and update data are required.' });
    }

    const todoId = parseInt(id);
    const todoIndex = todos.findIndex(t => t.id === todoId);

    if (todoIndex === -1) {
      return res.status(404).json({ message: 'Todo not found.' });
    }

    if (text) {
      todos[todoIndex].text = text;
    }
    if (typeof completed !== 'undefined') {
      todos[todoIndex].completed = completed;
    }

    res.status(200).json(todos[todoIndex]);
  } else if (req.method === 'DELETE') {
    // Delete a todo
    const { id } = req.query; // ID එක Query parameter එකෙන් ගන්නවා

    if (!id) {
      return res.status(400).json({ message: 'Todo ID is required.' });
    }

    const todoId = parseInt(id);
    const initialLength = todos.length;
    todos = todos.filter(t => t.id !== todoId); // අදාල ID එක තියෙන Todo එක අයින් කරනවා

    if (todos.length === initialLength) {
      // Check if any todo was actually removed
      return res.status(404).json({ message: 'Todo not found.' });
    }

    res.status(204).end(); // 204 No Content status code එක යවනවා, මොකුත් data response කරන්නේ නැහැ
  } else {
    // Other methods not allowed
    res.status(405).json({ message: 'Method Not Allowed' });
  }
}

Code එක පැහැදිලි කිරීම:

  • else if (req.method === 'DELETE'): මෙතනින් අපි DELETE Request එක හසුරුවනවා.
  • const { id } = req.query;: Delete කරන්න ඕන Todo එකේ id එක Query parameter එකෙන් ගන්නවා.
  • if (!id) { ... }: ID එක නැත්නම් Error එකක් යවනවා.
  • todos = todos.filter(t => t.id !== todoId);: Array එකේ filter Method එක පාවිච්චි කරලා අදාල ID එක තියෙන Todo එක අයින් කරනවා.
  • if (todos.length === initialLength) { ... }: මේකෙන් අපි බලනවා ඇත්තටම Todo එකක් Delete වුණාද කියලා. නැත්නම් 404 Not Found Status එකක් යවනවා.
  • res.status(204).end();: සාර්ථකව Delete කළාට පස්සේ 204 No Content කියන HTTP Status Code එක යවනවා. මේකෙන් කියවෙන්නේ Request එක සාර්ථකයි, හැබැයි Response Body එකේ මොකුත් Data නැහැ කියන එකයි. .end() Method එකෙන් Response එක ඉවර කරනවා.

Test කරමු:

curl -X DELETE "http://localhost:3000/api/todos?id=1"

මේකෙන් වෙන්නේ ID 1 තියෙන Todo එක Delete කරන එක. සාර්ථක නම් ඔයාට කිසිම Response Body එකක් නැතුව 204 No Content Status එකක් එනවා.

දැන් http://localhost:3000/api/todos වලට GET Request එකක් යවලා බලන්න. ID 1 තියෙන Todo එක නැද්ද කියලා.

හොඳ පුරුදු සහ පොදු ගැටළු (Best Practices & Common Issues)

1. Error Handling

API එකක් හදනකොට Error Handling කියන්නේ අනිවාර්යයෙන්ම කරන්න ඕන දෙයක්. අපේ Example වලදී අපි 400 Bad Request, 404 Not Found වගේ Status Codes පාවිච්චි කළා. මේ වගේ Status Codes පාවිච්චි කරන එකෙන් Client එකට (Front-end එකට) Request එකේ තත්ත්වය ගැන හොඳ අවබෝධයක් ලැබෙනවා. නොදන්නා Errors වලට 500 Internal Server Error එකක් යවන්න පුළුවන්. ඒ වගේම try...catch Block පාවිච්චි කරලා Code එක ඇතුළේ ඇතිවෙන Unexpected Errors අල්ලගන්න එකත් ගොඩක් වැදගත්.

// Example for better error handling
export default function handler(req, res) {
  try {
    if (req.method === 'POST') {
      const { text } = req.body;
      if (!text) {
        return res.status(400).json({ message: 'Todo text is required.' });
      }
      // ... rest of your POST logic
    } else if (req.method === 'GET') {
      // ... GET logic
    } else {
      res.status(405).json({ message: 'Method Not Allowed' });
    }
  } catch (error) {
    console.error('API Error:', error); // Development වලදී මේකෙන් error එක බලාගන්න පුළුවන්
    res.status(500).json({ message: 'Internal Server Error' });
  }
}

2. Input Validation

Client එකෙන් එවන හැම Data එකක්ම Validate කරන්න ඕන. අපි POST Request එකේදී text එක තියෙනවද කියලා බැලුවා වගේ. Complex Data Structures වලදී Zod, Yup වගේ Validation Libraries පාවිච්චි කරන්න පුළුවන්. මේකෙන් අපේ API එක Robust වෙනවා වගේම Security එකත් වැඩි වෙනවා.

3. Data Persistence

අපේ Example එකේදී අපි Data තියාගත්තේ In-memory Array එකක. ඒ කියන්නේ Server එක Restart කළොත් Data ටික නැති වෙනවා. Real Application එකකදී MongoDB, PostgreSQL, MySQL වගේ Database එකක් පාවිච්චි කරන්න ඕන. Next.js API Routes වලට ඕනම Database එකක් එක්ක Integrate කරන්න පුළුවන්.

4. Debugging

API Routes Debug කරන්න console.log() කියන්නේ හොඳම යාළුවෙක්. Request Body එකේ මොනවද තියෙන්නේ, Query Parameters මොනවද, Error එක මොකක්ද වගේ දේවල් බලාගන්න console.log() පාවිච්චි කරන්න. Project එක Development Mode එකේ තියෙනකොට Terminal එකේ ඒ Output බලාගන්න පුළුවන්.

// Debugging example
export default function handler(req, res) {
  console.log('Incoming Request Method:', req.method);
  console.log('Request Body:', req.body);
  console.log('Request Query:', req.query);

  // ... rest of your API logic
}

5. Single API Route File vs. Multiple Files

අපේ Example එකේදී අපි හැම HTTP Method එකක්ම (GET, POST, PUT, DELETE) එකම pages/api/todos.js file එකක් ඇතුළේ handle කළා. ඒක සාමාන්‍යයෙන් පොඩි API Routes වලට හොදයි. හැබැයි API එක Complex වෙනකොට pages/api/todos/[id].js වගේ Dynamic API Routes හදලා, GET, PUT, DELETE Requests අදාල ID එක එක්ක තව File එකක හසුරුවන්න පුළුවන්. ඒකෙන් Code එක තවත් Organize වෙනවා.

නිගමනය (Conclusion)

හරි එහෙනම් යාළුවනේ, අපි Next.js API Routes පාවිච්චි කරලා POST, PUT, DELETE Requests හසුරුවන හැටි සම්පූර්ණයෙන්ම ඉගෙනගත්තා. දැන් ඔයාට පුළුවන් Basic CRUD Operations කරන්න පුළුවන් Simple API Endpoints හදාගන්න. Next.js මේ API Routes Feature එක දුන්න නිසා Full-stack Application හදන එක ගොඩක් පහසු වෙලා තියෙනවා.

මේ ටියුටෝරියෙන් අපි In-memory Array එකක් පාවිච්චි කළත්, Real World Scenario වලදී Database එකක් එක්ක වැඩ කරන්න වෙනවා. ඒක මේ Concepts වලට වඩා වෙනස් වෙන්නේ නැහැ. ඔයාට Database Library එකක් (Mongoose, Prisma, TypeORM වගේ) පාවිච්චි කරලා මේ Logic එකටම Database Interactivity එකතු කරන්න පුළුවන්.

මතක තියාගන්න, හොඳ API එකක් කියන්නේ හොඳට Design කරපු, Error Handling තියෙන, Security Features එක්ක හදපු එකක්. මේ Concepts හොඳටම තේරුම් ගන්න මේ Code එක ඔයාගේම Project එකක Try කරලා බලන්න. ඒ වගේම විවිධ Use Cases වලට 맞춰 වෙනස්කම් කරලා බලන්න.

මේ ගැන ඔයාගේ අත්දැකීම් මොනවද? ඔයාට මොනවා හරි ප්‍රශ්න තියෙනවා නම්, නැත්නම් මේ Tutorial එකට අලුතින් මොනවා හරි එකතු කරන්න ඕන නම්, පහලින් Comment එකක් දාලා යන්න! 💬

ඉදිරියේදී මේ වගේම තවත් වැදගත් ලිපි වලින් හමුවෙමු! Happy Coding! 😊