Gatsby集成Mailchimp时遭遇CORS Policy Error,如何解决?
Gatsby集成Mailchimp遭遇CORS错误的解决方案
问题描述
将Mailchimp集成到Gatsby项目时触发CORS政策错误,错误提示:
"has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource."
预期效果:订阅请求成功发送至Mailchimp,用户完成新闻通讯订阅。
相关代码如下:
const SignUpBanner: React.FC<SignUpBannerProps> = ({}: SignUpBannerProps) => { const [email, setEmail] = useState(''); const [subscriptionStatus, setSubscriptionStatus] = useState(''); const handleSubscribe = async () => { try { const response = await axios.post( 'https://xxx.us21.list-manage.com/subscribe/post?u=xxxx&id=xxxx&f_id=xxxx', { EMAIL: email, SIGNUP: 'HOME', // Specify your signup location here }, { headers: { 'Content-Type': 'application/x-www-form-urlencoded', }, } ); if (response.status === 200) { setSubscriptionStatus('success'); } else { setSubscriptionStatus('error'); } } catch (error) { setSubscriptionStatus('error'); console.error('Error subscribing:', error); } }; return ( <div className={`${paddingForBanner}`}> <div className={`${paddingForSignUpContent} d-xl-flex d-lg-flex justify-content-xl-between justify-content-lg-between`} > <div className={`${signUpHeading}`}> Stay connected through our newsletter! </div> <div className={`${signUptitle}`}> Subscribe to our newsletter and get the latest insights on history, art & art & culture in your inbox. <div className={`${emailInput} d-xl-flex d-lg-flex`}> <div className={`${inputDiv}`}> <input type="email" placeholder="Enter Email" value={email} onChange={(e) => setEmail(e.target.value)} className={`${customInputField} ${emailfield} form-control`} /> </div> <div className={`${signUpButton} d-flex d-lg-flex flex-row flex-lg-row justify-content-end align-items-center justify-content-lg-center `} onClick={handleSubscribe} > <div className={`${signUpText}`}> {subscriptionStatus === 'success' ? 'Subscribed!' : 'SIGNUP'} </div> </div> </div> </div> </div> </div> ); }; export default SignUpBanner;
解决方法
Mailchimp的公开订阅端点不允许浏览器直接发起请求,这是CORS错误的核心原因。以下是三种可行的解决方式:
1. 用Gatsby Serverless Functions做代理
通过Gatsby的Serverless Functions转发请求,绕开浏览器的CORS限制:
- 在项目根目录创建
src/api/subscribe.js文件:
const axios = require('axios'); exports.handler = async (event) => { if (event.httpMethod !== 'POST') { return { statusCode: 405, body: 'Method Not Allowed' }; } const { email } = JSON.parse(event.body); const mailchimpUrl = 'https://xxx.us21.list-manage.com/subscribe/post?u=xxxx&id=xxxx&f_id=xxxx'; try { const response = await axios.post( mailchimpUrl, new URLSearchParams({ EMAIL: email, SIGNUP: 'HOME' }), { headers: { 'Content-Type': 'application/x-www-form-urlencoded' } } ); return { statusCode: response.status, body: JSON.stringify({ message: 'Subscription successful' }) }; } catch (error) { return { statusCode: error.response?.status || 500, body: JSON.stringify({ error: 'Subscription failed' }) }; } };
- 修改前端代码中的请求地址为Gatsby函数端点:
const response = await axios.post('/api/subscribe', { email: email });
2. 使用Mailchimp嵌入式表单
直接使用Mailchimp提供的现成订阅表单:
- 登录Mailchimp后台,进入目标列表的「Signup forms」页面
- 选择「Embedded forms」,复制生成的HTML代码
- 在Gatsby组件中通过
dangerouslySetInnerHTML嵌入代码,或转换为React组件使用
3. 改用传统表单提交(无AJAX)
放弃AJAX请求,用原生表单提交避免CORS问题:
- 修改组件的返回部分,用
<form>包裹输入框和按钮:
return ( <div className={`${paddingForBanner}`}> <div className={`${paddingForSignUpContent} d-xl-flex d-lg-flex justify-content-xl-between justify-content-lg-between`} > <div className={`${signUpHeading}`}> Stay connected through our newsletter! </div> <div className={`${signUptitle}`}> Subscribe to our newsletter and get the latest insights on history, art & art & culture in your inbox. <form action="https://xxx.us21.list-manage.com/subscribe/post?u=xxxx&id=xxxx&f_id=xxxx" method="post" className={`${emailInput} d-xl-flex d-lg-flex`} > <div className={`${inputDiv}`}> <input type="email" placeholder="Enter Email" name="EMAIL" className={`${customInputField} ${emailfield} form-control`} required /> <input type="hidden" name="SIGNUP" value="HOME" /> </div> <button type="submit" className={`${signUpButton} d-flex d-lg-flex flex-row flex-lg-row justify-content-end align-items-center justify-content-lg-center `} > <div className={`${signUpText}`}>SIGNUP</div> </button> </form> </div> </div> </div> );
这种方式会刷新页面,若需要无刷新体验,优先选择第一种代理方案。
内容的提问来源于stack exchange,提问作者Shubham Belwal
相关产品推荐
相关产品推荐

