aws-apigateway-importer icon indicating copy to clipboard operation
aws-apigateway-importer copied to clipboard

“Invalid mapping expression specified” when specifying an integration response header

Open aviflax opened this issue 9 years ago • 19 comments

I’m using RAML. When I specify an integration response header in my config JSON file, like so:

"^401.*": {
    "statusCode": "401",
    "responseParameters": {
        "method.response.header.WWW-Authenticate": "'realm=\"Pegged Web API\"'"
    },
    "responseTemplates": { "application/json": "{\"message\": $input.json('$.errorMessage')}" }
}

I get this error when running the importer:

2015-12-09 18:19:22,638 INFO - Creating integration with type AWS
2015-12-09 18:19:22,923 ERROR - Error creating API, rolling back
com.amazonaws.services.apigateway.model.BadRequestException: Invalid mapping expression specified: Validation Result: warnings : [], errors : [No method response exists for method.] (Service: null; Status Code: 400; Error Code: null; Request ID: 48738c76-9ecb-11e5-a89f-69a422b3b5fa)
    at com.amazonaws.http.AmazonHttpClient.handleErrorResponse(AmazonHttpClient.java:1275)
    at com.amazonaws.http.AmazonHttpClient.executeOneRequest(AmazonHttpClient.java:873)
    at com.amazonaws.http.AmazonHttpClient.executeHelper(AmazonHttpClient.java:576)
    at com.amazonaws.http.AmazonHttpClient.doExecute(AmazonHttpClient.java:362)
    at com.amazonaws.http.AmazonHttpClient.executeWithTimer(AmazonHttpClient.java:328)
    at com.amazonaws.http.AmazonHttpClient.execute(AmazonHttpClient.java:307)
    at com.amazonaws.hal.client.HalClient.invoke(HalClient.java:235)
    at com.amazonaws.hal.client.HalClient.putResource(HalClient.java:122)
    at com.amazonaws.hal.client.HalResourceInvocationHandler.invoke(HalResourceInvocationHandler.java:125)
    at com.sun.proxy.$Proxy32.putIntegrationResponse(Unknown Source)
    at com.amazonaws.service.apigateway.importer.impl.sdk.ApiGatewaySdkRamlApiImporter.createIntegrationResponses(ApiGatewaySdkRamlApiImporter.java:332)
    at com.amazonaws.service.apigateway.importer.impl.sdk.ApiGatewaySdkRamlApiImporter.createIntegration(ApiGatewaySdkRamlApiImporter.java:305)
    at com.amazonaws.service.apigateway.importer.impl.sdk.ApiGatewaySdkRamlApiImporter.createMethod(ApiGatewaySdkRamlApiImporter.java:256)
    at com.amazonaws.service.apigateway.importer.impl.sdk.ApiGatewaySdkRamlApiImporter.createMethods(ApiGatewaySdkRamlApiImporter.java:180)
    at com.amazonaws.service.apigateway.importer.impl.sdk.ApiGatewaySdkRamlApiImporter.createResources(ApiGatewaySdkRamlApiImporter.java:149)
    at com.amazonaws.service.apigateway.importer.impl.sdk.ApiGatewaySdkRamlApiImporter.createApi(ApiGatewaySdkRamlApiImporter.java:83)
    at com.amazonaws.service.apigateway.importer.impl.ApiGatewayRamlFileImporter.importApi(ApiGatewayRamlFileImporter.java:49)
    at com.amazonaws.service.apigateway.importer.ApiImporterMain.importRaml(ApiImporterMain.java:171)
    at com.amazonaws.service.apigateway.importer.ApiImporterMain.execute(ApiImporterMain.java:141)
    at com.amazonaws.service.apigateway.importer.ApiImporterMain.main(ApiImporterMain.java:83)

I’ve confirmed that if I remove responseParameters from the object above, the importer runs successfully with no errors.

I’m confused as to what’s going on here; whether I’m doing something wrong or what… because when I specify such a response header manually in the console, it succeeds just fine. And the result of doing so manually:

