Update the :connection
and :db-name
keys with your Datomic Cloud configuration
{:db-name "ws-demo"
:connection {:server-type :ion
:region "eu-west-1"
:system "knox"
:endpoint "http://entry.knox.eu-west-1.datomic.net:8182/"
:proxy-port 8182}}
Create a new Datomic database (if necessary)
(in-ns 'wsdemo.client)
(d/create-database (get-conn) {:db-name "ws-demo"})
And transact the demo schema:
(d/transact (get-conn) {:tx-data (-> "schema.edn" io/resource slurp read-string)})
The project uses Datomic Ions to deploy 3 Clojure Lambda functions which handle websocket connections via an AWS API Gateway:
wsdemo.handlers/gateway-authorizer
(Re)authorizes connections to the gateway
wsdemo.handlers/handle-connection-proxy
Links one or more gateway connection IDs with database users
wsdemo.io/handle-message-proxy
Handles all communications after a successful connection
Deploy them to your AWS infrastructure
$ clj -Adeploy-to-aws <system-name>
In the AWS Console, create a new WebSocket API
Route Selection Expression
=$request.body.event
(default)$connect
- Route Request
- Authorizer =
gateway-authorizer
Ion
- Authorizer =
- Integration Response
- Integration type: Lambda Function
- Use Lambda Proxy Integration
- Lambda function =
ws-handle-connection-proxy
- Route Request
$disconnect
- Integration Response
- Integration type: Lambda Function
- Use Lambda Proxy Integration
- Lambda function =
ws-handle-connection-proxy
- Integration Response
$default
- Integration Response
- Integration type: Lambda Function
- Use Lambda Proxy Integration
- Lambda function =
ws-handle-message-proxy
- Integration Response
Deploy the API, and then update resources/project-config.edn
{:api-gw {:hostname "n3giprj0y8.execute-api.eu-west-1.amazonaws.com"
:stage "dev"
:path "/dev/@connections/"}}
The wsdemo.test-connections
namespace will estabish two connections when loaded. The broadcast-from-conn-1
function will send a message from conn-1
to all connections, in this case conn-1
and conn-2
:
(in-ns 'wsdemo.test-connections)
(broadcast-from-conn-1)
Message received: {:message Hello everyone, :sender eb50a8b9-f285-4ca7-ac99-0c876a5daa5d}
Message received: {:message Hello everyone, :sender eb50a8b9-f285-4ca7-ac99-0c876a5daa5d}
Install wscat
$ yarn global add wscat
Get a valid JWT sign with the secret from project-config.edn
(in-ns 'wsdemo.test-connections)
(jwt/sign {:sub (UUID/randomUUID)} secret)
=>
"eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIwZmEyNTVkZS1jOGJkLTQ0M2EtODY0Yy1jODkyZGFmY2ZjNTgifQ.ZMcAEwd3JHP7HqBnprvz_38uPtNmp_cNl14mGCI1E_U"
Connect and broadcast a message
$ wscat -c wss://n3giprj0y8.execute-api.eu-west-1.amazonaws.com/dev -H Authorization:<JWT>
> {:action :broadcast :message "Hello everyone"}
< {:message "Hello everyone", :sender "0fa255de-c8bd-443a-864c-c892dafcfc58"}