本地Docker运行AWS Lambda函数,浏览器调用报错求助
解决本地Docker运行Lambda镜像时浏览器Fetch调用的UnmarshalError问题
问题场景
线上AWS Lambda启用Function URL后,浏览器通过JavaScript的fetch调用可正常工作(已配置CORS)。但本地用Docker运行同镜像时,浏览器调用出现异常:
- 浏览器控制台报错
- 容器日志输出
UnmarshalError: Unable to unmarshal input: Expecting value: line 1 column 1 (char 0) - Postman调用本地接口却能正常返回结果
原因分析
本地运行Lambda镜像依赖Lambda Runtime Interface Emulator(RIE),它的调用格式和线上Function URL存在差异:
- 线上Function URL会自动将普通HTTP请求转换为Lambda能识别的事件格式
- 本地RIE的默认端点
/2015-03-31/functions/function/invocations要求请求体必须是标准Lambda事件结构,而浏览器直接发送的普通JSON请求体不符合该格式,导致反序列化失败
Postman能正常调用,是因为请求符合了RIE的事件格式要求,而浏览器的fetch请求直接发送了原始JSON。
解决方案
方案1:修改前端请求适配RIE格式
直接调整前端的请求体,将数据包装成RIE所需的Lambda事件结构:
修改HTML中的JavaScript部分:
const button = document.getElementById('button'); button.addEventListener('click', async (e) => { // 切换到本地RIE端点 const endpointUrl = 'http://localhost:9000/2015-03-31/functions/function/invocations'; var myHeaders = new Headers(); myHeaders.append("Content-Type", "application/json"); // 包装成Lambda事件格式 var raw = JSON.stringify({ "httpMethod": "POST", "body": JSON.stringify({ "from": "browser" }), "headers": { "Content-Type": "application/json" } }); var requestOptions = { method: 'POST', headers: myHeaders, body: raw, }; fetch(endpointUrl, requestOptions) .then(response => response.text()) .then(result => console.log(result)) .catch(error => console.log('error', error)); });
方案2:使用AWS Lambda Adapter模拟线上Function URL行为
通过安装AWS Lambda Adapter,让本地容器直接处理普通HTTP请求,和线上Function URL行为完全一致,无需修改前端代码:
- 修改Dockerfile:
FROM public.ecr.aws/lambda/python:3.9 # 安装AWS Lambda Adapter COPY --from=public.ecr.aws/awsguru/aws-lambda-adapter:0.7.2 /lambda-adapter /opt/extensions/lambda-adapter COPY app.py ./ CMD ["app.handler"]
- 调整前端的endpointUrl为本地普通HTTP端点:
const endpointUrl = 'http://localhost:9000/';
- 重新构建镜像并启动容器:
docker-compose build docker-compose up
验证
无论使用哪种方案,点击页面按钮后:
- 容器日志会打印出正确的Lambda事件
- 浏览器控制台会输出
{"message": "Cool!!!"},调用成功
内容的提问来源于stack exchange,提问作者Rishabh Gupta
相关产品推荐
相关产品推荐

