Serverless-offline: Websocket won't connect using serverless-offline locally, but will work when deployed to aws

Created on 16 Sep 2019  路  20Comments  路  Source: dherault/serverless-offline

This is the follow-up on https://github.com/dherault/serverless-offline/issues/809

_re: forgot to mention, you get the header information on connect only with the latest v6 alpha._(dnalborczyk)

Ask: Can I use any non-alpha version of offline and still get the websocket working? A non-alpha version of offline would be much better received by my organization. I was under the impression that the x-api-key header was required because my api is defined as private in my serverless.yml. Is there any config I could use to make the websockets work without using an alpha? If so what would be my constraints? I am happy to have limited features if it makes things work. I know wss isn't supported. What if I turn off auth or mark the interface as public? Do I have any non-alpha options for websockets in the short term? If so, is there an example project that works out there that you can point me to?

question

Most helpful comment

It worked!!!
npx wscat -c ws://localhost:3001
connected (press CTRL+C to quit)

All 20 comments

Ask: Can I use any non-alpha version of offline and still get the websocket working?

yes, websockets should be working in the latest v5, with some minor short comings and missing features, e.g. the mentioned missing headers on connect.

A non-alpha version of offline would be much better received by my organization.

no problem, I understand. Just want to mention that development has entirely switched to v6 and at this point only PRs from contributors are being merged and released in v5. that being said, if you want any features, which exist in v6, you can still pull the code out of master and do a PR. Keep in mind that master (v6) is quite a big rewrite/refactor from v5.

I was under the impression that the x-api-key header was required because my api is defined as private in my serverless.yml.

probably so, could be a bug. do you specify the http-routes or the websocket-routes as private?

Is there any config I could use to make the websockets work without using an alpha? If so what would be my constraints?

everything should more or less work. some bugs have been fixed in v6, some more fixes are in the pipeline. if I remember correctly some return values, errors, http codes etc. might be not correct, and, of course, there might be more bugs. If you find any, please provide feedback!

I am happy to have limited features if it makes things work. I know wss isn't supported. What if I turn off auth or mark the interface as public?

auth is also not yet implemented, but we have a pending PR from @computerpunc which will be merged into master.

Do I have any non-alpha options for websockets in the short term? If so, is there an example project that works out there that you can point me to?

we intend to add some examples to the examples folder. but, as everything else, it's a work-in-progress. any examples you find, e.g. from serverless should just work.

here is a blog post from serverless: https://serverless.com/blog/api-gateway-websockets-example (which uses this plugin: https://github.com/serverless/serverless-websockets-plugin, but it has since moved into serverless core), but you can look at the example code in there. Personally I think, the example could have been illustrated in a _much_ simpler way, without using dynamo db, e.g. with just using some simple shareable memory (e.g. elastic cache with vpc). the only thing what comes to mind is that it wouldn't have had a dynamo db event for publishing to act on, as well as that vpc instantiation was _incredibly_ slow on AWS, but has been fixed since: https://aws.amazon.com/blogs/compute/announcing-improved-vpc-networking-for-aws-lambda-functions/

your serverless.yml looked correct, is it still not working with the port change?

Wow! The details above are very much appreciated.

As for as the connect after port change, no luck.
wscat -c ws://localhost:3001
error: connect ECONNREFUSED 127.0.0.1:3001

...from my package.json
"serverless-offline": "^5.11.0",
"serverless-offline-assume-role": "^1.0.0",
"serverless-offline-ssm": "^1.1.0",

no problem!

you might have to check your local firewall settings, or something similar along those lines. you can also try another port with websocketPort.

if you still don't get any results could you create a small simple repro repository I could have a look at?

I have tried specifying the websockets port, but I will try again. Yes, thats a good idea to do a separate project that is shareable. It will probably be tomorrow evening.

Just for fun, this is the output when the service starts up locally:
[offline] connectionHandler runtime nodejs10.x

Serverless: Routes for connectionHandler:
Serverless: (none)
Serverless: (none)
[offline] funOptions {
"funName": "defaultHandler",
"handlerName": "defaultHandler",
"handlerPath": "/Users/darndt/lms-ui/apps/server/.webpack/service/src/websocket/index",
"funTimeout": 30000,
"runtime": "nodejs10.x"
}

[offline] defaultHandler runtime nodejs10.x
Serverless: Routes for defaultHandler:
Serverless: (none)
[offline] funOptions {
"funName": "sendMessageHandler",
"handlerName": "sendMessageHandler",
"handlerPath": "/Users/darndt/lms-ui/apps/server/.webpack/service/src/websocket/index",
"funTimeout": 30000,
"runtime": "nodejs10.x"
}

[offline] sendMessageHandler runtime nodejs10.x
Serverless: Routes for sendMessageHandler:
Serverless: (none)
[offline] funOptions {
"funName": "registerApplicationListenHandler",
"handlerName": "registerApplicationListenHandler",
"handlerPath": "/Users/darndt/lms-ui/apps/server/.webpack/service/src/websocket/index",
"funTimeout": 30000,
"runtime": "nodejs10.x"
}

