S3托管联系表单通过JS直接POST到API Gateway的问题
解决S3静态联系表单POST请求错误发送至S3桶的问题
问题描述
在AWS S3托管的静态HTML联系表单,预期通过JavaScript将表单数据POST到AWS API Gateway端点,再由Node.js Lambda调用SES发送邮件。实际测试时,点击提交按钮后,POST请求被错误发送到S3桶地址,返回405错误,但通过curl直接调用API Gateway端点可正常触发Lambda发送邮件。
解决方案
1. 修正API端点URL格式
原JavaScript代码中,API端点URL被错误地用<>包裹,导致URL无效,浏览器最终使用表单默认提交地址(S3桶地址)。需移除多余的<>:
// 修正前 const endpoint = "<https://MyApiGatewayEndpoint-east-1.amazonaws.com/test/mailfwd>"; // 修正后 const endpoint = "https://MyApiGatewayEndpoint-east-1.amazonaws.com/test/mailfwd";
2. 确保表单默认提交行为被完全阻止
在提交事件监听函数中,确认event.preventDefault()正确触发,可添加日志验证:
form.addEventListener("submit", (event) => { // 阻止默认表单提交行为 event.preventDefault(); console.log("表单提交事件已拦截"); // 验证是否触发 // 后续逻辑... });
3. 添加JSON请求头(推荐)
由于发送的是JSON格式数据,需在请求中指定Content-Type头,确保API Gateway能正确解析请求体:
const requestOptions = { method: "POST", headers: { "Content-Type": "application/json" }, body };
4. 修正Lambda变量名不匹配问题(避免后续邮件发送失败)
JavaScript中传递的字段名与Lambda中解析的字段名不一致,会导致邮件内容缺失。需统一字段映射:
// Lambda函数修正后 exports.handler = async function (event) { console.log('EVENT: ', event) // 匹配JS传递的字段名,重命名为Lambda需要的变量 const { senderName, email: senderEmail, phone: senderPhone, subject, message } = JSON.parse(event.body) const params = { Destination: { ToAddresses: ["MyToAddress@whatever.com"], }, Message: { Body: { Text: { Data: `You just got a message from ${senderName} at phone number ${senderPhone} - ${senderEmail}: ${message}` }, }, Subject: { Data: `Message regarding ${subject}` }, }, Source: "contactform@whateverelse.com", }; return ses.sendEmail(params).promise(); };
修正后的完整JavaScript代码
<script async type="text/javascript"> const form = document.querySelector("form"); form.addEventListener("submit", (event) => { // 阻止默认表单提交行为 event.preventDefault(); console.log("表单提交事件已拦截"); const { name, email, phone, subject, message } = event.target; // 修正后的API端点URL const endpoint = "https://MyApiGatewayEndpoint-east-1.amazonaws.com/test/mailfwd"; const body = JSON.stringify({ senderName: name.value, email: email.value, phone: phone.value, subject: subject.value, message: message.value }); const requestOptions = { method: "POST", headers: { "Content-Type": "application/json" }, body }; fetch(endpoint, requestOptions) .then((response) => { if (!response.ok) throw new Error("Error in fetch"); return response.json(); }) .then((response) => { document.getElementById("result-text").innerText = "Email sent successfully!"; }) .catch((error) => { document.getElementById("result-text").innerText = "An unknown error occurred."; }); }); </script>
内容的提问来源于stack exchange,提问作者James Eastman
相关产品推荐
相关产品推荐

