You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

AWS API Gateway二进制媒体类型映射异常,Lambda无PDF数据求助

问题:API Gateway无法映射application/pdf模板导致Lambda无法获取PDF数据

问题描述

此前正常运行的AWS API Gateway+Lambda PDF上传功能突然失效,API Gateway无法正确映射application/pdf类型的集成模板,导致Lambda无法获取PDF数据。已在API设置中允许application/pdf并配置映射模板,排查无果,附上Terraform脚本:

resource "aws_api_gateway_rest_api" "api_gateway" {
name               = "api_gateway"
description        = "API Gateway"
binary_media_types = ["application/pdf"]
endpoint_configuration {
types = ["REGIONAL"]
}
}

resource "aws_api_gateway_account" "infofusion" {
cloudwatch_role_arn = aws_iam_role.cloudwatch.arn
}

data "aws_iam_policy_document" "assume_role" {
statement {
effect = "Allow"

    principals {
      type        = "Service"
      identifiers = ["apigateway.amazonaws.com"]
    }
    
    actions = ["sts:AssumeRole"]

}
}

resource "aws_iam_role" "cloudwatch" {
name               = "api_gateway_cloudwatch_global"
assume_role_policy = data.aws_iam_policy_document.assume_role.json
}

data "aws_iam_policy_document" "cloudwatch" {
statement {
effect = "Allow"

    actions = [
      "logs:CreateLogGroup",
      "logs:CreateLogStream",
      "logs:DescribeLogGroups",
      "logs:DescribeLogStreams",
      "logs:PutLogEvents",
      "logs:GetLogEvents",
      "logs:FilterLogEvents"
    ]
    
    resources = ["*"]

}
}
resource "aws_iam_role_policy" "cloudwatch" {
name   = "default"
role   = aws_iam_role.cloudwatch.id
policy = data.aws_iam_policy_document.cloudwatch.json
}

resource "aws_api_gateway_authorizer" "cognito" {
name            = "cognito"
rest_api_id     = aws_api_gateway_rest_api.api_gateway.id
type            = "COGNITO_USER_POOLS"
identity_source = "method.request.header.Authorization"
provider_arns   = [aws_cognito_user_pool.user_pool.arn]
}

resource "aws_api_gateway_resource" "pdf" {
parent_id   = aws_api_gateway_rest_api.api_gateway.root_resource_id
path_part   = "pdf"
rest_api_id = aws_api_gateway_rest_api.api_gateway.id
}

resource "aws_api_gateway_method" "upload_pdf" {
rest_api_id = aws_api_gateway_rest_api.api_gateway.id
resource_id = aws_api_gateway_resource.pdf.id
request_parameters = {
"method.request.querystring.pdfName"   = true
"method.request.querystring.projectId" = true
}
http_method   = "PUT"
authorization = "COGNITO_USER_POOLS"
authorizer_id = aws_api_gateway_authorizer.cognito.id
}

resource "aws_api_gateway_integration" "upload_pdf" {
rest_api_id             = aws_api_gateway_rest_api.api_gateway.id
resource_id             = aws_api_gateway_resource.pdf.id
http_method             = aws_api_gateway_method.upload_pdf.http_method
integration_http_method = "POST"
type                    = "AWS"
uri                     = aws_lambda_function.manage_pdf.invoke_arn
request_parameters = {
"integration.request.querystring.pdfName"   = "method.request.querystring.pdfName"
"integration.request.querystring.projectId" = "method.request.querystring.projectId"
}
passthrough_behavior = "WHEN_NO_MATCH"
request_templates = {
# "application/pdf" = file("${path.module}/resource/apigateway/pdf_upload_mapping_template.vt")
# I have a more sophisticated vt but at the moment I just want to get the body first
"application/pdf" = <<-EOT
{
"data": "$input.body"
}
EOT
}
}

resource "aws_lambda_permission" "pdf_lambda_permission" {
statement_id  = "AllowAPIInvokeManagePdf"
action        = "lambda:InvokeFunction"
function_name = aws_lambda_function.manage_pdf.function_name
principal     = "apigateway.amazonaws.com"

source_arn = "${aws_api_gateway_rest_api.api_gateway.execution_arn}/*/*". # one doc in tf said /\* and this other /*/*, both stop working
}

解决方案与排查点

1. 修正传递行为,强制使用映射模板

当前passthrough_behavior = "WHEN_NO_MATCH"会导致API Gateway对二进制类型跳过模板,直接传递原始数据。修改为:

passthrough_behavior = "NEVER"

确保API Gateway强制使用你配置的application/pdf映射模板处理请求。

2. 正确处理二进制数据的Base64编码

二进制PDF数据无法直接通过JSON传递,需要在映射模板中编码为Base64,修改模板内容:

"application/pdf" = <<-EOT
{
  "data": "$util.base64Encode($input.body)",
  "pdfName": "$input.params('pdfName')",
  "projectId": "$input.params('projectId')"
}
EOT

Lambda端解码data字段即可得到原始PDF字节流。

3. 修复Lambda权限的ARN格式错误

source_arn末尾多了一个句号,修正为:

source_arn = "${aws_api_gateway_rest_api.api_gateway.execution_arn}/*/*"

更严谨的写法可以指定到具体方法,避免权限过宽:

source_arn = "${aws_api_gateway_rest_api.api_gateway.execution_arn}/PUT/pdf"

4. 添加API Gateway部署资源

你的Terraform脚本缺少部署资源,配置修改后不会生效。添加:

resource "aws_api_gateway_deployment" "pdf_upload" {
  depends_on = [aws_api_gateway_integration.upload_pdf]
  rest_api_id = aws_api_gateway_rest_api.api_gateway.id
  stage_name = "prod" # 替换为你的实际阶段名称
}

每次修改API配置后,部署会自动更新生效。

5. 利用CloudWatch日志定位问题

在API Gateway的阶段设置中开启全量日志记录,查看:

  • 请求的Content-Type是否严格为application/pdf
  • 映射模板是否被正确触发
  • 传递到Lambda的请求体内容是否符合预期

内容的提问来源于stack exchange,提问作者Zhengtong Nie

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.10 20:26:03