[offline] registerApplicationListenHandler runtime nodejs10.x
Serverless: Routes for registerApplicationListenHandler:
Serverless: (none)
[offline] funOptions {
"funName": "echoMessageHandler",
"handlerName": "echoMessageHandler",
"handlerPath": "/Users/darndt/lms-ui/apps/server/.webpack/service/src/websocket/index",
"funTimeout": 30000,
"runtime": "nodejs10.x"
}

[offline] echoMessageHandler runtime nodejs10.x
Serverless: Routes for echoMessageHandler:
Serverless: (none)

Serverless: Offline listening on http://localhost:3000

since you are using webpack, there was a problem I remember: https://github.com/dherault/serverless-offline/pull/763 but I don't think it's related.

out of curiousity, could you also try the v6 release? npm i serverless-offline@next --save-dev.
you can revert back to v5 with npm i serverless-offline@latest --save-dev.

I just gave v6 a try. When I go up to v6 it errors when starting: _Cannot find module '@hapi/hoek/lib/assert'._ I am not sure that error doesn't happen on any of the 5.x versions, but it doesn't. So alas, I can't get far enough to try a test on v6.

If I could get this working, it would open up a whole world of options around websockets we don't have today. We have to push to AWS to really test anything websocket-ity. Thanks again for your willingness to help me at least get bootstrapped on websockets.

I just gave v6 a try. When I go up to v6 it errors when starting: _Cannot find module '@hapi/hoek/lib/assert'._ I am not sure that error doesn't happen on any of the 5.x versions, but it doesn't. So alas, I can't get far enough to try a test on v6.

this is even weirder. you might wanna wipe your node-modules, and re-install from scratch, either with npm ci or whichever the equivalent for yarn would be.

btw, which node.js version and OS are you using?

I deleted the node_modules directory altogether and also removed the yarn.lock file.
nvm current: v10.13.0
macOS Mojave (10.14)

alright, give me a second. now I'm curious. maybe it's a problem with webpack, although it shouldn't. btw, it's recommended that offline is being loaded last, after the webpack plugin. not sure if that wuld make a difference.

ok, try this. this is an absolute bare bone. no additional plugins, no webpack, nothing.

# serverless.yml
service: dev-websocket

plugins:
  - serverless-offline

provider:
  memorySize: 128
  name: aws
  region: us-east-1 # default
  runtime: nodejs10.x
  stage: dev
  versionFunctions: false

functions:
  connect:
    events:
      - websocket:
          route: $connect
    handler: handler.connect
// handler.js
exports.connect = async function connect() {
  console.log("connected!");
}
// package.json
{
  "name": "test",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "dependencies": {
    "serverless": "^1.52.0",
    "serverless-offline": "^5.11.0"
  }
}

npx serverless offline start

in another shell:
npx wscat -c ws://localhost:3001

It looks like it's last to me. Did you see something in one of my post that made you think of that? It would be really nice if it was the plugin order.

This is the plugins section

plugins:

  • serverless-webpack
  • serverless-offline-ssm
  • serverless-offline

It looks like it's last to me. Did you see something in one of my post that made you think of that? It would be really nice if it was the plugin order.

from this issue: https://github.com/dherault/serverless-offline/issues/809#issue-493535865 but I don't think that's the issue.

I am trying your sample. I hope it works. If it does, that means it is yet another fight to find out what webpack is doing. ugh...

It worked!!!
npx wscat -c ws://localhost:3001
connected (press CTRL+C to quit)

The last line of output from the startup actually says, _heh there is a websocket available_. I have never seen that when my project starts. WooHoo! progress!

$ npx serverless offline start
Serverless: Starting Offline: dev/us-east-1.

Serverless: Routes for connect:
WebSocket support in serverless-offline is experimental.
For any bugs, missing features or other feedback file an issue at https://github.com/dherault/serverless-offline/issues
Error: Serverless-offline: handler for 'connect' is not a function: Error while loading connect
Serverless: POST /{apiVersion}/functions/dev-websocket-dev-connect/invocations

Serverless: Offline [HTTP] listening on http://localhost:3000
Serverless: Enter "rp" to replay the last request

Serverless: Offline [websocket] listening on ws://localhost:3001

that's great!

just include/exclude stuff and rule stuff out till you find the problem. could be anything that's different, yarn, global/local install, bad state of node_modules, [combination of] other plugins, webpack, etc.

there could be also a problem with this plugin, or when used together with other plugins.

let me know what the issue was when you find it.

yep, you proved 5.11 works like a champ. I will let you know when I finally dig to the bottom. I can't thank you enough man.

Ok, matching your versions of serverless and serverless-offline as well as me taking more care to delete everything (our project has two yarn workspaces) so I had to delete the shared stuff and the stuff in my workspace. yes!!! You rock the free world man!

馃槃 thanks! great to hear it's working for you!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

stonebraker picture stonebraker  路  3Comments

Dong9769 picture Dong9769  路  4Comments

JimLynchCodes picture JimLynchCodes  路  4Comments

dnalborczyk picture dnalborczyk  路  3Comments

jormaechea picture jormaechea  路  4Comments