如何在Go语言AWS Lambda中直接接收API Gateway原始请求字节
问题:Go语言Lambda无法直接接收API Gateway原始请求体字节
我尝试用Go语言结合AWS Lambda与API Gateway构建REST API,希望直接处理原始请求体字节,无需手动进行Base64转换。目前API Gateway已配置application/octet-stream为Binary Media Types,Lambda集成设置了ContentHandling.CONVERT_TO_BINARY,但Lambda始终返回JSON解析错误,提示无法将二进制数据解析为JSON。
当前配置与错误信息
CDK集成代码
const testPath = api.root.addResource('test'); const testIntegration = new LambdaIntegration(props.testFunc, { proxy: false, contentHandling: ContentHandling.CONVERT_TO_BINARY, passthroughBehavior: PassthroughBehavior.WHEN_NO_MATCH, }); testPath.addMethod('POST', testIntegration);
Go Lambda处理函数
func Handler(ctx context.Context, payload []byte) ([]byte, error) { fmt.Println("received...") fmt.Printf("received request of length: %v", len(payload)) return nil, nil } func main() { lambda.Start(Handler) }
错误响应
{"message": "Could not parse request body into json: Could not parse payload into json: Invalid UTF-8 start byte 0xa3\n at [Source: (byte[])"\uFFFDWQo\uFFFD8\u0010.......\uFFFD"[truncated 360 bytes]; line: 1, column: 6]"}
API Gateway日志摘要
(xxx) Method request body before transformations: [Binary Data] (xxx) Endpoint request body after transformations: [Binary Data] (xxx) Execution failed: Could not parse request body into json: Could not parse payload into json: Invalid UTF-8 start byte 0xa3
问题原因
Lambda的Go运行时要求输入参数必须是可被encoding/json反序列化的类型:
- 当你使用
[]byte作为处理函数参数时,运行时期望输入是base64编码的JSON字符串,然后自动解码为字节数组。 - 但当前API Gateway直接传递原始二进制数据给Lambda,运行时尝试将非JSON格式的二进制数据解析为JSON,导致报错。
解决方案
方案1:自动处理Base64转换(代码无需手动解码)
调整API Gateway配置,将原始二进制数据Base64编码后以JSON字符串形式传递给Lambda,让Go运行时自动解码为字节数组。
修改后的CDK代码
const testPath = api.root.addResource('test'); const testIntegration = new LambdaIntegration(props.testFunc, { proxy: false, contentHandling: ContentHandling.CONVERT_TO_TEXT, passthroughBehavior: PassthroughBehavior.WHEN_NO_MATCH, }); testPath.addMethod('POST', testIntegration, { // 映射模板:将原始请求体Base64编码后作为JSON字符串传递 requestTemplates: { 'application/octet-stream': '$util.base64Encode($input.body)', }, });
保持原Go处理函数不变
func Handler(ctx context.Context, payload []byte) ([]byte, error) { fmt.Println("received...") fmt.Printf("received request of length: %v", len(payload)) // 直接使用payload原始字节处理业务逻辑 return nil, nil } func main() { lambda.Start(Handler) }
方案2:使用API Gateway代理模式+V2请求事件
如果希望完全避免Base64转换的感知,可以使用API Gateway V2的HTTP API代理模式,结合APIGatewayV2HTTPRequest事件类型,此时请求体将直接以原始字节对应的字符串形式传递(无需手动解码)。
修改后的CDK代码
const testPath = api.root.addResource('test'); const testIntegration = new LambdaIntegration(props.testFunc, { proxy: true, // 启用代理模式 contentHandling: ContentHandling.CONVERT_TO_BINARY, passthroughBehavior: PassthroughBehavior.WHEN_NO_MATCH, }); testPath.addMethod('POST', testIntegration);
修改后的Go处理函数
import ( "context" "fmt" "github.com/aws/aws-lambda-go/events" "github.com/aws/aws-lambda-go/lambda" ) func Handler(ctx context.Context, req events.APIGatewayV2HTTPRequest) ([]byte, error) { // req.Body即为原始请求体字节对应的字符串,直接转换为[]byte使用 requestBytes := []byte(req.Body) fmt.Printf("received request of length: %v", len(requestBytes)) return nil, nil } func main() { lambda.Start(Handler) }
内容的提问来源于stack exchange,提问作者Swati
相关产品推荐
相关产品推荐

