当前位置: 首页 > news >正文

Next Route Handlers的使用

本专栏内容均可在Github:test_04/route_handlers 找到,喜欢的兄弟上个Star

  • 本节Github 源码地址
  • Route Handlers

路由处理程序允许您使用 Web 请求为给定路由创建自定义请求处理程序和响应

需要了解:路由处理程序仅在 `app` 目录中可用。它们相当于 `pages` 目录中的 `API` 路由,这意味着您不需要同时使用 `API` 路由和路由处理程序。

一、约定

路由处理程序在 app 目录内的 route.js|ts 文件中定义:app/api/posts/route.ts

路由处理程序可以嵌套在 app 目录中的任何位置,类似于 page.jslayout.js 。但不能在与 page.js 相同的路由段级别上存在 route.js 文件。

在这里插入图片描述

每个 route.js 或 page.js 文件接管该路由的所有 HTTP 动词。

二、Request Method

我们从 GET 请求开始,现在写一个获取文章列表的接口

import { NextResponse } from "next/server";

export const GET = async () => {
  const res = await fetch("https://jsonplaceholder.typicode.com/posts");
  const data = await res.json();

  return NextResponse.json(data);
};

浏览器访问 http://localhost:3000/api/posts 查看接口返回的数据:

以下 HTTP 方法支持以下方法: GETPOSTPUTPATCHDELETEHEADOPTIONS 。如果调用了不受支持的方法,Next.js 将返回 405 Method Not Allowed 响应。

export const POST = async (request: Request) => {};

export const HEAD = async (request: Request) => {};

export const PUT = async (request: Request) => {};

export const PATCH = async (request: Request) => {};

export const DELETE = async (request: Request) => {};

// 如果 `OPTIONS` 没有定义, Next.js 会自动实现 `OPTIONS`
export const OPTIONS = async (request: Request) => {};

修改app/api/posts/route.ts 的 POST 方法为

export const POST = async (request: Request) => {
  console.log("request", request);
  const article = await request.json();

  return NextResponse.json(
    {
      id: Math.random().toString(36).slice(-8),
      data: article,
    },
    { status: 201 }
  );
};

三、获取请求参数

每个请求方法的处理函数会被传入两个参数,一个 request,一个 context 。两个参数都是可选的:

export async function GET(request, context) {}

request 对象是一个 NextRequest 对象,它是基于 Web Request API 的扩展。使用 request ,你可以快捷读取 cookies 和处理 URL

1、request query 参数获取

见:app/api/test/route.ts
打开浏览器输入 http://localhost:3000/api/test?name=myName

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

export const GET = async (request: NextRequest) => {
  // request /api/test
  console.log("request", request.nextUrl.pathname);

  // request URLSearchParams { 'name' => 'myName' }
  console.log("searchParams", request.nextUrl.searchParams);

  return NextResponse.json({
    message: "Hello, world!",
  });
};

2、request params 参数获取

见:app/api/blog/[id]/route.ts
打开浏览器输入 http://localhost:3000/api/blog/123

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

export const GET = async (
  { params }: { params: { id: string } }
) => {
  // request params { id: '123' }
  console.log("params", await params);

  return NextResponse.json({
    message: "Hello, world!",
  });
};

3、获取多个参数

见:app/api/detail/[name]/[age]/route.ts
打开浏览器输入 http://localhost:3000/api/detail/shmily/404

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

export const GET = async (
  { params }: { params: { name: string; age: string } }
) => {
  // request params { name: 'shmily', age: '20' }
  console.log("params", await params);

  return NextResponse.json({
    message: "Hello, world!",
  });
};

见:app/api/home/[…req]/route.ts
打开浏览器输入 http://localhost:3000/api/home/123/456/789

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

export const GET = async (
  { params }: { params: { req: string } }
) => {
  // request params { req: ['123', '456','789'] }
  console.log("params", await params);

  return NextResponse.json({
    message: "Hello, world!",
  });
};

四、常见问题

1、获取网站参数

// app/api/search/route.js
// 访问 /api/search?query=hello
export function GET(request) {
  const searchParams = request.nextUrl.searchParams
  const query = searchParams.get('query') // query
}

2、处理cookie

// app/api/route.js
import { cookies } from 'next/headers'
 
