尝试让 PhoneTrack (https://gitlab.com/eneiluj/phonetrack-android/-/wikis/userdoc) 与我的 API 网关一起接收位置数据。我已经设置了我的 API 来处理发布请求,如果我使用编码
application/jason
来卷曲它,它就可以正常工作。问题是该应用程序正在使用 application/x-www-form-urlencoded
的编码。
我已经设置了两个映射模板,并且尝试了一些组合来使映射工作,但是 x-www-form-urlencoded 模板似乎没有做任何事情,而且我认为我还没有完全理解如何获得这个对吧。
这是我的地形资源:
resource "aws_api_gateway_integration" "ddb_integration" {
depends_on = [aws_api_gateway_method.generic_post]
rest_api_id = aws_api_gateway_rest_api.generic_api.id
resource_id = aws_api_gateway_resource.generic_resource.id
http_method = aws_api_gateway_method.generic_post.http_method
passthrough_behavior = "NEVER"
content_handling = "CONVERT_TO_TEXT"
integration_http_method = "POST"
uri = "arn:aws:apigateway:${local.workspace.aws_region}:dynamodb:action/PutItem"
credentials = aws_iam_role.api_gw_to_ddb.arn
type = "AWS"
request_templates = {
"application/json" = <<-EOF
{
"TableName": "${aws_dynamodb_table.generic_data.name}",
"Item": {
"lon": {
"N": "$input.json('$.lon')"
},
"lat": {
"N": "$input.json('$.lat')"
},
"timestamp": {
"S": "$input.json('$.timestamp')"
}
}
}
EOF
"application/x-www-form-urlencoded" = <<-EOF
{
$util.log("Starting processing input body...")
#foreach( $token in $input.body.split('&') )
$util.log("Current token: $token")
#set( $keyVal = $token.split('=') )
#set( $keyValSize = $keyVal.size() )
$util.log("Split token into key and value. KeyValSize: $keyValSize")
#if( $keyValSize >= 1 && !$keyVal[0].isEmpty() )
#set( $key = $util.urlDecode($keyVal[0]) )
$util.log("Decoded key: $key")
#set($key = $key.substring(0,1).toLowerCase() + $key.substring(1))
$util.log("Processed key with first letter lower-cased: $key")
#if( $keyValSize >= 2 )
#set( $val = $util.urlDecode($keyVal[1]) )
$util.log("Decoded value: $val")
#if( $key == "lon" || $key == "lat" || $key == "timestamp" )
$util.log("$key: $val")
#end
#else
#set( $val = '' )
$util.log("No value found for key. Setting value to empty.")
#end
"$key": "$util.escapeJavaScript($val)"#if($foreach.hasNext),#end
#else
$util.log("Error processing token: $token. Either key is missing or empty.")
#end
#end
$util.log("Finished processing input body.")
}
EOF
}
}
这适用于
application/json
版本。我尝试在 Apache Velocity 模板语言中设置的日志记录,模板代码似乎没有登录到 cloudwatch,所以我似乎没有办法研究它是如何工作的。我还尝试使用最简单的版本进行 url 编码:
{
"TableName": "${aws_dynamodb_table.generic_data.name}",
"Item": {
"lon": {
"N": "$util.urlDecode($input.params('lon'))"
},
"lat": {
"N": "$util.urlDecode($input.params('lat'))"
},
"timestamp": {
"S": "$util.urlDecode($input.params('timestamp'))"
}
}
}
但这也行不通。在我的 APIG 执行日志下面,明显的问题是序列化异常。
问题显然是 URL 编码的对象负载没有被转换成 DDB 可以理解的东西。所以问题是映射模板没有发挥其魔力。这行得通吗?还是我需要使用 lambda 来让它发挥作用?
Apache VTL 似乎对 URL 编码的有效负载没有做任何事情,但是,它似乎对 json 编码的有效负载处理得很好。有没有办法让日志记录功能与 VTL 一起使用?
(REQUEST_ID_REMOVED) Extended Request Id: MGm12FcyoAMEsgA=
(REQUEST_ID_REMOVED) Verifying Usage Plan for request: REQUEST_ID_REMOVED. API Key: API Stage: STAGE_ID_REMOVED/prod
(REQUEST_ID_REMOVED) API Key authorized because method 'POST /data' does not require API Key. Request will not contribute to throttle or quota limits
(REQUEST_ID_REMOVED) Usage Plan check succeeded for API Key and API Stage STAGE_ID_REMOVED/prod
(REQUEST_ID_REMOVED) Starting execution for request: REQUEST_ID_REMOVED
(REQUEST_ID_REMOVED) HTTP Method: POST, Resource Path: /data
(REQUEST_ID_REMOVED) Method request path: {}
(REQUEST_ID_REMOVED) Method request query string: {}
(REQUEST_ID_REMOVED) Method request headers: {User-Agent=curl/8.3.0, X-Forwarded-Proto=https, X-Forwarded-For=REMOVED_IP, content-type=application/x-www-form-urlencoded, Host=REMOVED, X-Forwarded-Port=443, accept=*/*}
(REQUEST_ID_REMOVED) Method request body before transformations: lon=151.0&lat=-33.0×tamp=1695994041
(REQUEST_ID_REMOVED) Endpoint request URI: https://dynamodb.us-east-1.amazonaws.com/?Action=PutItem
(REQUEST_ID_REMOVED) Endpoint request headers: {Authorization=REMOVED, X-Amz-Date=20231001T034528Z, x-amzn-apigateway-api-id=STAGE_ID_REMOVED, Accept=application/x-www-form-urlencoded, User-Agent=AmazonAPIGateway_STAGE_ID_REMOVED, X-Amz-Security-Token=REMOVED
(REQUEST_ID_REMOVED) Endpoint request body after transformations: lon=151.0&lat=-33.0×tamp=1695994041
(REQUEST_ID_REMOVED) Sending request to https://dynamodb.us-east-1.amazonaws.com/?Action=PutItem
(REQUEST_ID_REMOVED) Received response. Status: 400, Integration latency: 6 ms
(REQUEST_ID_REMOVED) Endpoint response headers: {Server=Server, Date=Sun, 01 Oct 2023 03:45:28 GMT, Content-Type=application/x-amz-json-1.0, Content-Length=60, Connection=keep-alive, x-amzn-RequestId=REMOVED, x-amz-crc32=REMOVED}
(REQUEST_ID_REMOVED) Endpoint response body before transformations: {"__type": "com.amazon.coral.service#SerializationException"}
(REQUEST_ID_REMOVED) Execution failed due to configuration error: No match for output mapping and no default output mapping configured. Endpoint Response Status Code: 400
(REQUEST_ID_REMOVED) Gateway response type: DEFAULT_5XX with status code: 500
(REQUEST_ID_REMOVED) Gateway response body: {"message": "An unexpected error occurred."}
(REQUEST_ID_REMOVED) Gateway response headers: {x-amzn-ErrorType=InternalServerErrorException}
(REQUEST_ID_REMOVED) Method completed with status: 500
在 GPT 的帮助下,我尝试了许多不同的映射模板组合。我尝试尽可能详细地注销数据,希望能跳出一些内容,但我无法克服这一点。
您收到 400 异常,您尚未为其设置响应映射,因此您不确定错误的真正原因。我的预感是您得到了
ResourceNotFoundException
,并且我相信您在 VTL 中解析表名的方式不正确。获取表名称并将其硬编码到模板中,然后重试。这将让您确定问题的原因,然后您可以着手修复。
还设置一个异常模板,以便您知道遇到的错误。