Skip to content

examples: add a WebSocket example #218

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jun 10, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 45 additions & 0 deletions examples/websocket/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# WebSocket Example

This example shows how simple it is to use CloudEvents over a websocket
connection. The code here shows backend communication from two server
side processes, and also between a browser and a server process.

## Running the Example

This simple project consists of a server and a client. The server receives
`CloudEvents` from the client over a local websocket connection.


To get started, first install dependencies.

```sh
npm install
```

### Server
The server opens a websocket and waits for incoming connections. It expects that any
messages it receives will be a CloudEvent. When received, it reads the data field,
expecting a zip code. It then fetches the current weather for that zip code and
responds with a CloudEvent containing the body of the Weather API response as the
event data.

You will need to change one line in the `server.js` file and provide your Open
Weather API key.

To start the server, run `node server.js`.

### Client
Upon start, the client prompts a user for a zip code, then sends a CloudEvent over
a websocket to the server with the provided zip code as the event data. The server
fetches the current weather for that zip code and returns it as a CloudEvent. The
client extracts the data and prints the current weather to the console.

To start the client, run `node client.js`

### Browser
Open the [`index.html`]('./index.html') file in your browser and provide a zip
code in the provided form field. The browser will send the zip code in the data
field of a CloudEvent over a websocket. When it receives a response from the server
it prints the weather, or an error message, to the screen.

To terminate the client or server, type CTL-C.
46 changes: 46 additions & 0 deletions examples/websocket/client.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/* eslint-disable no-console */
const readline = require("readline");
const WebSocket = require("ws");
const ws = new WebSocket("ws://localhost:8080");

const { CloudEvent } = require("cloudevents-sdk");

const rl = readline.createInterface({
input: process.stdin,
output: process.stdout
});

rl.on("close", (_) => console.log("\n\nConnection closed! Press CTL-C to exit."));

ws.on("message", function incoming(message) {
const event = new CloudEvent(JSON.parse(message));
if (event.type === "weather.error") {
console.error(`Error: ${event.data}`);
} else {
print(event.data);
}
ask();
});

function ask() {
rl.question("Would you like to see the current weather? Provide a zip code: ", function (zip) {
console.log("Fetching weather data from server...");
ws.send(new CloudEvent({
type: "weather.query",
source: "/weather.client",
data: zip
}).toString());
});
}

function print(data) {
data = JSON.parse(data);
console.log(`
Current weather for ${data.name}: ${data.weather[0].main}
------------------------------------------
With ${data.weather[0].description}, the temperature is ${Math.round(data.main.temp)}F
and the wind is blowing at ${Math.round(data.wind.speed)}mph.
`);
}

ask();
59 changes: 59 additions & 0 deletions examples/websocket/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
<!DOCTYPE html>
<html>
<head>
<title>CloudEvent Example</title>
<script src="../../bundles/cloudevents-sdk.js"></script>
<script>
const CloudEvent = window['cloudevents-sdk'].CloudEvent;
const socket = new WebSocket("ws://localhost:8080");

function print(weather) {
const data = JSON.parse(weather);
const summary = `
<h2>Current weather for ${data.name}: ${data.weather[0].main}</h2>
<hr/>
<p>
With ${data.weather[0].description}, the temperature is ${Math.round(data.main.temp)}F
and the wind is blowing at ${Math.round(data.wind.speed)}mph.
</p>`;
console.log(summary);
const node = document.getElementById("summary");
node.innerHTML = summary;
}

function initialize() {
socket.onmessage = function(message) {
console.log(message.data)
const event = new CloudEvent(JSON.parse(message.data));
if (event.type === "weather.error") {
console.error(`Error: ${event.data}`);
alert(`Error: ${event.data}`);
} else {
print(event.data);
}
}

const input = document.getElementById("zip");
input.addEventListener("keyup", function(event) {
if (event.keyCode === 13) {
event.preventDefault();
socket.send(new CloudEvent({
type: "weather.query",
source: "/weather.client",
data: input.value
}).toString());
}
});

}
</script>
</head>
<body style="font-size: larger; margin: 1em;" onload="initialize()">
<h1>Weather By Zip Code</h1>
<p>Please provide a zip code
<input type="text" id="zip"/>
</p>
<p style="font-family: Arial, Helvetica, sans-serif;" id="summary">
</p>
</body>
</html>
22 changes: 22 additions & 0 deletions examples/websocket/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"name": "websocket-cloudevents",
"version": "0.0.1",
"description": "An example application that sends and receives CloudEvents over a websocket",
"main": "server.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "node server.js"
},
"keywords": [
"cloudevents",
"example",
"websocket"
],
"author": "",
"license": "ISC",
"dependencies": {
"cloudevents-sdk": "^2.0.2",
"got": "^11.3.0",
"ws": "^7.3.0"
}
}
45 changes: 45 additions & 0 deletions examples/websocket/server.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/* eslint-disable no-console */
const got = require("got");

const { CloudEvent } = require("cloudevents-sdk");
const WebSocket = require("ws");
const wss = new WebSocket.Server({ port: 8080 });

const api = "https://api.openweathermap.org/data/2.5/weather";
const key = "REPLACE WITH API KEY";

console.log("WebSocket server started. Waiting for events.");

wss.on("connection", function connection(ws) {
console.log("Connection received");
ws.on("message", function incoming(message) {
const event = new CloudEvent(JSON.parse(message));
console.log(`Message received: ${event.toString()}`);
fetch(event.data)
.then((weather) => {
ws.send(new CloudEvent({
dataContentType: "application/json",
type: "current.weather",
source: "/weather.server",
data: weather
}).toString());
})
.catch((err) => {
console.error(err);
ws.send(new CloudEvent({
type: "weather.error",
source: "/weather.server",
data: err.toString()
}).toString());
});
});
});

function fetch(zip) {
const query = `${api}?zip=${zip}&appid=${key}&units=imperial`;
return new Promise((resolve, reject) => {
got(query)
.then((response) => resolve(response.body))
.catch((err) => reject(err.message));
});
}