Monday, May 29, 2017

Ballerina for simple server side Web Socket programs

WebSockets is one of those protocols that was invented to solve the transmission barrier posted by HTTP’s stateless request-response model. One of the key differentiators of it is its ability piggy back on HTTP infrastructure using the HTTP upgrade mechanism[1], this ability when coupled with the inbuilt support provided by HTML5 for client-side WebSockets programming, allowed it to emerge as a strong contender to win the full-duplex protocol war.

As with other transport/application protocols supported by Ballerina, a consistent programming interface is provided to put together WebSocket based server side programs with ease. The example found below demonstrates this capability.


package socketproxy.sample;
import ballerina.lang.system;
import ballerina.lang.strings;
import ballerina.lang.messages;
import ballerina.net.http;
import ballerina.net.ws;
@http:BasePath {value:"/socketproxy"}
@ws:WebSocketUpgradePath {value:"/ws"}
service socketProxyServer {
http:ClientConnector backend = create http:ClientConnector("http://localhost:9090/backend");
message response = {};
@ws:OnOpen {}
resource onOpen(message m) {
system:println("New client connected to the server.");
}
@ws:OnTextMessage {}
resource onTextMessage(message m) {
string id = messages:getStringPayload(m);
xml requestPayload = `<id>${id}</id>`;
messages:setXmlPayload(m,requestPayload);
messages:setHeader(m,"Content-Type","application/xml");
response = http:ClientConnector.get(backend, "/", m);
xml responsePayload = messages:getXmlPayload(response);
string response = strings:valueOf(responsePayload);
ws:pushText(response);
system:println("Response from Backend : " + response);
}
@ws:OnClose {}
resource onClose(message m) {
system:println("client left the server.");
}
}
view raw SocketProxy.bal hosted with ❤ by GitHub


package socketproxy.sample;
import ballerina.lang.messages;
import ballerina.net.http;
import ballerina.lang.xmls;
@http:BasePath {value:"/backend"}
service BackendService {
message response = {};
xml payload = `<record><status>a record was not found for the id passed in.</status></record>`;
@http:GET{}
resource backendresource (message m) {
xml requestPayload = messages:getXmlPayload(m);
if (xmls:getString(requestPayload,"/id/text()") == "1101"){
payload = `<record><id>1101</id><status>payment was made.</status></record>`;
}
messages:setXmlPayload(response, payload);
reply response;
}
}
view raw Backend.bal hosted with ❤ by GitHub




To try out the example, create the folder structure <BALLERINA_HOME>/socketproxy/sample and copy the content into the two appropriately named bal files. Make an archive[2] and make a websocket client call to “ws://localhost:9090/socketproxy/ws”, find a sample python client attached(it requires python-websocket package to work).


Look to the websocket samples found in the ballerina 0.87 distribution to learn more about websocket programming with ballerina.

Note: the example above was constructed to demonstrate a simple use case involving websockets, a real world implementation should be built after careful analysis of the requirements.

No comments:

Post a Comment