在无服务器框架中使用 Swagger API 验证
Use Swagger API validation with Serverless Framework
我想向无服务器 aws-nodes 模板添加一个 api 验证,到目前为止我测试过的任何东西都运行良好。
我目前的方法是用包含我的验证模型的 yml/json swagger 定义覆盖由无服务器框架生成的现有 api-gateway。当我在 API-Gateway UI 中测试它时,这对我有用,但在外部请求时,api 不验证对 lambda 代理的请求。
当我使用普通的 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
我的 api 定义来自我的 serverless.yml
functions:
create:
handler: feedback/create.create
events:
- http:
path: feedback
method: post
list:
handler: feedback/list.list
events:
- http:
path: feedback
method: get
the lambda functions only read/write feedback from/to an DynamoDB
有人知道如何在不使用小插件 (serverless-reqvalidator-plugin) 的情况下向我的无服务器项目添加某种 api 验证,或者如何解决数据转换问题吗?
好的,验证适用于内部测试但不适用于外部请求的问题的解决方案非常明显。我忘了部署新的 api-definition。
aws apigateway create-deployment --rest-api-id {api-id} --stage-name dev
我也改变了我的API-definition。我现在整合到我的 Post 请求一个正常的 lambda。这是唯一的方法,我可以确保只有 json 内容得到验证,然后传递给 lamda 函数。因为我没有使用 lambda-proxy 请求事件从 api-gateway 转换而来,所以我必须定义一个请求模板,将整个请求 body 放在一个新请求中。
requestTemplates:
application/json: '{"statusCode": 202, "body": $input.body}'
通过这种方式,我还使用 Cors headers 将 lambda 响应转换为预定义的 api 响应。
最后我的解决方案是:
1:写个招摇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 ...
我想向无服务器 aws-nodes 模板添加一个 api 验证,到目前为止我测试过的任何东西都运行良好。
我目前的方法是用包含我的验证模型的 yml/json swagger 定义覆盖由无服务器框架生成的现有 api-gateway。当我在 API-Gateway UI 中测试它时,这对我有用,但在外部请求时,api 不验证对 lambda 代理的请求。
当我使用普通的 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
我的 api 定义来自我的 serverless.yml
functions:
create:
handler: feedback/create.create
events:
- http:
path: feedback
method: post
list:
handler: feedback/list.list
events:
- http:
path: feedback
method: get
the lambda functions only read/write feedback from/to an DynamoDB
有人知道如何在不使用小插件 (serverless-reqvalidator-plugin) 的情况下向我的无服务器项目添加某种 api 验证,或者如何解决数据转换问题吗?
好的,验证适用于内部测试但不适用于外部请求的问题的解决方案非常明显。我忘了部署新的 api-definition。
aws apigateway create-deployment --rest-api-id {api-id} --stage-name dev
我也改变了我的API-definition。我现在整合到我的 Post 请求一个正常的 lambda。这是唯一的方法,我可以确保只有 json 内容得到验证,然后传递给 lamda 函数。因为我没有使用 lambda-proxy 请求事件从 api-gateway 转换而来,所以我必须定义一个请求模板,将整个请求 body 放在一个新请求中。
requestTemplates:
application/json: '{"statusCode": 202, "body": $input.body}'
通过这种方式,我还使用 Cors headers 将 lambda 响应转换为预定义的 api 响应。
最后我的解决方案是:
1:写个招摇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 ...