# Handling HTTP request in Nextjs

We are using the Approuter to handle HTTP requests. Define your routes in the api folder and follow the guidelines below.

Structure of the NextRequest request object:

1. **request.method**: The HTTP method of the request (e.g., "GET", "POST", "PUT", etc.).
    
2. **request.url**: The full URL of the request as a string.
    
3. **request.nextUrl**: A parsed URL object (instance of URL) specific to Next.js, providing easy access to URL components.
    
    * **Properties**:
        
        * nextUrl.pathname: The path portion of the URL (e.g., /api/protected/users).
            
        * nextUrl.searchParams: A URLSearchParams object for query parameters (e.g., id=123).
            
        * nextUrl.href: The full URL.
            
        * nextUrl.origin: The origin e.g [http://localhost:3000](http://localhost:3000)
            
        * [nextUrl.search](http://nextUrl.search): The query string (e.g., ?id=123).
            
4. **request.headers**: A Headers object containing all HTTP headers sent with the request.
    
    * Example: request.headers.get("authorization") retrieves the Authorization header to check for a Bearer token.
        
5. **request.body**: A ReadableStream containing the raw request body (for POST, PUT, etc.).
    
    * **Important**: Reading the body consumes the stream, so you must clone the request (request.clone()) if you want to preserve it for the Route Handler.
        
        `const clonedRequest = request.clone();`
        
    * `const body = await clonedRequest.json();`
        
6. **request.cookies**: A RequestCookies object to access cookies sent with the request.
    
    * Example: request.cookies.get("session") retrieves a cookie named session.
        
7. **request.geo**: Geolocation data about the client (if available, depends on hosting environment like Vercel).
    
    * Example: { country: "US", city: "New York" }.
        
8. **request.ip**: The client’s IP address (if available).
    

## GET requests

1. ### Basic request
    
    For route define in api folder e.g /api/users
    

```javascript
export async function GET(request) {
  return Response.json({ message: "List of users" }, { status: 200 });
}
```

1. ### Parameters in request
    
    For dynamic routes e.g /api/users/\[id\]
    

```javascript
// app/api/users/[id]/route.js
export async function GET(request, { params }) {
  const { id } = params; // Extract the 'id' from the URL
  return Response.json({ userId: id }, { status: 200 });
}
```

1. ### Query in request
    
    For handling requests with queries in them e.g localhost:3000/api/users/name=”John”&age=20
    

```javascript
export async function GET(request) {
  const { searchParams } = new URL(request.url);
  const name = searchParams.get("name");
  const age = searchParams.get("age");
  return Response.json({ name, age }, { status: 200 });
}
```

## POST requests

1. ### Basic request
    

```javascript
export async function POST(request) {
  try {
    const body = await request.json()
    const { name, email } = body

    // Logic
    
    return Response.json({ message: "User created", user: newUser }, { status: 201 });
  } catch (error) {
    return Response.json({ error: "Invalid JSON" }, { status: 400 });
  }
}
```

2. ### Parameters in request
    

```javascript
export async function POST(request, { params }) {
  try {
    const { id } = params; 
    const body = await request.json(); 
    const { name, email } = body;
    
    //
   
    return Response.json({ message: "User updated", user: updatedUser }, { status: 200 });
  } catch (error) {
    return Response.json({ error: "Invalid JSON" }, { status: 400 });
  }
}
```

3. ### Query in request
    

```javascript
export async function POST(request) {
  try {
    const { searchParams } = new URL(request.url);
    const role = searchParams.get("role") || "user"; // Default to 'user'
    const body = await request.json();
    const { name, email } = body;

    //

    return Response.json({ message: "User created", user: newUser }, { status: 201 });
  } catch (error) {
    return Response.json({ error: "Invalid JSON" }, { status: 400 });
  }
}
```

4. ### Formdata
    

```javascript
export async function POST(request) {
  try {
    const formData = await request.formData();
    const name = formData.get("name");
    const email = formData.get("email");

   //

    return Response.json({ message: "User created", user: newUser }, { status: 201 });
  } catch (error) {
    return Response.json({ error: "Invalid form data" }, { status: 400 });
  }
}
```

## Middlewares

Example of middleware to check whether a token has been provided in the authorisation header. Create a middlware.js file in the app directory

```javascript
import { NextResponse } from "next/server";

const VALID_TOKEN = "my-secret-token";

export function middleware(request) {
  const { method, nextUrl } = request;
  const { pathname, searchParams } = nextUrl;

  // Extract Authorization header
  const authHeader = request.headers.get("authorization");
  const token = authHeader?.startsWith("Bearer ") ? authHeader.split(" ")[1] : null;

  // Check if token is provided and valid
  if (!token) {
    return Response.json(
      { error: "No token provided" },
      { status: 401 }
    );
  }

  if (token !== VALID_TOKEN) {
    return Response.json(
      { error: "Invalid token" },
      { status: 401 }
    );
  }

  // Add custom header to indicate middleware processing
  const response = NextResponse.next();
  response.headers.set("X-Auth-Status", "Authenticated");

  return response;
}

export const config = {
  // ALl paths in the protected folder
  matcher: ["/api/protected/:path*"],
};
```
