question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

AWS deployment impossible: non-alphanumeric characters not fully escaped in WebSocket routes

See original GitHub issue

AWS Lambda WebSocket routes not fully escaped in CloudFormation template

Description

When using serverless for deploying AWS Lambda functions, WebSocket routes with multiple instances of the same non-alphanumeric character result in a CloudFormation template validation error on deployment.

  1. What did you do?

Added a AWS Lambda function definition to serverless.yml with a WebSocket route with multiple dashes, like the following:

myFunction:
  handler: main.handler
  events:
    - http: POST /some-api-route
    - websocket:
        route: some-api-route
  1. What happened?

The command sls deploy fails with the message: Error: The CloudFormation template is invalid: Template format error: Resource name someDashapi-routeWebsocketsRoute is non alphanumeric.

Stack trace:

Error: The CloudFormation template is invalid: Template format error: Resource name someDashapi-routeWebsocketsRoute is non alphanumeric.
      at provider.request.catch.error (/usr/local/lib/node_modules/serverless/lib/plugins/aws/deploy/lib/validateTemplate.js:20:13)
      at tryCatcher (/usr/local/lib/node_modules/serverless/node_modules/bluebird/js/release/util.js:16:23)
      at Promise._settlePromiseFromHandler (/usr/local/lib/node_modules/serverless/node_modules/bluebird/js/release/promise.js:547:31)
      at Promise._settlePromise (/usr/local/lib/node_modules/serverless/node_modules/bluebird/js/release/promise.js:604:18)
      at Promise._settlePromise0 (/usr/local/lib/node_modules/serverless/node_modules/bluebird/js/release/promise.js:649:10)
      at Promise._settlePromises (/usr/local/lib/node_modules/serverless/node_modules/bluebird/js/release/promise.js:725:18)
      at _drainQueueStep (/usr/local/lib/node_modules/serverless/node_modules/bluebird/js/release/async.js:93:12)
      at _drainQueue (/usr/local/lib/node_modules/serverless/node_modules/bluebird/js/release/async.js:86:9)
      at Async._drainQueues (/usr/local/lib/node_modules/serverless/node_modules/bluebird/js/release/async.js:102:5)
      at Immediate.Async.drainQueues (/usr/local/lib/node_modules/serverless/node_modules/bluebird/js/release/async.js:15:14)
      at runCallback (timers.js:794:20)
      at tryOnImmediate (timers.js:752:5)
      at processImmediate [as _immediateCallback] (timers.js:729:5)

This template works when running locally with the serverless offline plugin.

  1. What should’ve happened?

The deployment should have run successfully.

  1. What’s the content of your serverless.yml file?
service: my-service

provider:
  name: aws
  runtime: python3.6
  stage: dev
  region: eu-west-1
  deploymentBucket:
    name: deploymentBucket
  websocketsApiRouteSelectionExpression: $request.body.action

