DianaIonita / serverless-api-gateway-caching

A plugin for the Serverless framework which helps with configuring caching for API Gateway endpoints.
ISC License
136 stars 35 forks source link

Add multiple caching keys (method.response.body and others) #65

Closed BorjaMacedo closed 3 years ago

BorjaMacedo commented 4 years ago

Hi! The limitations of the cache keys are produced by this piece of code:

for (let cacheKeyParameter of endpointSettings.cacheKeyParameters) {
      let existingValue = method.Properties.RequestParameters[`method.${cacheKeyParameter.name}`];
      method.Properties.RequestParameters[`method.${cacheKeyParameter.name}`] = (existingValue == null || existingValue == undefined) ? {} : existingValue;

      if (method.Properties.Integration.Type !== 'AWS_PROXY') {
        method.Properties.Integration.RequestParameters[`integration.${cacheKeyParameter.name}`] = `method.${cacheKeyParameter.name}`;
      }

      method.Properties.Integration.CacheKeyParameters.push(`method.${cacheKeyParameter.name}`);
}

In resources of type AWS::ApiGateWay::Method we have two places to define the request parameters.

Example: image

Generate...

image

As we can see, only the id is generated in the request parameters of the root. Anything else would generate an error. image

Note: As you can see to be able to use fields outside of path, querystring and header as keys we have to put them into some of those three, in this case they were entered as header fields. This should not affect the operation in any case.

DianaIonita commented 4 years ago

Hi @BorjaMacedo,

Thanks for having a look. I tried to use your code and the example provided, but I'm getting:

An error occurred: ApiGatewayMethodCatPawidVarPost - Invalid cache key parameter specified

The yaml I used:

  post-cat:
    handler: rest_api/cats/get/handler.handle
    events:
      - http:
          method: post
          path: /cat/{pawId}
          caching:
            enabled: true
            cacheKeyParameters:
              - name: integration.request.path.pawId
                value: method.request.path.pawId
              - name: integration.request.header.bodyCacheHeader
                value: method.request.body.foo

The generated CloudFormation looks like this:

"ApiGatewayMethodCatPawidVarPost": {
      "Type": "AWS::ApiGateway::Method",
      "Properties": {
        "HttpMethod": "POST",
        "RequestParameters": {
          "method.request.path.pawId": {}
        },
        "ResourceId": {
          "Ref": "ApiGatewayResourceCatPawidVar"
        },
        "RestApiId": {
          "Ref": "ApiGatewayRestApi"
        },
        "ApiKeyRequired": false,
        "AuthorizationType": "NONE",
        "Integration": {
          "IntegrationHttpMethod": "POST",
          "Type": "AWS_PROXY",
          "Uri": {
            // omitted
          },
          "CacheKeyParameters": [
            "integration.request.path.pawId",
            "integration.request.header.bodyCacheHeader"
          ],
          "RequestParameters": {},
          "CacheNamespace": "ApiGatewayMethodCatPawidVarPostCacheNS"
        },
        "MethodResponses": []
      }
    }

Maybe I'm missing something?

Edit: updated example

chris-burkhardt commented 4 years ago

Any progress being made on this PR?

DianaIonita commented 4 years ago

Hey @BorjaMacedo,

Curious to see what your thoughts are on this PR now.

Thanks, Diana

BorjaMacedo commented 4 years ago

I apologize for my delay. I think the problem is that you are trying to use the cache in a POST. Although AWS allows this, I do not usually do it and therefore do not contemplate that possibility. We would have to review this specific case and try to make an implementation for different methods of the GET.

BorjaMacedo commented 4 years ago

Hi @BorjaMacedo,

Thanks for having a look. I tried to use your code and the example provided, but I'm getting:

An error occurred: ApiGatewayMethodCatPawidVarPost - Invalid cache key parameter specified

The yaml I used:

  post-cat:
    handler: rest_api/cats/get/handler.handle
    events:
      - http:
          method: post
          path: /cat/{pawId}
          caching:
            enabled: true
            cacheKeyParameters:
              - name: integration.request.path.pawId
                value: method.request.path.pawId
              - name: integration.request.header.bodyCacheHeader
                value: method.request.body.foo

The generated CloudFormation looks like this:

"ApiGatewayMethodCatPawidVarPost": {
      "Type": "AWS::ApiGateway::Method",
      "Properties": {
        "HttpMethod": "POST",
        "RequestParameters": {
          "method.request.path.pawId": {}
        },
        "ResourceId": {
          "Ref": "ApiGatewayResourceCatPawidVar"
        },
        "RestApiId": {
          "Ref": "ApiGatewayRestApi"
        },
        "ApiKeyRequired": false,
        "AuthorizationType": "NONE",
        "Integration": {
          "IntegrationHttpMethod": "POST",
          "Type": "AWS_PROXY",
          "Uri": {
            // omitted
          },
          "CacheKeyParameters": [
            "integration.request.path.pawId",
            "integration.request.header.bodyCacheHeader"
          ],
          **"RequestParameters": {},**
          "CacheNamespace": "ApiGatewayMethodCatPawidVarPostCacheNS"
        },
        "MethodResponses": []
      }
    }

Maybe I'm missing something?

Edit: updated example

I have reviewed your case even with the post and it works correctly for me. Could you try the latest commit?

PD: I find it strange that nothing has been generated within RequestParameters into Integration because in my code it is obv that it gets it and it appears to me if I do the test with POST.

DianaIonita commented 4 years ago

Hi @BorjaMacedo

Thanks for having another look. I tried running this again and I'm getting the same error:

Serverless Error ---------------------------------------

  An error occurred: ApiGatewayMethodCatPawidVarPost - Invalid cache key parameter specified

Here's my configuration:

custom:
  apiGatewayCaching:
    enabled: true

functions:
  post-cat:
    handler: rest_api/cats/get/handler.handle
    events:
      - http:
          method: post
          path: /cat/{pawId}
          caching:
            enabled: true
            cacheKeyParameters:
              - name: integration.request.path.pawId
                value: method.request.path.pawId
              - name: integration.request.header.someHeader
                value: context.authorizer.principalId
              - name: integration.request.header.bodyCacheHeader
                value: method.request.body.foo

And here's what was generated in the CloudFormation template:

"ApiGatewayMethodCatPawidVarPost": {
      "Type": "AWS::ApiGateway::Method",
      "Properties": {
        "HttpMethod": "POST",
        "RequestParameters": {
          "method.request.path.pawId": {}
        },
        "ResourceId": {
          "Ref": "ApiGatewayResourceCatPawidVar"
        },
        "RestApiId": {
          "Ref": "ApiGatewayRestApi"
        },
        "ApiKeyRequired": false,
        "AuthorizationType": "NONE",
        "Integration": {
          "IntegrationHttpMethod": "POST",
          "Type": "AWS_PROXY",
          "Uri": "OMITTED",
          "CacheKeyParameters": [
            "integration.request.path.pawId",
            "integration.request.header.someHeader",
            "integration.request.header.bodyCacheHeader"
          ],
          "RequestParameters": {},
          "CacheNamespace": "ApiGatewayMethodCatPawidVarPostCacheNS"
        },
        "MethodResponses": []
      }
    }
DianaIonita commented 3 years ago

Hi @BorjaMacedo,

I think what was missing from my configuration was integration: lambda, which was spotted in PR #72. I merged that in and released version 1.5.0.

Thank you for your help!