$ aws apigateway get-integration --rest-api-id 59r3v8xeoh --resource-id yvazbs --http-method GET
{
    "integrationResponses": {
        "200": {
            "responseTemplates": {
                "application/json": "$input.json('$.body')\n"
            }, 
            "selectionPattern": "^$", 
            "statusCode": "200"
        }, 
        "401": {
            "responseParameters": {
                "method.response.header.WWW-Authenticate": "'realm=\"Pegged Web API\"'"
            }, 
            "selectionPattern": "^401.*", 
            "responseTemplates": {
                "application/json": "{\"message\": $input.json('$.errorMessage')}"
            }, 
            "statusCode": "401"
        }
    },
...

as you can see, the responseParameters property is identical… so I’m just confused!

Any help would be greatly appreciated!

Thanks, Avi

aviflax avatar Dec 09 '15 23:12 aviflax

:+1: - Getting the same issue.

spencerfdavis avatar Dec 10 '15 18:12 spencerfdavis

The error message "No method response exists for method" usually means that you don't have a method response defined matching the status code (in this case 401).

Here's an example: https://github.com/awslabs/aws-apigateway-importer/blob/master/tst/resources/raml/apigateway.raml#L205

If you're still having issues send along your raml file and I'll take a look

rpgreen avatar Dec 10 '15 19:12 rpgreen

The error message "No method response exists for method" usually means that you don't have a method response defined matching the status code (in this case 401).

Yup, I get that, but I don’t think that’s what’s going on here. When I remove the responseParameters property from the 401 integration response in the JSON file, the 401 integration response is successfully created. So it seems I have properly specified the 401 response in my RAML. There seems to be something specifically about my responseParameters values that the importer doesn’t like, or is mishandling. I’m not sure what, because I can successfully set the same values via the console.

aviflax avatar Dec 10 '15 20:12 aviflax

Can you send a sample swagger file so that we can reproduce the issue?

rpgreen avatar Dec 10 '15 23:12 rpgreen

I can send it by email… if would that be acceptable, please shoot me a short note at [email protected] and I’ll supply it. Thanks!

aviflax avatar Dec 14 '15 18:12 aviflax

Hi,

You do need to have headers defined in your method response before they are defined in the integration response. Could that be the case here?

Was the CLI command you ran was on the same resource/method or a different one that you created?

I'm wondering if the error message is wrong since you're saying that removing the responseParameters field fixes the issue.

Jack

jackrk avatar Dec 15 '15 02:12 jackrk

You do need to have headers defined in your method response before they are defined in the integration response. Could that be the case here?

No, they’re defined properly in my RAML file.

Was the CLI command you ran was on the same resource/method or a different one that you created?

I guess you’re referring to the case wherein I was able to successfully add this response parameter mapping manually — but in this case I used the console, not the CLI.

I'm wondering if the error message is wrong since you're saying that removing the responseParameters field fixes the issue.

Seems plausible, I don’t know.

aviflax avatar Dec 29 '15 00:12 aviflax

@aviflax I apologize that you still have this issue. We found a bug in the RAML Importer which highlighted in code (https://github.com/awslabs/aws-apigateway-importer/blob/master/src/com/amazonaws/service/apigateway/importer/impl/sdk/ApiGatewaySdkRamlApiImporter.java#L256). It should create method response before creating the integration responses which is associated to the method response. We will prioritize to fix this issue.

We appreciate that you are reporting this bug.

kahouieong avatar Dec 29 '15 23:12 kahouieong

@kaieongataws ah, I’m glad you figured it out! Thank you!

aviflax avatar Dec 30 '15 00:12 aviflax

@blakeembrey can you have a look? @kaieongataws is correct in that the method responses should be created before the integration response. I'm not sure if this is a new regression.

Also I noticed that API key support is not implemented for RAML

rpgreen avatar Dec 31 '15 23:12 rpgreen

can you have a look?

Seems correct to me, it's likely I wrote this out of order and didn't know that limitation - is it as easy as switching the order or is it more involved than I suspect?

Also I noticed that API key support is not implemented for RAML

There isn't a way in RAML 0.8 to specify API key support, it only describes custom scheme types using x- (https://github.com/raml-org/raml-spec/blob/master/raml-0.8.md#type-1). Since x-{other} could technically describe anything, I omitted it - if it's needed I could co-opt a specific name and use the first describedBy header parameter for API key support. I believe RAML 1.0 can work around this with the "Pass Through" type, which provides a runtime guarantee that the property is actually passed through as described (such as "API key"). Maybe that's overcomplicated, so let me know if I confused anyone else.

blakeembrey avatar Jan 05 '16 23:01 blakeembrey

I am getting the same issue, using swagger.json file. Full file below. I even get the error if I use exact responses object in the README.md, so there must be a regression bug someplace.

FWIW I'm using APIG-importer because its such a PITA to set response headers in the UI, so this is a blocker for me.

{
  "swagger": "2.0",
  "info": {
    "title": "MY Customer API",
    "description": "Allow clients to access a subset of our APIs",
    "version": "1.0.0"
  },
  "host": "ws.myhost.com",
  "schemes": [
    "https"
  ],
  "consumes": [
    "application/json"
  ],
  "produces": [
    "application/json"
  ],
  "security": [
    {
      "api_key": []
    }
  ],
  "securityDefinitions": {
    "api_key": {
      "type": "apiKey",
      "name": "x-api-key",
      "in": "header"
    }
  },
  "paths": {
    "/apps/1/get-apps": {
      "get": {
        "summary": "Get a list of your company’s apps",
        "description": "Get a list of your company’s apps",
        "tags": [
          "my-apps"
        ],
        "responses": {
          "400": {
            "description": "Error",
            "schema": {
              "$ref": "#/definitions/Error"
            }
          },
          "500": {
            "description": "Execution Error",
            "schema": {
              "$ref": "#/definitions/Error"
            }
          }
        },
        "security": [
          {
            "api_key": []
          }
        ],
        "x-amazon-apigateway-auth": {
          "type": "none"
        },
        "x-amazon-apigateway-integration": {
          "type": "http",
          "uri": "https://${stageVariables.WsDomain}/apps/1/test",
          "httpMethod": "GET",
          "requestParameters": {
            "integration.request.header.ex-1": "stageVariables.ex1",
            "integration.request.header.ex2": "stageVariables.ex2"
          },
          "responses": {
            "2\\d{2}": {
              "statusCode": "200",
              "responseParameters": {
                "method.response.header.Cache-Control": "integration.response.header.Cache-Control"
              }
            },
            "default": {
              "statusCode": "400"
            }
          }
        }
      }
    }
  },
  "definitions": {
    "Error": {
      "properties": {
        "error": {
          "type": "string"
        },
        "code": {
          "type": "integer",
          "format": "int32"
        },
        "server": {
          "type": "string"
        }
      }
    }
  }
}

doapp-ryanp avatar Feb 08 '16 22:02 doapp-ryanp

@doapp-ryanp Same error message but different root cause.

You're missing the referenced 200 response and the definition for the Cache-Control response header.

You'll want to add something like this to the operation responses:

                    "200" : {
                        "headers" : {
                            "Cache-Control" : {
                                "type" : "string"
                            }
                        }
                    }

rpgreen avatar Feb 08 '16 23:02 rpgreen

@rpgreen thanks for the quick response. That did indeed fix my issue.

doapp-ryanp avatar Feb 08 '16 23:02 doapp-ryanp

any updates on this, was it fixed by any chance?

clonq avatar Mar 27 '16 04:03 clonq

Swagger/OpenAPI import is now generally available in the API Gateway REST API, the AWS CLI and all AWS SDKs. You can also import and export Swagger definitions using the API Gateway console. This release addresses many of the open issues and feedback in this repository.

I would encourage you to migrate your workflow to the standard AWS tools. aws-apigateway-importer will receive minimal support from the API Gateway team going forward.

Any feedback or issues with the new importer should be directed to the official API Gateway forums.

Thanks, Ryan

rpgreen avatar Apr 06 '16 18:04 rpgreen

Thanks Ryan - this was about RAML though...

clonq avatar Apr 11 '16 23:04 clonq

Now that Swagger has been officially “blessed” by and fully integrated into API Gateway, it would seem clear that RAML is just not a high priority for the team. Next time I work on an API Gateway project I’ll probably just use Swagger, even though I prefer RAML’s semantics.

aviflax avatar Apr 12 '16 16:04 aviflax

Apologies - I've reopened this issue. To be clear, we still want to support RAML, it just hasn't made it into the service yet. If there is enough demand for RAML support we will certainly prioritize.

rpgreen avatar Apr 12 '16 16:04 rpgreen