Netlify部署Hugo站点调用Mailgun发信出现JSON解析错误
问题原因
两个JSON报错均由请求体解析逻辑和实际传入的请求格式不匹配导致:
Unexpected end of JSON input:触发函数时传入的event.body为空、或未完成传输、或是被base64编码的二进制内容,直接执行JSON.parse无法识别Unexpected token b in JSON at position 0:event.body是Buffer类型的二进制流,未转成字符串就直接解析,流的首字节对应字符b,不符合JSON语法规则
Netlify函数不会自动解析所有格式的请求体,当请求头Content-Type不是application/json、或请求体被base64编码时,直接调用JSON.parse(event.body)必然报错。
修复方案
按以下步骤调整即可:
- 替换原有直接解析请求体的逻辑,增加编码判断、格式兼容和错误捕获,覆盖JSON提交、普通表单提交、base64编码请求体三种常见场景
- 检查前端请求逻辑:如果是JS异步提交表单,必须设置请求头
Content-Type: application/json,发送数据前用JSON.stringify()转成合法JSON字符串;如果是原生form表单同步提交,不需要额外改前端,后端加urlencoded格式解析即可 - 解析逻辑后增加字段校验,避免必填字段为空导致后续邮件发送逻辑报错
修复后的完整函数代码如下:
require('dotenv').config() const { MAILGUN_API_KEY, MAILGUN_DOMAIN, MAILGUN_URL, FROM_EMAIL_ADDRESS, CONTACT_TO_EMAIL_ADDRESS } = process.env const mailgun = require('mailgun-js')({ apiKey: MAILGUN_API_KEY, domain: MAILGUN_DOMAIN, host: "api.eu.mailgun.net" }) exports.handler = async (event, context, callback) => { let data = {} // 处理base64编码的请求体 let rawBody = event.body if (event.isBase64Encoded) { rawBody = Buffer.from(event.body, 'base64').toString('utf8') } // 按请求头的Content-Type匹配对应解析规则 const contentType = event.headers['content-type'] || event.headers['Content-Type'] || '' try { if (contentType.includes('application/json')) { data = JSON.parse(rawBody) } else if (contentType.includes('application/x-www-form-urlencoded')) { // 解析普通表单提交的urlencoded格式数据 rawBody.split('&').forEach(kvPair => { const [key, val] = kvPair.split('=') data[decodeURIComponent(key)] = decodeURIComponent(val.replace(/\+/g, ' ')) }) } } catch (parseError) { console.log('请求体解析失败,原始内容:', rawBody) return { statusCode: 400, headers: { "Access-Control-Allow-Origin": "*" }, body: JSON.stringify({ error: "请求格式不合法" }) } } // 原有邮件发送逻辑保持不变 var text = `Dear ${data.name}, \n\n` text += `${data.message} \n` text += `Country of residence: ${data.country} \n` const style = "<style> </style>" var body = `<html>${style}<div>` body += `<p>Dear ${data.name},</p>` body += `<h4>Your message:</h4><p>${data.message}</p>` body += `<p>Country of residence: ${data.country}</p>` body += `</div></html>` let response try { response = await mailgun.messages().send({ to: data.email, bcc: CONTACT_TO_EMAIL_ADDRESS, from: FROM_EMAIL_ADDRESS, subject: `Enquiry for Summertime from ${data.arrdate}`, text: text, html: body }) } catch (error) { console.log('邮件发送错误: ', error) return { statusCode: error.statusCode || 500, headers: { "Access-Control-Allow-Origin": "*" }, body: JSON.stringify({ error: error.message }) } } return { statusCode: 200, headers: { "Access-Control-Allow-Origin": "*" }, body: JSON.stringify({ result: 200 }) } }
部署前可以先在本地Netlify开发环境测试,打印解析后的
data对象确认所有表单字段都能正常读取,再上线使用。
内容的提问来源于stack exchange,提问作者Our Man in India
相关产品推荐
相关产品推荐

