捕获表单邮箱并通过API发送时遭遇CORS跨域错误的问题求助
我在自己的网站上做了一个订阅表单,想要把捕获到的邮箱地址通过API发送出去,但运行时遇到了下面的错误:
"Access to fetch at 'https://domainname.com/api/subscribers' from origin 'null' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: Redirect is not allowed for a preflight request."
我的代码如下:
<form id="subscriptionForm"> <input type="email" id="emailInput" placeholder="Email Address" required> <button type="submit">Subscribe</button> </form> <script> document.getElementById("subscriptionForm").addEventListener("submit", function (event) { event.preventDefault(); var email = document.getElementById("emailInput").value; var data = { email: email }; var apiKey = "12345678"; fetch("https://domainname.com/api/subscribers", { method: "POST", headers: { "Content-Type": "application/json", "X-DemoAPI-Key": apiKey }, body: JSON.stringify(data) }) .then(function (response) { if (response.ok) { console.log("Success"); } else { console.error("Error"); } }) .catch(function (error) { console.error("Error:", error); }); }); </script>
有没有人知道我哪里出错了?
嘿,我来帮你分析下这个问题~
首先,这个错误的核心原因是预检请求(preflight request)被重定向了,而浏览器的CORS规则明确禁止预检请求被重定向,这就是你看到报错的根源。
先拆解下为什么会触发这个情况:
- 你的请求携带了自定义头
X-DemoAPI-Key,并且使用了Content-Type: application/json,这两个条件会让浏览器自动发送OPTIONS类型的预检请求,用来提前确认目标服务器是否允许跨域请求。 - 现在你的目标API地址
https://domainname.com/api/subscribers在收到预检请求后,返回了重定向响应(比如301/302状态码),这直接违反了CORS规范,所以浏览器会拦截后续的实际请求。
接下来给你几个可行的解决方向:
先检查API地址是否正确
很多时候重定向是因为URL写错了,比如有没有遗漏路径、域名是否需要带www/不带www?比如本来应该是https://www.domainname.com/api/subscribers,你写成了不带www的版本,服务器就会返回重定向,这就触发了预检请求的重定向问题。先确认API的正确地址,避免低级错误。修改API服务器的CORS配置(如果API是你维护的)
如果这个API是你自己开发的,那你需要在服务器端调整CORS设置:- 确保预检请求(OPTIONS)不会被重定向,直接返回200状态码和正确的CORS响应头。
- 配置允许的来源(Origin)、允许的请求头(包括你的
X-DemoAPI-Key和Content-Type)、允许的请求方法(POST、OPTIONS)。
举个Node.js/Express的例子,用cors中间件可以这么配置:
const cors = require('cors'); app.use(cors({ origin: '你的网站域名', // 比如'https://your-website.com' allowedHeaders: ['Content-Type', 'X-DemoAPI-Key'], methods: ['GET', 'POST', 'OPTIONS'] }));使用代理服务器转发请求(如果API无法修改)
如果这个API不是你维护的,没法调整它的CORS配置,那你可以在自己的服务器上搭建一个代理:让前端请求先发到自己的服务器,再由服务器转发到目标API。服务器端的请求不受浏览器CORS规则约束,这样就能绕开跨域问题。
比如用Node.js做简单代理的示例代码:const express = require('express'); const request = require('request'); const app = express(); app.use(express.json()); app.post('/api/proxy-subscribe', (req, res) => { const targetUrl = 'https://domainname.com/api/subscribers'; req.pipe(request({ url: targetUrl, method: 'POST', headers: { 'Content-Type': 'application/json', 'X-DemoAPI-Key': '12345678', ...req.headers }, body: JSON.stringify(req.body) })).pipe(res); }); app.listen(3000);之后前端的fetch地址改成
/api/proxy-subscribe即可。
另外,你错误信息里的origin 'null'也需要注意——这通常意味着你是直接打开本地HTML文件(file://协议)测试的,这种情况下浏览器会把origin设为null,很多API服务器会拒绝这种来源的请求。建议用本地服务器(比如http-server、live-server)来测试,这样origin就会是正常的http://localhost:xxx,也能避免一些额外的CORS问题。
最后再检查下你的API密钥是否正确,有没有调用该接口的权限,有时候权限问题也会间接导致重定向或者错误响应哦~
备注:内容来源于stack exchange,提问作者Gökmen Bekar

