Next.js如何正确处理跨域问题?

news/2024/12/22 23:57:37/

以前一直使用Vue来写前端。去年下半年接手了一个基于React + Next.js的项目,于是顺带学习了一下Next.js。由于Next.js的特点,这个项目的前后端是放在一起的。一开始没什么问题,看了半天文档就上手了。

上周我们需要在另一个网页项目中,调用这个项目的后端接口,于是就需要处理跨域请求的问题。但我发现按照网上的方法,跨域问题依然存在。这个问题浪费了我不少时间,好在最后终于找到了原因。记录在这里,免得大家跟我一样踩坑。

为了复现这个问题,我们先来创建一个Next.js项目。执行代码创建代码脚手架:

npx create-next-app test_cors

使用TypeScript,其他选项选择默认,如下图所示:

图片

命令执行完成以后,会生成一个test_cors文件夹,在文件夹中创建文件pages/api/test.ts。内容如下:

import { NextResponse } from 'next/server'export const config = {runtime: "edge"
}export interface UserInfo {name: stringage: numberaddress: string
}const handler = async (req: Request): Promise<Response> => {const user = (await req.json()) as UserInforeturn NextResponse.json({success: true,msg: `你的名字是${user.name}, 今年${user.age}岁`})
}export default handler;

如下图所示:

图片

然后运行命令npm run dev。这个后端接口就启动起来了。我们可以使用Postman来进行测试:

图片

接下来,我们来写一段HTML代码,触发跨域问题:

<!DOCTYPE html>
<html lang="zh-CN">
<head><meta charset="UTF-8"><title>API 请求示例</title><script>// 当按钮被点击时执行此函数function sendRequest() {// 创建一个新的 XMLHttpRequest 对象var xhr = new XMLHttpRequest();// 配置请求类型、URL 以及异步处理xhr.open('POST', 'http://127.0.0.1:3000/api/test', true);// 设置请求头xhr.setRequestHeader('Content-Type', 'application/json');// ... 其他请求头设置// 设置响应类型xhr.responseType = 'json';// 定义请求完成的回调函数xhr.onload = function () {if (xhr.status === 200) {// 请求成功,处理响应数据document.getElementById('response').innerText = JSON.stringify(xhr.response);} else {// 请求失败,处理错误document.getElementById('response').innerText = '请求失败: ' + xhr.status;}};// 发送请求xhr.send(JSON.stringify({name: "青南", age: 20, "address": "上海"}));}</script>
</head>
<body><button onclick="sendRequest()">发送请求</button><div id="response"></div>
</body>
</html>

直接双击打开这个html文件,点击页面上的按扭,就会触发跨域报错,如下图所示:

图片

然后,你在网上用关键词搜索next.js 跨域或者next.js cors,一般看到的文章都会让你直接在next.config.js文件中添加响应头,如下图所示:

图片

你按照这些文章中写到方法加了配置,重启服务,然后用Postman来测试,你会发现返回的响应头里面确实已经有这几项了,如下图所示:

图片

但当你使用HTML页面来测试时,跨域的报错还在。

你连续打开Google上面10篇讲Next.js跨域的文章,无论是中文博客还是英文博客,甚至你直接使用ChatGPT来问,他们给你的回复肯定都是上面的这个方法。但是无论你怎么测试,跨域问题还在。

实际上,跨域就是这样配置的。你的配置没有任何问题。问题出现在你的后端代码上,如下图所示:

图片

首先你需要是一个POST请求,你才能执行await req.json()。而浏览器在判断能不能跨域时,会首先发送一个OPTIONS请求,如下图所示:

图片

这个请求也会走到你的这段后端代码里面。但由于OPTIONS请求没有Body,于是代码运行到await req.json()时,就会报错。于是浏览器认为OPTIONS请求没有返回status 200,因此强行认为你的接口不支持跨域。

那么解决方法也非常简单,提前判断一下请求方法是不是OPTIONS就可以了:

if(req.method === 'OPTIONS') {return NextResponse.next()
}

如下图所示:

图片

运行效果如下图所示,跨域成功:

图片

这个问题对于资深前端来说,可能不值一提。但对于后端兼职前端的人,或者第一次接触Next.js的人来说,可能是一个深坑,会浪费很多的时间。


http://www.ppmy.cn/news/1337828.html

相关文章

Qt+css绘制标题

之前学过html和小程序&#xff0c;帮老师做项目的时候也用过vue&#xff0c;在想qt绘制界面是不是也可以使用css,然后查了一些资料&#xff0c;绘制了一个标题&#xff0c;准备用到智能家居的上位机上面。 成果 源码 重写了paintEvent函数和TimeEvent函数&#xff0c;一个用于绘…

Modern C++ idiom1:Copy-and-Swap

​ Copy-and-Swap&#xff08;拷贝并交换&#xff09;是一种 C 编程技术&#xff0c;用于以提供强异常安全性保证的方式实现赋值运算符&#xff08;operator&#xff09;。这种技术在处理资源管理&#xff08;如管理动态内存或其他外部资源&#xff09;时特别有用。该技巧涉及使…

这些AI写作软件让你轻松成为文坛巨擘

我们都知道写作是一件需要时间以及灵光乍现&#xff0c;但是灵感总有枯竭的时候&#xff0c;随着人工智能技术的不断发展&#xff0c;AI自动写作软件在国内市场上越来越受欢迎。这些软件利用先进的自然语言处理和机器学习算法&#xff0c;能够帮助用户快速生成高质量的文章。在…

条件判断的模式

防御式编程和卫语句 推荐的方法结构&#xff1a; function sample() {/* 前断言 P {这里是方法能够运行的前提} *//* 防御 {消除异常、性能、安全等问题} *//* 逻辑正文 C */ }表驱动 表驱动方法是一种编程模式&#xff08;Scheme&#xff09;&#xff0c;其的核心思想是将数据…

Idea设置代理后无法clone git项目

背景 对于我们程序员来说&#xff0c;经常上github找项目、找资料是必不可少的&#xff0c;但是一些原因&#xff0c;我们访问的时候速度特别的慢&#xff0c;需要有个代理&#xff0c;才能正常的访问。 今天碰到个问题&#xff0c;使用idea工具 clone项目&#xff0c;速度特…

【Tomcat与网络4】Tomcat的连接器设计

目录 1 如何设计一个灵活可靠的连接器 2 主要组件介绍 在上一篇&#xff0c;我们介绍了Tomcat提供服务的整体结构&#xff0c;本文我们一起来看一下Tomcat的连接器的设计。 在前面我们提到Tomcat主要完成两个功能&#xff1a; 处理 Socket 连接&#xff0c;负责网络字节流与…

C++/MFC:在窗体Form(Dialog)中多个编辑框时,在输入时将回车解释为TAB键,将输入焦点移到下一个编辑框的方法

很多时候&#xff0c;为了输入方便&#xff0c;常用的做法&#xff0c;就是将回车键解释为将输入焦点移动到下一个编辑框中。就像是我的VxTerm中的快速连接输入一样&#xff1a; VxTerm是一个国产化替代的SSH工具&#xff0c;可以从本站的资源中免费下载并且免费使用&#xff…

(HAL)STM32F407ZGT6——10-4 高级定时器 PWM 输入模式实验

一、高级定时器简介 高级定时器的框图和通用定时器框图很类似&#xff0c;只是添加了其它的一些功能&#xff0c;如&#xff1a;重复计数器、带死区控制的互补输出通道、断路输入等。 高级定时器的时钟来自APB2, 而PCLK2 168Mhz, 我们设置PPRE2不分频, 因此高级定时器时钟 …