{"id":15457549,"url":"https://github.com/stayallive/serverless-websockets","last_synced_at":"2025-04-01T10:34:51.394Z","repository":{"id":75595105,"uuid":"315461578","full_name":"stayallive/serverless-websockets","owner":"stayallive","description":"WebSockets for Serverless.","archived":false,"fork":false,"pushed_at":"2021-11-14T14:22:20.000Z","size":339,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":4,"default_branch":"main","last_synced_at":"2024-10-12T10:10:25.186Z","etag":null,"topics":["websocket-server"],"latest_commit_sha":null,"homepage":"","language":"PHP","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/stayallive.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":"stayallive"}},"created_at":"2020-11-23T23:01:21.000Z","updated_at":"2022-11-08T13:44:48.000Z","dependencies_parsed_at":"2023-06-07T01:00:32.327Z","dependency_job_id":null,"html_url":"https://github.com/stayallive/serverless-websockets","commit_stats":{"total_commits":56,"total_committers":2,"mean_commits":28.0,"dds":"0.017857142857142905","last_synced_commit":"b8c8f1ba6520f3c53699136754ff7ff8b44b2709"},"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stayallive%2Fserverless-websockets","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stayallive%2Fserverless-websockets/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stayallive%2Fserverless-websockets/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stayallive%2Fserverless-websockets/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/stayallive","download_url":"https://codeload.github.com/stayallive/serverless-websockets/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246627325,"owners_count":20808101,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["websocket-server"],"created_at":"2024-10-01T22:47:12.858Z","updated_at":"2025-04-01T10:34:51.371Z","avatar_url":"https://github.com/stayallive.png","language":"PHP","readme":"\u003ch3 align=\"center\"\u003e\n    \u003cb\u003e⚠️ Please do not use this in production yet, use it at your own risk! ⚠️\u003c/b\u003e\n\u003c/h3\u003e\n\n---\n\n# Serverless WebSockets\n\nBrings the power of WebSockets to serverless. Tries to achieve drop-in Pusher replacement.\n\nThis project is heavily inspired by [Laravel WebSockets](https://github.com/beyondcode/laravel-websockets).\n\n## Parameters\n\nThe `serverless.yml` references AWS Systems Manager Parameter Store parameters to configure the application.\n\nSet your values using the AWS CLI (or create them manually through the AWS Console):\n\n```bash\n# Set this to the region you are deploying to\nREGION=\"eu-central-1\"\n\n# You will need to set the parameter for each stage\nSTAGE=\"dev\"\n\n# Configuration that you need to share with your Pusher SDKs\naws ssm put-parameter --region $REGION --name \"/serverless-websockets/$STAGE/app-id\" --type String --value 'MY_APP_ID'\naws ssm put-parameter --region $REGION --name \"/serverless-websockets/$STAGE/app-key\" --type String --value 'MY_APP_KEY'\naws ssm put-parameter --region $REGION --name \"/serverless-websockets/$STAGE/app-secret\" --type String --value 'MY_APP_SECRET'\n\n### The parameters below are optional:\n\n# Set this to true to enable the webhook worker which sends the webhooks, set to false to disable the worker\naws ssm put-parameter --region $REGION --name \"/serverless-websockets/$STAGE/webhook-enabled\" --type String --value 'false'\n# You cannot set empty values so just not create the parameters if you don't want webhooks\naws ssm put-parameter --region $REGION --name \"/serverless-websockets/$STAGE/webhook-target\" --type String --value ''\n# Add the events you want to receive: channel_occupied,channel_vacated,member_added,member_removed,client_event\naws ssm put-parameter --region $REGION --name \"/serverless-websockets/$STAGE/webhook-events\" --type String --value ''\n\n# Set to true if you want to see how many clients are connected and how long they are connected on average\naws ssm put-parameter --region $REGION --name \"/serverless-websockets/$STAGE/write-cloudwatch-metrics\" --type String --value 'false'\n\n# Set to true if you want to allow clients to send event in authenticated channels\naws ssm put-parameter --region $REGION --name \"/serverless-websockets/$STAGE/client-events-enabled\" --type String --value 'false'\n\n# There is a little example application on /wave you can use to see if everything is working as expected\naws ssm put-parameter --region $REGION --name \"/serverless-websockets/$STAGE/wave-example-enabled\" --type String --value 'false'\n```\n\nDo not forget to re-deploy after updating the parameters.\n\n## CLI\n\nThere is a Lambda function called CLI created for each deployment, this Lambda serves a few purposes.\n\nYou can call any CLI action by executing:\n\n```bash\n# Don't forget to include --stage=\u003cstage\u003e if you want to execute it on a specific stage\nserverless invoke -f cli -d '{\"action\": \"\u003cACTION NAME\u003e\"}'\n```\n\n### One-off commands\n\n#### disconnect-all-connections\n\nExecuting this action will disconnect all currently connected clients. It will not prevent them from immediately reconnecting.\n\n### Scheduled commands\n\n#### write-cloudwatch-metrics\n\nThis action is scheduled to run every minute and is disabled by default. It writes the current amount of connectiond and the average time the currently connected clients are connected.\n\n#### cleanup-stale-connections\n\nThis action is scheduled to run every 4 hours and is enabled by default. It finds and disconnects client who are connected for over 24 hours.\n\n## Limitations\n\nThis project uses the AWS API Gateway to provide it's WebSocket connection. The limitation with using the API Gateway is that you cannot specify a WebSocket endpoint yourself, it's defined by AWS and defaults to `wss://\u003cgateway-endpoint\u003e/\u003cstage-name\u003e`. This has 2 drawbacks:\n\n- Only one application per deployment, since there is no other way to specify the application ID in the Pusher SDK except in the WebSocket url which we cannot modify\n- We need to \"message\" the Pusher JS SDK (and other SDK that handle the WebSocket connection) a bit to use the correct WebSocket endpoint\n\nAnother limitation is that we cannot respond to the initial connection from the API Gateway so we need the client to send an event so we can respond with the Pusher protocol handshake.\n\nIt's likely client SDKs (handling the WebSocket connection) needs changes to use the correct `wss` url.\n\n### Changes required for the Pusher JS SDK\n\nThis is code is tested with version `7.0.1` of the Pusher JS SDK, keep in mind that upgrading to newer Pusher JS SDK version might break this workaround.\n\n```js\n// Pusher has it's own socket URL structure that doesn't play nice with API Gateway\n// so we patch the method that generates the wss URL and return our own WebSocket URL\nPusher.Runtime.Transports.ws.hooks.urls.getInitial = () =\u003e {\n    return 'wss://YOUR_API_GATEWAY_ENDPOINT/YOUR_API_GATEWAY_STAGE_NAME';\n};\n\n// We also need to get the socket to workaround another API Gateway limitation\nconst socketRetriever = Pusher.Runtime.Transports.ws.hooks.getSocket;\n\n// We need to capture the actual WebSocket created by Pusher so we can send an initital message\nPusher.Runtime.Transports.ws.hooks.getSocket = (e) =\u003e {\n    // We let Pusher create the WebSocket\n    const socket = socketRetriever(e);\n\n    // We listen for when the WebSocket opens so we can push our connect message\n    // We don't use `socket.onopen` since Pusher SDK immeditaly wil overwrite it\n    socket.addEventListener('open', () =\u003e {\n        // Send our initial \"handshake\" event so we can respond with the Pusher handshake message\n        // without this handshake message from the server the SDK will timeout the connection and reconnect\n        socket.send(JSON.stringify({'event': 'internal:connect'}));\n    });\n\n    // Continue to let Pusher do it's thing\n    return socket;\n};\n\n// The app key can be anything since it's unused (no support for multiple apps per deployment)\nconst pusher = new Pusher('APP_KEY', {\n    forceTLS:          true,\n    enableStats:       false, // disable this since we do not accept the stats being sent\n    enabledTransports: ['ws'],\n});\n```\n\n## Security\n\nIf you discover any security related issues, please email alex@bouma.dev instead of using the issue tracker.\n\n## Credits\n\n- [Alex Bouma](https://github.com/stayallive)\n- [All Contributors](../../contributors)\n- [All Contributors of Laravel WebSockets](https://github.com/beyondcode/laravel-websockets)\n\n## License\n\nThe MIT License (MIT). Please see [License File](LICENSE.md) for more information.\n","funding_links":["https://github.com/sponsors/stayallive"],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstayallive%2Fserverless-websockets","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fstayallive%2Fserverless-websockets","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstayallive%2Fserverless-websockets/lists"}