API Gateway validate content-type header

Viewed 3557

IF the content type isn't json api gateway does no validation and just passes through. Im using the proxy integration so dont have mapping templates and can only use "when_no_match". Im using inline swagger.

I can check if the header exists but not check the value- how do I do that?

/myMethod:
    post:
        x-amazon-apigateway-request-validator : "myvalidator"
        parameters:
        # How do I also validate Content-Type value is "application/json"
        - name: Content-Type
          in: header
          required: true

I want API gateway to validate this so I dont have to check it in code

2 Answers

Go to the Integration Request tab of your endpoint, click Mapping Templates, set Request body passthrough to never, add a mapping template for application/javascript, and click Method Request Passthrough from the dropdown next to Generate template.

Here's the swagger snippet: requestTemplates: application/json: | ## See http://docs.aws.amazon.com/apigateway/latest/developerguide/api-gateway-mapping-template-reference.html ## This template will pass through all parameters including path, querystring, header, stage variables, and context through to the integration endpoint via the body/payload #set($allParams = $input.params()) { "body-json" : $input.json('$'), "params" : { #foreach($type in $allParams.keySet()) #set($params = $allParams.get($type)) "$type" : { #foreach($paramName in $params.keySet()) "$paramName" : "$util.escapeJavaScript($params.get($paramName))" #if($foreach.hasNext),#end #end } #if($foreach.hasNext),#end #end }, "stage-variables" : { #foreach($key in $stageVariables.keySet()) "$key" : "$util.escapeJavaScript($stageVariables.get($key))" #if($foreach.hasNext),#end #end }, "context" : { "account-id" : "$context.identity.accountId", "api-id" : "$context.apiId", "api-key" : "$context.identity.apiKey", "authorizer-principal-id" : "$context.authorizer.principalId", "caller" : "$context.identity.caller", "cognito-authentication-provider" : "$context.identity.cognitoAuthenticationProvider", "cognito-authentication-type" : "$context.identity.cognitoAuthenticationType", "cognito-identity-id" : "$context.identity.cognitoIdentityId", "cognito-identity-pool-id" : "$context.identity.cognitoIdentityPoolId", "http-method" : "$context.httpMethod", "stage" : "$context.stage", "source-ip" : "$context.identity.sourceIp", "user" : "$context.identity.user", "user-agent" : "$context.identity.userAgent", "user-arn" : "$context.identity.userArn", "request-id" : "$context.requestId", "resource-id" : "$context.resourceId", "resource-path" : "$context.resourcePath" } } passthroughBehavior: "never" httpMethod: "POST" type: "aws"

As I was myself also looking for the answer to this after such a long time, the only solution I found that involved the swagger/openapi spec file was using this Mapping Template (this is the shortest I could come up with):

#set($allParams = $input.params())
    {
        "body" : $input.json('$'),
        #set($pathParams = $allParams.get('path'))
        "pathParameters" : {
            #foreach($paramName in $pathParams.keySet())
                "$paramName" : "$util.escapeJavaScript($pathParams.get($paramName))"
                #if($foreach.hasNext),#end
            #end
        },
        #set($queryParams = $allParams.get('querystring'))
        "queryString" : {
            #foreach($paramName in $queryParams.keySet())
                "$paramName" : "$util.escapeJavaScript($queryParams.get($paramName))"
                #if($foreach.hasNext),#end
            #end
        }
    }

In a spec path that we want to apply it to:

  paths:
    /your-path:
      x-amazon-apigateway-integration:
        credentials: "arn:aws:iam::xxx:role/yyy"
        uri: "arn:aws:apigateway:us-east-1:lambda:path/2015-03-31/functions/arn:aws:lambda:us-east-1:zzz:function:qqq/invocations"
        responses:
          default:
            statusCode: 200
        passthroughBehavior: never
        httpMethod: POST
        requestTemplates:
          application/json: "#set($allParams = $input.params())\n        {\n     \
        \       \"body\" : $input.json('$'),\n            #set($pathParams = $allParams.get('path'))\n\
        \            \"pathParameters\" : {\n                #foreach($paramName\
        \ in $pathParams.keySet())\n                    \"$paramName\" : \"$util.escapeJavaScript($pathParams.get($paramName))\"\
        \n                    #if($foreach.hasNext),#end\n                #end\n\
        \            },\n            #set($queryParams = $allParams.get('querystring'))\n\
        \            \"queryString\" : {\n                #foreach($paramName\
        \ in $queryParams.keySet())\n                    \"$paramName\" : \"$util.escapeJavaScript($queryParams.get($paramName))\"\
        \n                    #if($foreach.hasNext),#end\n                #end\n\
        \            }\n        }"
        type: aws

Unfortunately, this is super unwieldy for me, and I just decided to use the standard Proxy Integration with the request validation set to all:

x-amazon-apigateway-request-validators: {
  all: {
    validateRequestBody: true,
    validateRequestParameters: true
  }
}
x-amazon-apigateway-request-validator: all
Related