Skip to Content

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": "^8.9.4",
    "npm": "5.6.0"
  }
}

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/

To report this post you need to login first.

5 Comments

You must be Logged on to comment or reply to a post.

  1. Former Member

    Thanks, this is really helpful.

    Can you share how would the manifest file look in case a separate application on CF (UI Client) needs to communicate to the websocket server.

    (0) 
  2. Noemi Bugyi

    Hello,

    Thank you this is really useful!

    Could you please help with some ideas, hints regarding a connection issue.

    When the external client tries to connect to my Websocket server, the connection fails and I’m getting the “Upgrade required” – 426 error.

    Could you tell me which configuration should be changed, in order to establish the connection.

    Thank you in advance.

     

    Regards,

    Noemi B.

    (0) 
  3. Noemi Bugyi

    Hello,

     

    It is possible to remove the “Upgrade” header in order to establish the connection/handshake or how we can add custom headers to our websocket server ?

     

    Are there any websocket compatible libraries with cloud foundry ?

     

    Regards,

    Noemi B

    (0) 

Leave a Reply