Introduction
WebSockets are a pretty common way to enable applications to communicate fast with each other. Especially for Web Development they are essential, therefore it is important that they work sufficient and secure.
Usually they are straight forward and easy to use. But there is an aspect you need to pay attention to if you want to use them in the Cloud Foundry environment. If you don't know about it, this might save you some time and nerves in the future.
SSL/TLS Termination
Cloud Foundry uses a mechanism called SSL/TLS-Termination. If you haven't heard of this term before, don't worry, you did now. It basically provides a proxy for SSL connection which handles the cryptographic processing and forwards the unencrypted data to the corresponding service.
In short words: You can use a secure WebSocket connection, even though you do not provide one yourself. The same works of course for a HTTPS connection.
What does this mean?
The WebSocket
server needs to run on the port 8080 which is opened by Cloud Foundry to the internet.
Your WebSocket
client needs to access the plain endpoint of your application without a specified port.
Some examples that
do not work:
const url = "wss://websocket-cf.cfapps.sap.hana.ondemand.com:8080"
const url = "wss://websocket-cf.cfapps.sap.hana.ondemand.com:3000"
const url = "wss://websocket-cf.cfapps.sap.hana.ondemand.com:80"
Examples that
will work:
const url = "wss://websocket-cf.cfapps.sap.hana.ondemand.com"
const url = "https://websocket-cf.cfapps.sap.hana.ondemand.com"
--> Only if there is not a http-based app running
const url = "wss://websocket-cf.cfapps.sap.hana.ondemand.com:443"
--> 443 is the only accessible port
Now, let's try this.
Hands-on: WebSockets on Cloud Foundry
First of all you need a current version of NodeJS installed. If this is not the case, please refer to:
https://nodejs.org/en/download/
Also you will need a SAP Cloud Platform Account in the
Cloud Foundry environment.
Next, we are going to create script running on the Cloud Platform:
server.js
const WebSocketServer = require('ws').Server
//We will create the websocket server on the port given by Cloud Foundry --> Port 8080
const ws = new WebSocketServer({ port: process.env.PORT || 8080 });
ws.on('connection', function (socket) {
socket.send('Hi, this is the Echo-Server');
socket.on('message', function (message) {
console.log('Received Message: ' + message);
socket.send('Echo: ' + message);
});
});
The script creates a WebSocket server which is listening for connections on the port specified by Cloud Foundry. Just in case, there is a fallback port specified. Once there is a connection established, the server sends a message to the connected client and waits for incoming messages. When a client sends a message the server responds with an echo.
Cloud Foundry also needs some meta information about the application. For this we need a file called
package.json:
{
"name": "websocket_cf",
"version": "1.0.0",
"description": "Basic WebSocket example application for Cloud Foundry on SAP Cloudplatform",
"main": "client.js",
"dependencies": {
"ws": "^4.0.0"
},
"devDependencies": {},
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "node client.js"
},
"engines": {
"node": "12.x.x"
}
}
It stores information about how to start the application, what dependencies are needed, etc.
To install the dependencies run the following command:
> npm install
In order to deploy the app on the Cloud Foundry environment we need a
manifest.yml:
---
applications:
- name: websocket_cf
command: node server.js
buildpack: https://github.com/cloudfoundry/nodejs-buildpack
health-check-type: none
memory: 256M
random-route: true
Now you are ready to deploy the server script to the cloud!
For the next steps you need to have the Cloud Foundry Command Line Interface installed:
https://github.com/cloudfoundry/cli#downloads
Now use your command line (CMD, Terminal, ...) to navigate to the folder you created the files
server.js, package.json and
manifest.yml.
> cd /folder/to/the/manifest/
Now set the API Endpoint according to the Cloud Foundry environment you are using. In my case it is:
https://api.cf.sap.hana.ondemand.com
> cf api https://api.cf.sap.hana.ondemand.com
api endpoint: https://api.cf.sap.hana.ondemand.com
api version: 2.100.0
Afterwards you need to login using your e-mail and password:
(You might need to choose the corresponding org where you want to deploy the app)
> cf login
After a successful login you can push the app to the cloud:
> cf push
This might take a minute, but once it's done you should see something like this:
requested state: started
instances: 1/1
usage: 256M x 1 instances
urls: websocket-cf.cfapps.sap.hana.ondemand.com
last uploaded: Tue Jan 23 09:30:51 UTC 2018
stack: cflinuxfs2
buildpack: https://github.com/cloudfoundry/nodejs-buildpack
state since cpu memory disk details
#0 running 2018-01-23 10:31:24 AM 0.0% 15.7M of 256M 56.4M of 1G
The most important information is the url: "urls: websocket-cf.cfapps.sap.hana.ondemand.com". You will need it to connect the client.
Alright, now that the server is running we need a client to test it:
client.js
const WebSocket = require('ws');
//replace the url with yours after pushing the app wss://<your-app>.<your-host>.hana.ondemand.com/
//do not specify a port
//you can use secure websockets because of the SSL-Termination
const url = "wss://websocket-cf.cfapps.sap.hana.ondemand.com"
const ws = new WebSocket(url);
ws.on('open', function() {
const message = 'Hi there!'
ws.send(message);
console.log('Sent Message: '+ message)
});
ws.on('error',function(data){
console.log('Error: ' + data);
});
ws.on('message', function(data, flags) {
console.log('Recieved Message: ' + data);
});
ws.on('close', function() {
console.log('Disconnected from Server');
});
The client connects to the server and sends a message "Hi there". In case it gets a message from the server, it logs it to console. Same happens if there is an error or the connection is closed. Don't forget to replace the url with yours.
To start the script run the following command:
> node client.js
You should get the following output:
Sent Message: Hi there!
Recieved Message: Hi, this is the Echo-Server
Recieved Message: Echo: Hi there!
Well that's it. You have create a simple WebSocket Server and deployed on the SAP Cloud Platform using Cloud Foundry and NodeJS.
If you are lazy, you can also just download the following repository from
GitHub, it contains all the necessary files.
For information please refer to:
https://github.com/websockets/ws
https://docs.cloudfoundry.org/