functions:
  myFunction:
    handler: main.handler
    events:
      - http: POST /some-api-route
      - websocket:
          route: some-api-route
  1. What’s the output you get when you use the SLS_DEBUG=* environment variable (e.g. SLS_DEBUG=* serverless deploy)
  Error --------------------------------------------------
 
  Error: The CloudFormation template is invalid: Template format error: Resource name someDashapi-routeWebsocketsRoute is non alphanumeric.
      at provider.request.catch.error (/usr/local/lib/node_modules/serverless/lib/plugins/aws/deploy/lib/validateTemplate.js:20:13)
  From previous event:
      at AwsDeploy.validateTemplate (/usr/local/lib/node_modules/serverless/lib/plugins/aws/deploy/lib/validateTemplate.js:16:85)
  From previous event:
      at AwsDeploy.BbPromise.bind.then (/usr/local/lib/node_modules/serverless/lib/plugins/aws/deploy/index.js:119:39)
  From previous event:
      at Object.aws:deploy:deploy:validateTemplate [as hook] (/usr/local/lib/node_modules/serverless/lib/plugins/aws/deploy/index.js:115:30)
      at BbPromise.reduce (/usr/local/lib/node_modules/serverless/lib/classes/PluginManager.js:490:55)
  From previous event:
      at PluginManager.invoke (/usr/local/lib/node_modules/serverless/lib/classes/PluginManager.js:490:22)
      at PluginManager.spawn (/usr/local/lib/node_modules/serverless/lib/classes/PluginManager.js:510:17)
      at AwsDeploy.BbPromise.bind.then (/usr/local/lib/node_modules/serverless/lib/plugins/aws/deploy/index.js:93:48)
  From previous event:
      at Object.deploy:deploy [as hook] (/usr/local/lib/node_modules/serverless/lib/plugins/aws/deploy/index.js:89:30)
      at BbPromise.reduce (/usr/local/lib/node_modules/serverless/lib/classes/PluginManager.js:490:55)
  From previous event:
      at PluginManager.invoke (/usr/local/lib/node_modules/serverless/lib/classes/PluginManager.js:490:22)
      at getHooks.reduce.then (/usr/local/lib/node_modules/serverless/lib/classes/PluginManager.js:525:24)
  From previous event:
      at PluginManager.run (/usr/local/lib/node_modules/serverless/lib/classes/PluginManager.js:525:8)
      at variables.populateService.then (/usr/local/lib/node_modules/serverless/lib/Serverless.js:133:33)
      at runCallback (timers.js:794:20)
      at tryOnImmediate (timers.js:752:5)
      at processImmediate [as _immediateCallback] (timers.js:729:5)
  From previous event:
      at Serverless.run (/usr/local/lib/node_modules/serverless/lib/Serverless.js:120:74)
      at serverless.init.then (/usr/local/lib/node_modules/serverless/bin/serverless.js:75:30)
      at /usr/local/lib/node_modules/serverless/node_modules/graceful-fs/graceful-fs.js:111:16
      at /usr/local/lib/node_modules/serverless/node_modules/graceful-fs/graceful-fs.js:45:10
      at FSReqWrap.oncomplete (fs.js:135:15)
  From previous event:
      at initializeErrorReporter.then (/usr/local/lib/node_modules/serverless/bin/serverless.js:75:8)
      at runCallback (timers.js:794:20)
      at tryOnImmediate (timers.js:752:5)
      at processImmediate [as _immediateCallback] (timers.js:729:5)
  From previous event:
      at Object.<anonymous> (/usr/local/lib/node_modules/serverless/bin/serverless.js:64:4)
      at Module._compile (module.js:652:30)
      at Object.Module._extensions..js (module.js:663:10)
      at Module.load (module.js:565:32)
      at tryModuleLoad (module.js:505:12)
      at Function.Module._load (module.js:497:3)
      at Function.Module.runMain (module.js:693:10)
      at startup (bootstrap_node.js:188:16)
      at bootstrap_node.js:609:3
 
  Get Support --------------------------------------------
     Docs:          docs.serverless.com
     Bugs:          github.com/serverless/serverless/issues
     Issues:        forum.serverless.com
 
  Your Environment Information ---------------------------
     Operating System:          linux
     Node Version:              8.10.0
     Framework Version:         1.60.5
     Plugin Version:            3.2.7
     SDK Version:               2.2.1
     Components Core Version:   1.1.2
     Components CLI Version:    1.4.0

Suggested Potential Fix

The following code in lib/plugins/aws/lib/naming.js appears to be the culprit:

getNormalizedWebsocketsRouteKey(route) {
    return route
      .replace('$', 'S') // dollar sign
      .replace('/', 'Slash')
      .replace('-', 'Dash')
      .replace('_', 'Underscore')
      .replace('.', 'Period');
  },

Proposed change:

getNormalizedWebsocketsRouteKey(route) {
    return route
      .replace(/\$/g, 'S') // dollar sign
      .replace(/\//g, 'Slash')
      .replace(/-/g, 'Dash')
      .replace(/_/g, 'Underscore')
      .replace(/\./g, 'Period');
  },

Proposed unit tests (lib/plugins/aws/lib/naming.test.js), under the describe('#getNormalizedWebsocketsRouteKey()') section at line 252:

it('converts multiple `-` correctly', () => {
    expect(sdk.naming.getNormalizedWebsocketsRouteKey('a-longer-path')).to.equal('aDashlongerDashpath');
});

it('converts multiple `-` and `_` correctly', () => {
    expect(sdk.naming.getNormalizedWebsocketsRouteKey('a-long_er-path_still')).to.equal('aDashlongUnderscoreerDashpathUnderscorestill');
});

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Comments:7 (7 by maintainers)

github_iconTop GitHub Comments

1reaction
tom-marshcommented, Feb 5, 2020

Apologies for the delay, see above for the pull request.

1reaction
medikoocommented, Jan 15, 2020

@tom-marsh indeed normalization logic is broken as you point (sorry I missed your point in initial description).

PR that fixes that is definitely welcome!

Read more comments on GitHub >

github_iconTop Results From Across the Web

Amazon API Gateway important notes
Amazon API Gateway important notes for REST APIs · Path segments can only contain alphanumeric characters, underscores, hyphens, periods, commas, colons, and ...
Read more >
Troubleshooting - Harness.io Docs
This error occurs when you are testing a Harness AWS Cloud Provider and the credentials used for the connection do not include a...
Read more >
Integrate LDAP with GitLab
If the user is no longer active in LDAP, they are placed in an ldap_blocked status and are signed out. They are unable...
Read more >
Configuration - NGINX Unit
Possible alternatives: Application: applications/qwk2mart; PHP target or Python target: applications/myapp/section; Route: routes/route66 , ...
Read more >
SAP BTP Connectivity
Using SAP BTP, you subscribe to or deploy your own applications. ... For cloud to on-premise solutions there are no port limitations.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found