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

使用VTL为AWS API Gateway编写自定义错误响应映射模板报内部服务错误

AWS API Gateway VTL映射模板返回500错误排查

问题描述

为AWS API Gateway的集成响应编写VTL映射模板,期望返回自定义格式的错误输出。
第一版模板代码如下:

{
    "gw_code":"$gw_code",
    "er_code":"$er_code",
    "code":"$gw_code" + "-" + "$er_code",
    "developerMessage":"$developerMessage"
    "message":"$message"
    "gw_msg":"$code
              $developerMessage"
}
#set ($er_num = "200")
#set ($er_msg = "ACCESS_DENIED")
#if($code == "403-001" && $developerMessage == "Unauthorized")
    // Ignore
#else
    {
        "code" : "403-001",
        "developerMessage" : "Unauthorized."
    }
#end

部署后访问接口返回内部服务器错误,响应内容为:

{"message": "Internal server error"}

参考VTL语法规则精简修改后得到第二版模板:

#set($messageOverride = "foo")
{
    #if($status == "403-001" && $developerMessage = "Unauthorized")
        // Ignore
    #else
        #if($inputRoot.toString().contains("error"))
            "code" : "403-001",
            "developerMessage" : "Unauthorized."
        #end
    #end
#end
}

修改后500错误仍然存在,无法定位问题点。

错误原因

两版模板同时存在VTL语法错误、输出JSON结构非法两类问题,任意一个问题都会触发API Gateway的模板解析失败,直接返回500响应:

  • 第一版模板问题:
    • JSON语法错误:"developerMessage":"$developerMessage"、"message":"$message"两个键值对末尾缺少分隔逗号;gw_msg字段直接换行写值,生成非法JSON格式
    • VTL语法错误:不支持在JSON值位置直接用+做字符串拼接,拼接逻辑必须放在#set指令中完成;使用//写注释,VTL会将其识别为普通文本输出,破坏JSON结构
    • 输出结构错误:第一个JSON对象闭合后,条件分支又输出第二个独立JSON对象,最终响应是两段拼接的无效内容
  • 第二版模板问题:
    • VTL语法错误:条件判断中用单等号=做相等比较,VTL中相等判断必须使用双等号==;直接调用未定义的$inputRoot变量方法,触发解析异常;#if块闭合位置错误,多余的#end导致VTL引擎解析失败
    • 同样存在//注释被输出破坏JSON结构的问题

注意:API Gateway对VTL映射模板的输出校验非常严格,最终输出必须是完全合法的JSON结构,任何多余字符、格式错误都会直接返回500。VTL的单行注释必须用##开头,多行注释需要用#* ... *#包裹。

修复参考模板

## 提前拼接错误码,避免在JSON结构中写运算逻辑
#set($respCode = "${gw_code}-${er_code}")

## 提前处理分支逻辑,确定最终返回字段值
#if($respCode == "403-001" && $developerMessage == "Unauthorized")
    #set($finalCode = $respCode)
    #set($finalDevMsg = $developerMessage)
#else
    #set($finalCode = "403-001")
    #set($finalDevMsg = "Unauthorized.")
#end

## 最后输出唯一的合法JSON结构
{
    "gw_code": "$gw_code",
    "er_code": "$er_code",
    "code": "$finalCode",
    "developerMessage": "$finalDevMsg",
    "message": "$message",
    "gw_msg": "${finalCode} ${finalDevMsg}"
}

如果需要使用$inputRoot读取集成响应的内容,必须在使用前先赋值:#set($inputRoot = $input.path('$')),不能直接调用未声明的变量。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.01 20:06:40