我想为无服务器的aws-nodes模板添加api验证,直到现在我已经测试过的任何东西都运行得很好。
我目前的方法是使用yml / json swagger定义覆盖现有的api-gateway,该api-gateway由无服务器框架生成,该定义包含用于验证的模型。当我在API-Gateway UI中测试它时,这对我有用,但在外部请求中,api不验证对lambda-proxy的请求。
当我使用普通的lambda时,api网关也会通过请求体而不进行验证或转换。
我当前的swagger api定义与验证:
swagger: "2.0"
info:
title: feedback
version: '1.0'
schemes:
- https
produces:
- application/json
x-amazon-apigateway-api-key-source : HEADER
x-amazon-apigateway-request-validators:
full:
validateRequestBody: true
validateRequestParameters: true
body-only:
validateRequestBody: true
validateRequestParameters: false
x-amazon-apigateway-request-validator: full
# Custom 400 response with validation feedback
x-amazon-apigateway-gateway-responses:
BAD_REQUEST_BODY:
statusCode: 400
type:
application/json:
responseTemplates:
application/json:
|-
{
"message": $context.error.messageString,
"validation": "$context.error.validationErrorString",
"statusCode": "'400'"
}
# request structure
paths:
/feedback:
post:
# validation definition
x-amazon-apigateway-request-validator: body-only
parameters:
- in: body
name: Create ...
required: true
schema:
"$ref": "#/definitions/Model"
responses:
'200':
description: validation succeeded
'400':
description: validation failed
x-amazon-apigateway-integration:
uri: "arn:aws:apigateway:{api-region}:lambda:path/2015-03-31/functions/arn:aws:lambda:{lambda-region}:{konto-id}:function:{function-name}/invocations"
passthroughBehavior: when_no_match
httpMethod: POST
requestTemplates:
application/json: '{"statusCode": 200}'
type: aws
get:
responses:
'201':
description: list all Data
content:
application/json:
schema:
type: array
items:
feedback:
$ref: "#/definitions/Model"
'401':
$ref: "#/definitions/UnauthorizedError"
x-amazon-apigateway-integration:
uri: "arn:aws:apigateway:{api-region}:lambda:path/2015-03-31/functions/arn:aws:lambda:{lambda-region}:{konto-id}:function:{function-name}/invocations"
passthroughBehavior: never
httpMethod: POST
type: aws_proxy
# definition of the request/respons model with validation
definitions:
Model:
type: object
properties:
topic:
$ref: "#/definitions/Topic"
text:
type: string
minLength: 1
maxLength: 250
required:
- topic
- text
Topic:
type: string
enum:
- xyz
我的serverless.yml中的api定义
functions:
create:
handler: feedback/create.create
events:
- http:
path: feedback
method: post
list:
handler: feedback/list.list
events:
- http:
path: feedback
method: get
lambda函数只能从/向DynamoDB读/写反馈
有人知道如何在不使用小插件(serverless-reqvalidator-plugin)或如何解决数据转换问题的情况下为我的无服务器项目添加某种api验证?
确定问题的解决方案是验证与内部测试一起使用而不是外部请求是非常明显的。我忘了部署新的api-definition。
aws apigateway create-deployment --rest-api-id {api-id} --stage-name dev
我也改变了我的API定义。我现在将我的Post请求归为普通lambda。这是唯一的方法,我可以确保只有json内容得到验证,然后传递给lamda函数。因为我没有使用lambda-proxy,所以请求事件从api-gateway转换,所以我必须定义一个请求模板,将整个请求体放在一个新请求中。
requestTemplates:
application/json: '{"statusCode": 202, "body": $input.body}'
通过这种方式,我还使用Cors头在预定义的api响应中转换了lambda响应。
我最后的解决方案是:
1:写一个swagger api定义:
swagger: "2.0"
info:
title: xxxxxx
version: '0.0.0'
schemes:
- https
produces:
- application/json
x-amazon-apigateway-api-key-source : HEADER
# Define which parts of the request should be validated
x-amazon-apigateway-request-validators:
full:
validateRequestBody: true
validateRequestParameters: true
body-only:
validateRequestBody: true
validateRequestParameters: false
# Custom response model from the api-gateway that return validation error string
x-amazon-apigateway-gateway-responses:
BAD_REQUEST_BODY:
statusCode: 400
type:
application/json:
responseParameters: # CORS Headers
gatewayresponse.header.Access-Control-Allow-Credentials : "'true'"
gatewayresponse.header.Access-Control-Allow-Origin : "'*'"
responseTemplates:
application/json: #must be an json string because otherwiese there are some transformation issues
|-
{
"message": $context.error.messageString,
"validation": "$context.error.validationErrorString",
"statusCode": "400"
}
paths:
/feedback:
options:
description:
Enable CORS by returning correct headers
tags:
- CORS
x-amazon-apigateway-integration:
type: mock
requestTemplates:
application/json: |
{
"statusCode" : 200
}
responses:
"default":
statusCode: "200"
responseParameters: # CORS Headers
method.response.header.Access-Control-Allow-Headers : "'Content-Type,X-Amz-Date,Authorization,X-Api-Key'"
method.response.header.Access-Control-Allow-Methods : "'*'"
method.response.header.Access-Control-Allow-Origin : "'*'"
responseTemplates:
application/json: |
{}
responses:
200:
description: Default response for CORS method
headers:
Access-Control-Allow-Headers:
type: "string"
Access-Control-Allow-Methods:
type: "string"
Access-Control-Allow-Origin:
type: "string"
post:
# validation definition
x-amazon-apigateway-request-validator: body-only
parameters:
- in: body
name: requestBody
required: true
content:
application/json:
schema: # validation model
"$ref": "#/definitions/Model"
responses: # response documentation
'200':
description: Create ......
headers: # Header format for the CORS headers
Access-Control-Allow-Credentials:
type: "string"
Access-Control-Allow-Origin:
type: "string"
x-amazon-apigateway-integration:
responses:
default:
statusCode: "200"
responseParameters: # CORS Header
method.response.header.Access-Control-Allow-Credentials : "'true'"
method.response.header.Access-Control-Allow-Origin : "'*'"
uri: arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/arn:aws:lambda:${AWS::Region}:${AWS::account-id}:function:{AWS::lambda-function-name}/invocations
requestTemplates:
application/json: '{"statusCode": 202, "body": $input.body}'
passthroughBehavior: never # only accept Json Data
httpMethod: POST
type: aws
get:
security: # X-API-Key
- authorizer: []
responses:
'200':
description: ......
x-amazon-apigateway-integration:
uri: "arn:aws:apigateway:xxx:lambda:path/2015-03-31/functions/arn:aws:lambda:xxx:xxxxxxx:function:function-name/invocations"
httpMethod: POST
type: aws_proxy
definitions:
Model:
# Swagger Model with validation
securityDefinitions:
authorizer :
type : apiKey
name : x-api-key
in : header
2:覆盖现有的无服务器api:
aws apigateway put-rest-api --rest-api-id {api-id} --mode overwrite --body file://xxxx/api.yml
3:不要忘记部署新的api:
aws apigateway create-deployment --rest-api-id {api-id} --region eu-central-1 --stage-name ...