Repository: serverless/serverless (JavaScript)
Date: 2016-11-26 00:55:58+00:00
Task type: Bug Fix

Issue:
v1.2.1 introduces a bug with HTTP event Request Parameters
# This is a Bug Report

## Description

For bug reports:
* What went wrong?

When doing a `sls deploy`, the following error occurs:

```
............................Serverless: Deployment failed!

  Serverless Error ---------------------------------------

     An error occurred while provisioning your stack: ApiGatewayMethodBroadcastIdVarGet
     - Invalid mapping expression specified: Validation Result:
     warnings : [], errors : [Invalid mapping expression
     specified: paths].

  Get Support --------------------------------------------
     Docs:          docs.serverless.com
     Bugs:          github.com/serverless/serverless/issues

  Your Environment Information -----------------------------
     OS:                 darwin
     Node Version:       6.5.0
     Serverless Version: 1.2.0
```

* What did you expect should have happened?

When I use Serverless 1.1.0, it works as expected.

* What was the config you used?

The relavant part of the config file is:

```yaml
functions:
  http:
    name: ${self:custom.${env:PROG_ENV}.name.lower}-http
    handler: handlers.http_handler
    timeout: 5
    events:
      - http:
          method: get
          path: resource/{id}
          request:
            parameters:
              paths:
                id: true
          cors:
            origins:
              - '*'
            headers:
              - Content-Type
              - Authorization
              - Accept
              - X-Amz-Date
              - X-Api-Key
              - X-Amz-Security-Token
              - x-secret
```

* What stacktrace or error message from your provider did you see?

    Invalid mapping expression specified: paths

## Additional Data

I also tested this with v1.2.0 and the issue happens there too. So I am going to stick with 1.1.0 until this get resolved.

If there is anything I can do to help, please let me know.


Issue discussion:
I've found the cause.

When you do an `sls deploy --noDeploy` I expect you should see:

```
Serverless: Warning! You're using the LAMBDA-PROXY in combination with request / response configuration in your function "http". This configuration will be ignored during deployment.
```

It's not actually 'ignoring' the configuration, but what it is doing is *not* parsing the configuration. So the un-transformed "parameters" object is being passed through

So if you

`cat .serverless/cloudformation-template-update-stack.json` you should see:

```json
"ApiGatewayMethodResourceIdVarGet": {
      "Type": "AWS::ApiGateway::Method",
      "Properties": {
        "HttpMethod": "GET",
        "RequestParameters": {
          "paths": {
            "id": true
          }
        }
  ...
```

This is the relevant-ish line of code: https://github.com/serverless/serverless/blob/master/lib/plugins/aws/deploy/compile/events/apiGateway/lib/validate.js#L72

So, I need @pmuens or someone to advise on what's supposed to happen here. The configuration that @pas256 has in their serverless.yml is said to be ignored, so we could just `delete http.request` (and `delete http.response`) - but this issue sort of implies people are ignoring that warning and expecting that configuration to set up api gateway for some reason, even though they're using proxy integration and I suspect that there might be value in that.

So, TL;DR is: I introduced a bug, it's a two line fix, but I'm not sure that once fixed, users will be getting the results they expect.



Solution patch:
diff --git a/lib/plugins/aws/deploy/compile/events/apiGateway/lib/validate.js b/lib/plugins/aws/deploy/compile/events/apiGateway/lib/validate.js
index 9c974f3da65..033bdce1410 100644
--- a/lib/plugins/aws/deploy/compile/events/apiGateway/lib/validate.js
+++ b/lib/plugins/aws/deploy/compile/events/apiGateway/lib/validate.js
@@ -62,7 +62,7 @@ module.exports = {
             corsPreflight[http.path] = cors;
           }
 
-          http.integration = this.getIntegration(http);
+          http.integration = this.getIntegration(http, functionName);
 
           if (http.integration === 'AWS') {
             if (http.request) {
@@ -98,9 +98,12 @@ module.exports = {
               const warningMessage = [
                 'Warning! You\'re using the LAMBDA-PROXY in combination with request / response',
                 ` configuration in your function "${functionName}".`,
-                ' This configuration will be ignored during deployment.',
+                ' Serverless will remove this configuration automatically before deployment.',
               ].join('');
               this.serverless.cli.log(warningMessage);
+
+              delete http.request;
+              delete http.response;
             }
           }
 
@@ -277,7 +280,7 @@ module.exports = {
     return cors;
   },
 
-  getIntegration(http) {
+  getIntegration(http, functionName) {
     if (http.integration) {
       const allowedIntegrations = [
         'LAMBDA-PROXY', 'LAMBDA',
@@ -288,7 +291,7 @@ module.exports = {
       if (allowedIntegrations.indexOf(normalizedIntegration) === NOT_FOUND) {
         const errorMessage = [
           `Invalid APIG integration "${http.integration}"`,
-          ` in function "${http.functionName}".`,
+          ` in function "${functionName}".`,
           ' Supported integrations are: lambda, lambda-proxy.',
         ].join('');
         throw new this.serverless.classes.Error(errorMessage);


Test patch:
diff --git a/lib/plugins/aws/deploy/compile/events/apiGateway/lib/validate.test.js b/lib/plugins/aws/deploy/compile/events/apiGateway/lib/validate.test.js
index 5d67839bb01..8a21ad4008d 100644
--- a/lib/plugins/aws/deploy/compile/events/apiGateway/lib/validate.test.js
+++ b/lib/plugins/aws/deploy/compile/events/apiGateway/lib/validate.test.js
@@ -1038,6 +1038,38 @@ describe('#validate()', () => {
     expect(logStub.args[0][0].length).to.be.at.least(1);
   });
 
+  it('should remove request/response config with LAMBDA-PROXY', () => {
+    awsCompileApigEvents.serverless.service.functions = {
+      first: {
+        events: [
+          {
+            http: {
+              method: 'GET',
+              path: 'users/list',
+              integration: 'lambda-proxy',
+              request: {
+                template: {
+                  'template/1': '{ "stage" : "$context.stage" }',
+                },
+              },
+              response: {},
+            },
+          },
+        ],
+      },
+    };
+    // initialize so we get the log method from the CLI in place
+    serverless.init();
+
+    // don't want to print the logs in this test
+    sinon.stub(serverless.cli, 'log');
+
+    const validated = awsCompileApigEvents.validate();
+    expect(validated.events).to.be.an('Array').with.length(1);
+    expect(validated.events[0].http.request).to.equal(undefined);
+    expect(validated.events[0].http.response).to.equal(undefined);
+  });
+
   it('should throw an error when an invalid integration type was provided', () => {
     awsCompileApigEvents.serverless.service.functions = {
       first: {