React Native
You can integrate the RUAL backend with any frontend or application. The most commonly used framework is React Native, and we offer connection code that can serve as a template.
Authentication
If you wish to manage authentication using RUAL, you can refer to our authentication APIs. These APIs enable you to generate a valid access_token
that you can store locally on the device for future use.
WebSocket Connection
The most commonly employed connection logic is WebSocket. Below, we offer an example code snippet for establishing such a connection, which is compatible with React Native.
websocket.js
export default class WS {
requestId = 0;
openRequests = new Map();
_connection = null;
connect () {
if (this._connection) {
if (this._connection.readyState === this._connection.CONNECTING || this._connection.readyState === this._connection.OPEN) {
return;
}
}
this.requestId = 0;
this._connection = new WebSocket('wss://rual-ws.{{cluster-domain}}/primus');
this._connection.onopen = () => {
console.log('connected');
};
this._connection.onmessage = (e) => {
this.handleMessage(e);
};
this._connection.onerror = (e) => {
this.disconnect();
};
this._connection.onclose = (e) => {
this.disconnect();
this.handleClose(e);
};
}
async waitForConnected (count = 0) {
if (!this._connection) {
this.connect();
} else if (this._connection) {
if (this._connection.readyState === this._connection.OPEN) {
return;
}
}
console.log('waiting for connection [' + count + ']');
await (new Promise((resolve) => {
setTimeout(resolve, 100 + (1 * count));
}));
return this.waitForConnected(count + 1);
}
disconnect () {
if (this._connection) {
try {
this._connection.close();
} catch (e) {}
}
this._connection = null;
}
async requestURI (method, uri, body = null, query = null, token = null) {
await this.waitForConnected();
this.requestId += 1;
const uriId = 'RN' + String(this.requestId).padStart(10, '0');
const requestBody = {
'method': String(method).toUpperCase(),
'requestid': uriId,
'uri': '/api/' + uri
};
if (token) {
requestBody.access_token = token;
}
if (body) {
requestBody.body = body;
}
if (query) {
requestBody.query = query;
}
this._connection.send(JSON.stringify(requestBody));
return new Promise((resolve, reject) => {
this.openRequests.set(uriId, {
'resolve': resolve,
'reject': reject,
'uri': uri,
'method': method
});
});
}
handleClose (message) {
console.log(message);
console.log('closed');
}
handleMessage (message) {
if (message.data) {
const data = JSON.parse(message.data);
console.log('---> ', data);
if (typeof data === 'string') {
this._replyPing(message.data);
return;
}
try {
if (data.requestid) {
const currentRequest = this.openRequests.get(data.requestid);
if (currentRequest) {
if (data.code === 200) {
currentRequest.resolve(data.result);
} else {
currentRequest.reject(data.result);
}
this.openRequests.delete(data.requestid);
} else {
console.log('request id', data.requestid, 'not found');
}
}
if (data.broadcast) {
const payload = data.broadcast.message || {};
switch (payload.type) {
case 'broadcast-type':
// do something with payload
break;
}
}
} catch (err) {
console.error('failed handle WS');
}
}
}
async _replyPing (data) {
await this.waitForConnected();
console.log('sending', data.replace('ping', 'pong'));
this._connection.send(data.replace('ping', 'pong'));
}
}