Coding 7(RESTful Route handlers) - Unlike page routes, route handlers allow us to create RESTful endpoints, giving us full control over the response. - We dont have to create and configure a separate server for that - For making external API requests - For securing private keys In `src/app/flashboard/route.js` ```js export async function GET() { return new Response("flash board api data"); } ``` when visited to page `localhost:3000/flashboard` then it will represent this response If there is page.jsx too like in `src/app/flashboard/page.js` then in this case page.jsx will take precedence over route.js and page.jsx content will be displayed. To avoid this make sure that page.jsx and route.jsx is never in same folder/route. So make sure to have different folder (say api) under flashboard folder and add route.jsx to that ```text src/app flashboard api route.jsx page.jsx ``` **GET Request** in `src/app/comments/data.js` ```js export const comments = [ { id: 1, text: "This is my first comment", }, { id: 2, text: "This is my second comment", }, { id: 3, text: "This is my third comment", }, ]; ``` in `src/app/comments/route.js` ```js import { comments } from "./data"; export async function GET() { return Response.json(comments); } ``` **POST Request** in `src/app/comments/route.js` ```js export async function POST(request) { const comment = await request.json(); const newcomment = { id: comments.length + 1, text: comment, }; comments.push(newcomment); return new Response(JSON.stringify(newcomment), { headers: { "Content-Type": "application/json", }, status: 201, }); } ``` Every POST route handler recieved a request in form of object **Dynamic Route Handler** - for dynamic routes like `localhost:3000/comments/:id` Structure ```text src/app comments [id] route.js route.js ``` in `src/app/comments/[id]/route.js` ```js import { comments } from "../data"; export async function GET(request, context) { const { params } = context; const comment = comments.find( (comment) => comment.id === parseInt(params.id) ); return Response.json(comments); } ``` Here we have other parameter which is a object that contains params **Handling PATCH request** in `src/app/comments/[id]/route.js` ```js export async function PATCH(request, { params }) { const body = await request.json(); const { text } = body; console.log("text: ", text); const index = comments.findIndex( (comment) => comment.id === parseInt(params.id) ); console.log("index : ", index); comments[index]["text"] = text; return Response.json(comments[index]); } ``` **Handling DELETE request** in `src/app/comments/[id]/route.js` ```js export async function DELETE(request, { params }) { const index = comments.findIndex( (comment) => comment.id === parseInt(params.id) ); const deletedContext = comments[index]; comments.splice(index, 1); return Response.json(deletedContext); } ``` **URL Query parameters** - To handle and parse query parameters like `localhost:3001/comments?s=first` we need to parameter in GET method. - The paramater is of type NextRequest and contains nextUrl and this contains searchParams field too. searchParams field contains get method through which we can get values of query parameters In `src/app/comments/route.js` ```js export async function GET(request) { const searchParams = request.nextUrl.searchParams; const query = searchParams.get("s"); // if query is not null then only filter else print all comments const filteredComments = query ? comments.filter((comment) => comment.text.includes(query)) : comments; return Response.json(filteredComments); } ``` **Redirects in URL** - Just like useRouter. useRouter is for client side and redirect is for server side. to navigate to `/comments` in client side ```js "use client"; import { useRouter } from "next/navigation"; const router = useRouter() router.push('/comments') ``` to navigate `/comments` in server side ```js import {redirect} from "next/navigation"; redirect('/comments'); ``` In `src/app/comments/[id]/route.js` ```js export async function GET(request, context) { const { params } = context; // if id is invalid then redirects if (parseInt(params.id) > comments.length) { redirect("/comments"); } const comment = comments.find( (comment) => comment.id === parseInt(params.id) ); return Response.json(comment); } ``` - When using this it sends status code as 307 which means for redirect **Headers in Route Handlers** - HTTP headers represent the metadata associated with an API request and response - Request Headers - Sent by client to server containing info about request so server process it accordingly - `User-Agent` indicates browser and OS - `Accept` : indicates content-type that client will understand and expects server to send it in 'Content-Type' in response headers - `Authorization` : fr authenticate itself to server. Eg : Bearer token - Reponse Headers - Sent by server to client containing info abour server and data sent in reponse - `Content-Type` : indicates media type of response. eg : 'application/json', 'text/plain', 'text/html'. - Headers Class can be used to create object after passing `req.headers` in its constructor - there is a method named `headers` which can be imported from 'next/headers' In `src/app/flashboard/api/route.js` ```js import { headers } from "next/headers"; export async function GET(request) { const reqHeaders = new Headers(request.headers); const headerList = headers(); console.log(reqHeaders.get("Authorization")); console.log(headerList.get("Authorization")); return new Response("