export async function GET(request) {
  const cookieStore = cookies()
  const token = cookieStore.get('token')
 
  return new Response('Hello, Next.js!', {
    status: 200,
    headers: { 'Set-Cookie': `token=${token}` },
  })
}

3、处理headers

// app/api/route.js
import { headers } from 'next/headers'
 
export async function GET(request) {
  const headersList = headers()
  const referer = headersList.get('referer')
 
  return new Response('Hello, Next.js!', {
    status: 200,
    headers: { referer: referer },
  })
}

4、如何重定向

import { redirect } from 'next/navigation'
 
export async function GET(request) {
  redirect('https://nextjs.org/')
}

5、获取请求体内容

// app/items/route.js 
import { NextResponse } from 'next/server'
 
export async function POST(request) {
  const res = await request.json()
  return NextResponse.json({ res })
}

如果为FormData类型

// app/items/route.js
import { NextResponse } from 'next/server'
 
export async function POST(request) {
  const formData = await request.formData()
  const name = formData.get('name')
  const email = formData.get('email')
  return NextResponse.json({ name, email })
}

6、设置CORS

// app/api/route.ts
export async function GET(request) {
  return new Response('Hello, Next.js!', {
    status: 200,
    headers: {
      'Access-Control-Allow-Origin': '*',
      'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
      'Access-Control-Allow-Headers': 'Content-Type, Authorization',
    },
  })
}

7、响应无 UI 内容?

// app/api/route.ts
export async function GET(request) {
  return new Response('Hello, Next.js!', {
    status: 200,
    headers: {
      'Access-Control-Allow-Origin': '*',
      'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
      'Access-Control-Allow-Headers': 'Content-Type, Authorization',
    },
  })
}

8、Stream 流

// app/api/chat/route.js
import OpenAI from 'openai'
import { OpenAIStream, StreamingTextResponse } from 'ai'
 
const openai = new OpenAI({
  apiKey: process.env.OPENAI_API_KEY,
})
 
export const runtime = 'edge'
 
export async function POST(req) {
  const { messages } = await req.json()
  const response = await openai.chat.completions.create({
    model: 'gpt-3.5-turbo',
    stream: true,
    messages,
  })
 
  const stream = OpenAIStream(response)
 
  return new StreamingTextResponse(stream)
}

相关文章:

  • 树莓派开发(一):烧录系统,设置SSH远程登录,用摄像头拍照
  • Nginx反向代理及负载均衡
  • 精选10个好用的WordPress免费主题
  • 代码随想录第55期训练营第十一天|LeetCode150.逆波兰表达式求值、239.滑动窗口最大值、347.前K个高频元素
  • 【日常笔记 1】 有关异常学习笔记
  • 《破解老龄化的智能密钥:机器人四维战略与未来养老生态》
  • 魔法测试:用本地多模态大模型(Qwen2.5-VL)将PDF转为Markdown文档
  • 大文件分片上传及断点续传实现
  • AI胡思乱想系列——大模型被当成了X度
  • 【Git Log 指南:提交历史的有效管理与分析】
  • 力扣刷题39. 组合总和
  • 基于 OCO - 2 氧气 A 带辐射数据与地面台站气压观测数据构建近地面气压监测算法方案
  • Java 8-17核心特性全景解析之Java8
  • 【WPF】ListView数据绑定
  • 4. 如何减少大模型幻觉?⸺大模型外挂向量数据库的分析(知识延伸版)
  • 基于DIFY与DeepSeek搭建AI技术博客智能体:从本地部署到自动化创作
  • 【测试篇】探秘自动化测试函数:解锁高效测试新路径
  • TCP粘包原因分析以及解决方案
  • 什么是权威解析服务器?权威解析服务器有什么用?(国科云)
  • 时尚复古品牌海报包装设计无衬线英文字体安装包 Malevice Inkbleed
  • 局域网内做网站/东莞营销推广公司
  • 网站更换空间需要怎么做/自媒体营销方式有哪些
  • 收费的网站怎么做/营销型网站建设案例
  • 有什么做视频的免费素材网站/sem推广什么意思
  • 建b2c网站需要办的手续/官网优化哪家专业
  • 酒店网站开发回扣/青岛网络seo公司