[lib.client.client-driver][lib.client.xhr][lib.client.ws] made more generic with trying to re-configure connection (bind) if connection lost and trying to send() a request
This commit is contained in:
parent
1cedd6284a
commit
a1a5610f2c
|
@ -1,3 +1,4 @@
|
|||
import {APIClient} from './lib/api-client'
|
||||
import {GlobalStore} from './lib/gstore'
|
||||
import VueRouter from 'vue-router'
|
||||
import routes from './routes'
|
||||
|
@ -6,8 +7,14 @@ import {ContentController} from './lib/content-controller'
|
|||
import {RoomController} from './lib/room-controller'
|
||||
import {ChannelController} from './lib/channel-controller'
|
||||
|
||||
import XHRClientDriver from './lib/client/xhr.js'
|
||||
import WebSocketClientDriver from './lib/client/ws.js'
|
||||
|
||||
|
||||
window.gs = new GlobalStore();
|
||||
window.api = new APIClient('localhost', null, false);
|
||||
window.xhrcd = XHRClientDriver;
|
||||
window.wscd = WebSocketClientDriver;
|
||||
|
||||
/* (1) Global data
|
||||
---------------------------------------------------------*/
|
||||
|
|
|
@ -1,81 +1,142 @@
|
|||
/* classe API */
|
||||
export class APIClient{
|
||||
|
||||
constructor(target){
|
||||
|
||||
this.target = target;
|
||||
|
||||
this.xhr = []; // tableau d'objets pour les requêtes ajax
|
||||
this.buffer = null; // Contiendra le buffer pour debugger si erreur de parsage
|
||||
this.error = { // error constants
|
||||
'-1': 'Invalid target format: "METHOD module/method"',
|
||||
'-2': 'XHR error',
|
||||
'-3': 'Invalid JSON response',
|
||||
/* (1) Constructs an API client manager
|
||||
*
|
||||
* @_hostname<String> Server hostname (without http, port number, etc)
|
||||
* @_baseuri<String> Server base URI
|
||||
* @_ssl<bool> [OPT] Whether SSL is activated (http vs https) (default: https)
|
||||
* @_port<int> [OPT] optional HTTP port (default: none)
|
||||
*
|
||||
* @return http_url<String> Built http_url
|
||||
*
|
||||
---------------------------------------------------------*/
|
||||
constructor(_hostname, _baseuri, _ssl=true, _port=null){
|
||||
|
||||
/* (1) Build URL parts */
|
||||
this.http_parts = {
|
||||
|
||||
ssl: _ssl === true,
|
||||
hostname: _hostname,
|
||||
baseuri: this.fix_uri(_baseuri),
|
||||
port: !isNaN(_port) ? _port: null
|
||||
|
||||
};
|
||||
|
||||
this.xhr_stack = []; // Ajax request stack
|
||||
this.buffer = null; // Last request buffer
|
||||
|
||||
}
|
||||
|
||||
|
||||
fix_uri(_uri){
|
||||
|
||||
if( typeof _uri !== 'string' )
|
||||
return '';
|
||||
|
||||
return _uri.split('/').filter((r) => r.trim().length).join('/')
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* (2) HTTP url dynamic getter
|
||||
*
|
||||
* @_uri<String> [OPT] optional URI string
|
||||
* @_token<String> [OPT] optional HTTP token
|
||||
*
|
||||
* @return http_url<String> Built http_url
|
||||
*
|
||||
---------------------------------------------------------*/
|
||||
build_url(_uri, _token=null){
|
||||
|
||||
/* (1) Initialize URL buffer */
|
||||
let bufurl = 'http';
|
||||
|
||||
/* (2) Manage @ssl */
|
||||
this.http_parts.ssl && ( bufurl = bufurl.concat('s') );
|
||||
bufurl = bufurl.concat('://');
|
||||
|
||||
/* (3) Manage token */
|
||||
( typeof _token === 'string' ) && ( bufurl = bufurl.concat(`${_token}@`) );
|
||||
|
||||
/* (4) Manage hostname */
|
||||
bufurl = bufurl.concat(this.http_parts.hostname);
|
||||
|
||||
/* (5) Manage port */
|
||||
( this.http_parts.port !== null ) && ( bufurl = bufurl.concat(`:${this.http_parts.port}`) );
|
||||
|
||||
/* (6) Base uri */
|
||||
bufurl = bufurl.concat(`/${this.http_parts.baseuri}/`);
|
||||
|
||||
/* (7) Manage URI */
|
||||
bufurl = bufurl.concat( this.fix_uri(_uri) );
|
||||
|
||||
return bufurl;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* transaction avec le serveur (http://{host}/api/)
|
||||
/* Server Transaction
|
||||
*
|
||||
* @param pTarget<String> URI cible, format "HTTP_METHOD uri/uri/uri"
|
||||
* @param pArgs<Object> Le tableu d'arguments passé en POST (attribut<->postfield) à http://{host}/api/
|
||||
* @param pHandler<Function> Fonction qui s'éxécutera lors de la réponse (1 argument -> réponse<Object>)
|
||||
* @param pToken<String> Optionnel, token d'auth pour l'api
|
||||
* @param _path<String> target path (format "HTTP_METHOD uri/uri/uri")
|
||||
* @param _args<Object> formdata object (as raw object)
|
||||
* @param _callback<Function> Response callback
|
||||
* @param _token<String> [OPT] http token
|
||||
*
|
||||
***************************************************************************************************
|
||||
*
|
||||
* @usecase
|
||||
* 1. api.call(
|
||||
* 2. "PUT newspaper/article/4"
|
||||
* 2. { content: "New article content" },
|
||||
* 3. function(resp){
|
||||
* 4. alert(resp.error);
|
||||
* 5. }
|
||||
* 2. 'PUT newspaper/article/4'
|
||||
* 3. { content: "new content" },
|
||||
* 4. (r) => alert(r.error),
|
||||
* 5. 'sometoken'
|
||||
* 6. );
|
||||
*
|
||||
*/
|
||||
call(pTarget, pArgs, pHandler, pToken=null){
|
||||
call(_path, _args, _callback, _token=null){
|
||||
|
||||
|
||||
/* (1) Check @pHandler (for dispatching errors)
|
||||
/* (1) Argument management
|
||||
---------------------------------------------------------*/
|
||||
/* (1) Check if is a Function */
|
||||
if( !(pHandler instanceof Function) )
|
||||
throw new Error("3rd argument must be a function, but is of type '"+typeof(pHandler)+"' !");
|
||||
/* (1) Set default callback if @callback not callable */
|
||||
if( !(_callback instanceof Function) )
|
||||
_callback = function(r){ console.warn('The API callback function is missing, default callback set.', 'Response', r); };
|
||||
|
||||
|
||||
|
||||
/* (2) Check @pTarget
|
||||
---------------------------------------------------------*/
|
||||
/* (1) Check format */
|
||||
if( !/^([A-Z]+) (.+)/i.test(pTarget) ){
|
||||
pHandler({ error: -1, ErrorDescription: this.error['-1'] });
|
||||
/* (2) Check @path format */
|
||||
if( !/^([A-Z]+) (.+)/i.test(_path) ){
|
||||
_callback({ error: -1 });
|
||||
return false;
|
||||
}
|
||||
|
||||
/* (2) Store locally data */
|
||||
var lHttpMethod = RegExp.$1;
|
||||
var lUri = RegExp.$2;
|
||||
var http_method = RegExp.$1;
|
||||
var http_uri = RegExp.$2;
|
||||
|
||||
/* (3) Default @_token */
|
||||
if( typeof _token !== 'string' )
|
||||
_token = null;
|
||||
|
||||
|
||||
|
||||
|
||||
/* (3) Create form data
|
||||
---------------------------------------------------------*/
|
||||
/* (1) Create virtual form */
|
||||
var lForm = new FormData();
|
||||
var form_data = new FormData();
|
||||
|
||||
/* (2) Add attributes */
|
||||
for( var key in pArgs ){
|
||||
for( var key in _args ){
|
||||
|
||||
// {2.1} If a file -> send as it //
|
||||
if( pArgs[key] instanceof File )
|
||||
lForm.append(key, pArgs[key]);
|
||||
if( _args[key] instanceof File )
|
||||
form_data.append(key, _args[key]);
|
||||
|
||||
// {2.2} Else -> JSON stringify //
|
||||
else
|
||||
lForm.append(key, JSON.stringify(pArgs[key]));
|
||||
form_data.append(key, JSON.stringify(_args[key]));
|
||||
|
||||
}
|
||||
|
||||
|
@ -84,74 +145,69 @@ export class APIClient{
|
|||
/* (4) Create XHR request
|
||||
---------------------------------------------------------*/
|
||||
/* (1) Clean ended requests */
|
||||
for( var i = this.xhr.length-1 ; i >= 0 ; i-- ){
|
||||
for( var i = this.xhr_stack.length-1 ; i >= 0 ; i-- ){
|
||||
|
||||
if( this.xhr[i] != null )
|
||||
if( this.xhr_stack[i] != null )
|
||||
break;
|
||||
|
||||
this.xhr.pop();
|
||||
this.xhr_stack.pop();
|
||||
|
||||
}
|
||||
|
||||
/* (2) Push a new entry -> fetch its index */
|
||||
i = this.xhr.push(null) - 1;
|
||||
i = this.xhr_stack.push(null) - 1;
|
||||
|
||||
/* (3) Create XHR object */
|
||||
this.xhr[i] = (window.XMLHttpRequest) ? new XMLHttpRequest() : new ActiveXObject('Microsoft.XMLHttpRequest');
|
||||
this.xhr_stack[i] = (window.XMLHttpRequest) ? new XMLHttpRequest() : new ActiveXObject('Microsoft.XMLHttpRequest');
|
||||
|
||||
|
||||
|
||||
/* (5) Bind response event
|
||||
---------------------------------------------------------*/
|
||||
var self = this; // to access the buffer
|
||||
|
||||
this.xhr[i].onreadystatechange = function(i){
|
||||
this.xhr_stack[i].onreadystatechange = function(i, parent){
|
||||
|
||||
/* (1) If request over */
|
||||
if( this.xhr[i].readyState == 4 ){
|
||||
if( this[i].readyState === 4 ){
|
||||
|
||||
/* (2) Update buffer (for debug) */
|
||||
self.buffer = this.xhr[i].responseText;
|
||||
parent.buffer = this[i].responseText;
|
||||
|
||||
/* (3) If request success */
|
||||
if( [0, 200, 417].indexOf(this.xhr[i].status) > -1 ){
|
||||
if( [0, 200].indexOf(this[i].status) > -1 ){
|
||||
|
||||
|
||||
/* (3.1) Create default response (if JSON error) */
|
||||
var response = {error:-3, ErrorDescription: self.error['-3']};
|
||||
var response = { error: -2 };
|
||||
|
||||
/* (3.2) Try to parse JSON */
|
||||
try{ response = JSON.parse(this.xhr[i].responseText); }catch(e){}
|
||||
try{ response = JSON.parse(this[i].responseText); }catch(e){}
|
||||
|
||||
/* (3.3) Launch @pHandler with response */
|
||||
pHandler(response);
|
||||
/* (3.3) Launch @_callback with response */
|
||||
_callback(response);
|
||||
|
||||
/* (4) If request error */
|
||||
}else
|
||||
pHandler({ error:-2, ErrorDescription: self.error['-2'] });
|
||||
_callback({ error: -3 });
|
||||
|
||||
/* (5) Notify current xhr instance is done */
|
||||
this.xhr[i] = null;
|
||||
this[i] = null;
|
||||
|
||||
}
|
||||
|
||||
}.bind(this, i);
|
||||
}.bind(this.xhr_stack, i, this);
|
||||
|
||||
|
||||
/* (6) Finish & send request
|
||||
---------------------------------------------------------*/
|
||||
/* (1) Open the XHR */
|
||||
this.xhr[i].open(lHttpMethod, this.target+lUri, true);
|
||||
console.log(http_method, this.build_url(http_uri, _token));
|
||||
this.xhr_stack[i].open(http_method, this.build_url(http_uri, _token), true);
|
||||
|
||||
/* (2) Manage optional token */
|
||||
if( pToken != null )
|
||||
this.xhr[i].setRequestHeader('Authorization', 'Digest '+pToken);
|
||||
/* (2) Custom header to notify we're using Ajax */
|
||||
this.xhr_stack[i].setRequestHeader('X-Requested-With', 'XMLHttpRequest');
|
||||
|
||||
/* (3) Custom header to notify we're using Ajax */
|
||||
this.xhr[i].setRequestHeader('X-Requested-With', 'XMLHttpRequest');
|
||||
|
||||
/* (4) Make the call */
|
||||
this.xhr[i].send( lForm );
|
||||
/* (3) Make the call */
|
||||
this.xhr_stack[i].send(form_data);
|
||||
|
||||
return true;
|
||||
|
||||
|
|
|
@ -1,15 +1,15 @@
|
|||
export class ClientDriver{
|
||||
export default class ClientDriver{
|
||||
|
||||
/* (0) Constants & Enums
|
||||
---------------------------------------------------------*/
|
||||
static get STATE(){
|
||||
|
||||
return Object.freeze({
|
||||
OPENING: 0,
|
||||
OPENED: 1,
|
||||
CLOSED: 0,
|
||||
READY: 1,
|
||||
CONNECTING: 2,
|
||||
CONNECTED: 3,
|
||||
CLOSED: 4
|
||||
TRANFERING: 4
|
||||
});
|
||||
|
||||
}
|
||||
|
@ -22,27 +22,81 @@ export class ClientDriver{
|
|||
---------------------------------------------------------*/
|
||||
constructor(_resource){
|
||||
|
||||
/* (1) Initialize driver
|
||||
---------------------------------------------------------*/
|
||||
/* (1) Default attributes values */
|
||||
this.error = false;
|
||||
this.state = ClientDriver.STATE.OPENING;
|
||||
this.force_close = false;
|
||||
this.state = ClientDriver.STATE.READY;
|
||||
this.stack = [];
|
||||
|
||||
/* (2) Default User callbacks */
|
||||
this.callback = {
|
||||
onready: function(){},
|
||||
onconnected: function(){},
|
||||
onclose: function(){},
|
||||
onreceive: function(){}
|
||||
};
|
||||
|
||||
/* (2) Fail: invalid _resource */
|
||||
this.event = {
|
||||
|
||||
/* (3) Manage connection opened */
|
||||
onconnected: function(){
|
||||
|
||||
// update state
|
||||
this.state = ClientDriver.STATE.CONNECTED;
|
||||
|
||||
// call callback
|
||||
this.callback.onconnected();
|
||||
|
||||
// if request(s) in stack -> pop & send them
|
||||
while( this.stack.length > 0 )
|
||||
this.send(this.stack.shift());
|
||||
|
||||
}.bind(this),
|
||||
|
||||
/* (4) Manage connection closed */
|
||||
onclose: function(){
|
||||
|
||||
// if called close() -> CLOSED
|
||||
if( this.force_close )
|
||||
this.state = ClientDriver.STATE.CLOSED;
|
||||
|
||||
// else set state back to READY
|
||||
else
|
||||
this.state = ClientDriver.STATE.READY;
|
||||
|
||||
// call callback
|
||||
this.callback.onclose();
|
||||
|
||||
}.bind(this),
|
||||
|
||||
/* (5) Manage response received */
|
||||
onreceive: function(_response){
|
||||
|
||||
// set state from TRANSFERING to CONNECTED
|
||||
this.state = ClientDriver.STATE.CONNECTED;
|
||||
|
||||
// call callback
|
||||
this.callback.onreceive(_response);
|
||||
|
||||
}.bind(this)
|
||||
|
||||
};
|
||||
|
||||
/* (2) Manage errors
|
||||
---------------------------------------------------------*/
|
||||
/* (1) Fail: invalid _resource */
|
||||
if( typeof _resource !== 'string' )
|
||||
return ( this.error = true );
|
||||
|
||||
/* (3) Set explicit attributes */
|
||||
/* (2) Set explicit attributes */
|
||||
this.resource = _resource;
|
||||
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* (2) Binds the client to the resource
|
||||
*
|
||||
* @return bound<boolean> Whether the binding has been successful
|
||||
|
@ -50,17 +104,43 @@ export class ClientDriver{
|
|||
---------------------------------------------------------*/
|
||||
bind(){
|
||||
|
||||
/* (1) Fail: not OPENING OR error */
|
||||
if( this.error || this.state !== ClientDriver.STATE.OPENING )
|
||||
/* (1) force_close -> fail */
|
||||
if( this.force_close )
|
||||
return false;
|
||||
|
||||
/* (2) By default return success */
|
||||
/* (2) Fail: not READY */
|
||||
if( this.state !== ClientDriver.STATE.READY )
|
||||
return false;
|
||||
|
||||
/* (3) Update state */
|
||||
this.state = ClientDriver.STATE.CONNECTING;
|
||||
|
||||
/* (4) Child dispatch */
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* (3) Send request
|
||||
/* (3) Closes the connection
|
||||
*
|
||||
* @return closed<boolean> Whether the connection has been closed
|
||||
*
|
||||
---------------------------------------------------------*/
|
||||
close(){
|
||||
|
||||
/* (1) set force_close */
|
||||
this.force_close = true;
|
||||
|
||||
/* (2) Update state */
|
||||
this.state = ClientDriver.STATE.CLOSED;
|
||||
|
||||
/* (4) Child dispatch */
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* (4) Send request
|
||||
*
|
||||
* @_request<Object> Request data
|
||||
*
|
||||
|
@ -69,111 +149,99 @@ export class ClientDriver{
|
|||
---------------------------------------------------------*/
|
||||
send(_request){
|
||||
|
||||
/* (1) Fail: if error */
|
||||
if( this.error )
|
||||
/* (1) force_close -> fail */
|
||||
if( this.force_close )
|
||||
return false;
|
||||
|
||||
/* (2) Fail: invalid _request */
|
||||
/* (2) bufferise 'state' */
|
||||
let state = this.state;
|
||||
|
||||
/* (3) Fail: invalid _request */
|
||||
if( !(_request instanceof Object) )
|
||||
return false;
|
||||
|
||||
/* (3) If not already connected -> stack request */
|
||||
if( this.state < ClientDriver.STATE.CONNECTED ){
|
||||
|
||||
this.stack.push(_request);
|
||||
/* (4) CLOSED -> abort */
|
||||
if( state === ClientDriver.STATE.CLOSED )
|
||||
return false;
|
||||
|
||||
}
|
||||
/* (5) READY -> stack message + bind() [in case connection failed)] */
|
||||
if( state === ClientDriver.STATE.READY )
|
||||
return ( this.stack.push(_request) > -1 ) && this.bind();
|
||||
|
||||
/* (6) CONNECTING -> stack message */
|
||||
if( state === ClientDriver.STATE.CONNECTING )
|
||||
return ( this.stack.push(_request) > -1 );
|
||||
|
||||
/* (4) By default return success */
|
||||
/* (7) update state */
|
||||
this.state = ClientDriver.STATE.TRANFERING;
|
||||
|
||||
/* (8) Child dispatch */
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* (4) Bind event to connection opened
|
||||
/* (5) Bind event to connection successfully opened
|
||||
*
|
||||
* @_callback<Function> Callback launched when connection is opened
|
||||
*
|
||||
* @return bound<boolean> Whether the callback has successfully been bound
|
||||
*
|
||||
---------------------------------------------------------*/
|
||||
onready(_callback){
|
||||
set onconnected(_callback){
|
||||
|
||||
/* (1) Fail: already CONNECTED OR error */
|
||||
if( this.error || this.state >= ClientDriver.STATE.CONNECTED )
|
||||
return false;
|
||||
|
||||
/* (2) Fail: invalid _callback */
|
||||
/* (1) Fail: invalid _callback */
|
||||
if( !(_callback instanceof Function) )
|
||||
return false;
|
||||
|
||||
/* (3) Register _callback */
|
||||
this.callback.onready = function(cback){
|
||||
/* (2) Register _callback */
|
||||
this.callback.onconnected = _callback;
|
||||
|
||||
// call callback
|
||||
cback();
|
||||
|
||||
// if request(s) in stack -> pop & send them
|
||||
while( this.stack.length > 0 )
|
||||
this.send(this.stack.shift());
|
||||
|
||||
}.bind(this, _callback);
|
||||
|
||||
/* (5) By default return success */
|
||||
/* (3) By default return success */
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* (5) Bind event to connection closed
|
||||
/* (6) Bind event to connection closed
|
||||
*
|
||||
* @_callback<Function> Callback launched when connection is closed
|
||||
*
|
||||
* @return bound<boolean> Whether the callback has successfully been bound
|
||||
*
|
||||
---------------------------------------------------------*/
|
||||
onclose(_callback){
|
||||
set onclose(_callback){
|
||||
|
||||
/* (1) Fail: already CLOSED OR error */
|
||||
if( this.error || this.state === ClientDriver.STATE.CLOSED )
|
||||
return false;
|
||||
|
||||
/* (2) Fail: invalid _callback */
|
||||
/* (1) Fail: invalid _callback */
|
||||
if( !(_callback instanceof Function) )
|
||||
return false;
|
||||
|
||||
/* (3) Register _callback */
|
||||
/* (2) Register _callback */
|
||||
this.callback.onclose = _callback;
|
||||
|
||||
/* (4) By default return success */
|
||||
/* (3) By default return success */
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* (6) Bind event to message reception
|
||||
/* (7) Bind event to message reception
|
||||
*
|
||||
* @_callback<Function> Callback launched when a message is received
|
||||
*
|
||||
* @return bound<boolean> Whether the callback has successfully been bound
|
||||
*
|
||||
---------------------------------------------------------*/
|
||||
onreceive(_callback){
|
||||
set onreceive(_callback){
|
||||
|
||||
/* (1) Fail: already CONNECTED OR error */
|
||||
if( this.error || this.state >= ClientDriver.STATE.CONNECTED )
|
||||
return false;
|
||||
|
||||
/* (2) Fail: invalid _callback */
|
||||
/* (1) Fail: invalid _callback */
|
||||
if( !(_callback instanceof Function) )
|
||||
return false;
|
||||
|
||||
/* (3) Register _callback */
|
||||
/* (2) Register _callback */
|
||||
this.callback.onreceive = _callback;
|
||||
|
||||
/* (4) By default return success */
|
||||
/* (3) By default return success */
|
||||
return true;
|
||||
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import {ClientDriver} from './client-driver.js'
|
||||
import ClientDriver from './client-driver.js'
|
||||
|
||||
export class WebSocketClientDriver extends ClientDriver{
|
||||
export default class WebSocketClientDriver extends ClientDriver{
|
||||
|
||||
|
||||
/* (1) Creates a client driver
|
||||
|
@ -21,9 +21,6 @@ export class WebSocketClientDriver extends ClientDriver{
|
|||
this.ws = null;
|
||||
this.buffer = null; // useful when waiting for WebSocket to open
|
||||
|
||||
/* (N) Set all is ok */
|
||||
this.error = false;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -42,28 +39,16 @@ export class WebSocketClientDriver extends ClientDriver{
|
|||
this.ws = new WebSocket(this.resource);
|
||||
|
||||
/* (2) Bind callback.onready */
|
||||
this.ws.onopen = function(){
|
||||
this.state = ClientDriver.STATE.CONNECTED;
|
||||
this.callback.onready();
|
||||
}.bind(this);
|
||||
this.ws.onopen = this.event.onconnected;
|
||||
|
||||
/* (3) Bind callback.onclose */
|
||||
this.ws.onclose = function(){
|
||||
this.state = ClientDriver.STATE.CLOSED;
|
||||
this.callback.onclose();
|
||||
}.bind(this);
|
||||
this.ws.onclose = this.event.onclose;
|
||||
|
||||
/* (4) Bind callback.onerror */
|
||||
this.ws.onerror = function(){
|
||||
this.state = ClientDriver.STATE.CLOSED;
|
||||
this.callback.onclose();
|
||||
}.bind(this);
|
||||
this.ws.onerror = this.event.onclose;
|
||||
|
||||
/* (5) Bind callback.onreceive */
|
||||
this.ws.onmessage = function(response){
|
||||
this.state = ClientDriver.STATE.CONNECTED;
|
||||
this.callback.onreceive(response);
|
||||
}.bind(this);
|
||||
this.ws.onmessage = (_message_event) => this.event.onreceive(_message_event.data);
|
||||
|
||||
/* (6) Return success */
|
||||
return true;
|
||||
|
@ -85,11 +70,12 @@ export class WebSocketClientDriver extends ClientDriver{
|
|||
return false;
|
||||
|
||||
/* (1) Error: invalid _request.buffer */
|
||||
if( typeof _request.buffer !== 'string' )
|
||||
if( typeof _request.buffer !== 'string' ){
|
||||
this.state = ClientDriver.STATE.CONNECTED;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* (2) Send message */
|
||||
console.log('sent', _request.buffer);
|
||||
this.ws.send(_request.buffer);
|
||||
|
||||
/* (3) Return success */
|
||||
|
@ -98,50 +84,22 @@ export class WebSocketClientDriver extends ClientDriver{
|
|||
}
|
||||
|
||||
|
||||
/* (4) Bind event to connection opened
|
||||
/* (3) Closes the connection
|
||||
*
|
||||
* @_callback<Function> Callback launched when connection is opened
|
||||
*
|
||||
* @return bound<boolean> Whether the callback has successfully been bound
|
||||
* @return closed<boolean> Whether the connection has been closed
|
||||
*
|
||||
---------------------------------------------------------*/
|
||||
onready(_callback){
|
||||
close(){
|
||||
|
||||
/* (0) Parent check */
|
||||
if( !super.onready(_callback) )
|
||||
if( !super.close() )
|
||||
return false;
|
||||
|
||||
}
|
||||
/* (1) Close websocket */
|
||||
this.ws.close();
|
||||
|
||||
|
||||
/* (5) Bind event to connection closed
|
||||
*
|
||||
* @_callback<Function> Callback launched when connection is closed
|
||||
*
|
||||
* @return bound<boolean> Whether the callback has successfully been bound
|
||||
*
|
||||
---------------------------------------------------------*/
|
||||
onclose(_callback){
|
||||
|
||||
/* (0) Parent check */
|
||||
if( !super.onclose(_callback) )
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* (6) Bind event to message reception
|
||||
*
|
||||
* @_callback<Function> Callback launched when a message is received
|
||||
*
|
||||
* @return bound<boolean> Whether the callback has successfully been bound
|
||||
*
|
||||
---------------------------------------------------------*/
|
||||
onreceive(_callback){
|
||||
|
||||
/* (0) Parent check */
|
||||
if( !super.onreceive(_callback) )
|
||||
return false;
|
||||
/* (2) Return success */
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import {ClientDriver} from './client-driver.js'
|
||||
import ClientDriver from './client-driver.js'
|
||||
|
||||
export class XHRClientDriver extends ClientDriver{
|
||||
export default class XHRClientDriver extends ClientDriver{
|
||||
|
||||
|
||||
/* (1) Creates a client driver
|
||||
|
@ -20,9 +20,6 @@ export class XHRClientDriver extends ClientDriver{
|
|||
/* (2) Create useful attributes */
|
||||
this.xhr = null;
|
||||
|
||||
/* (N) Set all is ok */
|
||||
this.error = false;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -51,17 +48,13 @@ export class XHRClientDriver extends ClientDriver{
|
|||
// Got response
|
||||
if( this.xhr.status === 200 ){
|
||||
|
||||
this.callback.onreceive(this.xhr.responseText);
|
||||
this.state = ClientDriver.STATE.CLOSED;
|
||||
this.callback.onclose();
|
||||
this.event.onreceive(this.xhr.responseText);
|
||||
this.event.onclose();
|
||||
|
||||
// Request error
|
||||
}else{
|
||||
}else
|
||||
this.event.onclose();
|
||||
|
||||
this.state = ClientDriver.STATE.CLOSED;
|
||||
this.callback.onclose();
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
|
@ -69,11 +62,11 @@ export class XHRClientDriver extends ClientDriver{
|
|||
|
||||
}.bind(this);
|
||||
|
||||
/* (3) State is now CONNECTED (wrong but ..) */
|
||||
/* (3) State is now CONNECTED (ready to send) */
|
||||
this.state = ClientDriver.STATE.CONNECTED;
|
||||
|
||||
/* (4) Bind to callback onready() */
|
||||
this.callback.onready();
|
||||
/* (4) Bind to callback onconnected() */
|
||||
this.event.onconnected();
|
||||
|
||||
/* (5) Return success */
|
||||
return true;
|
||||
|
@ -97,14 +90,18 @@ export class XHRClientDriver extends ClientDriver{
|
|||
return false;
|
||||
|
||||
/* (2) Error: invalid _request.path */
|
||||
if( typeof _request.path !== 'string' )
|
||||
if( typeof _request.path !== 'string' ){
|
||||
this.state = ClientDriver.STATE.CONNECTED;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* (2) Manage _request.path argument
|
||||
---------------------------------------------------------*/
|
||||
/* (1) Error: invalid path format */
|
||||
if( !/^([A-Z]+) (.+)/i.test(_request.path) )
|
||||
if( !/^([A-Z]+) (.+)/i.test(_request.path) ){
|
||||
this.state = ClientDriver.STATE.CONNECTED;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/* (2) Extract path data */
|
||||
|
@ -145,54 +142,4 @@ export class XHRClientDriver extends ClientDriver{
|
|||
|
||||
}
|
||||
|
||||
|
||||
/* (4) Bind event to connection opened
|
||||
*
|
||||
* @_callback<Function> Callback launched when connection is opened
|
||||
*
|
||||
* @return bound<boolean> Whether the callback has successfully been bound
|
||||
*
|
||||
---------------------------------------------------------*/
|
||||
onready(_callback){
|
||||
|
||||
/* (0) Parent check */
|
||||
if( !super.onready(_callback) )
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* (5) Bind event to connection closed
|
||||
*
|
||||
* @_callback<Function> Callback launched when connection is closed
|
||||
*
|
||||
* @return bound<boolean> Whether the callback has successfully been bound
|
||||
*
|
||||
---------------------------------------------------------*/
|
||||
onclose(_callback){
|
||||
|
||||
/* (0) Parent check */
|
||||
if( !super.onclose(_callback) )
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
|
||||
/* (6) Bind event to message reception
|
||||
*
|
||||
* @_callback<Function> Callback launched when a message is received
|
||||
*
|
||||
* @return bound<boolean> Whether the callback has successfully been bound
|
||||
*
|
||||
---------------------------------------------------------*/
|
||||
onreceive(_callback){
|
||||
|
||||
/* (0) Parent check */
|
||||
if( !super.onreceive(_callback) )
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,81 @@
|
|||
=== USER ===
|
||||
|
||||
>>> POST /user/
|
||||
{
|
||||
username: <String>
|
||||
password: <String>
|
||||
}
|
||||
|
||||
>>> GET /user/:uid
|
||||
{}
|
||||
|
||||
>>> PUT /user/:uid
|
||||
{
|
||||
username: <?String>
|
||||
passowrd: <?String>
|
||||
}
|
||||
|
||||
>>> DELETE /user/:uid
|
||||
{}
|
||||
|
||||
=== USER AUTHENTICATION ===
|
||||
|
||||
>>> POST /user/token
|
||||
{
|
||||
username: <String>
|
||||
password: <String>
|
||||
}
|
||||
|
||||
|
||||
=== CHANNEL ===
|
||||
|
||||
|
||||
>>> POST @token:/channel/
|
||||
{
|
||||
link: <String>
|
||||
name: <String>
|
||||
}
|
||||
|
||||
>>> GET @token:/channel/:cid --> channel specific data
|
||||
>>> GET @token:/channel/ --> all available channels for user
|
||||
{}
|
||||
|
||||
>>> PUT @token:/channel/:cid
|
||||
{
|
||||
link: <?String>
|
||||
name: <?String>
|
||||
}
|
||||
|
||||
>>> DELETE @token:/channel/:cid
|
||||
{}
|
||||
|
||||
|
||||
|
||||
|
||||
=== CHANNEL <> USER ===
|
||||
|
||||
|
||||
>>> POST @token:/channel/:cid/subscribe
|
||||
{}
|
||||
|
||||
>>> DELETE @token:/channel/:cid/subscribe
|
||||
{}
|
||||
|
||||
|
||||
=== ROOM ===
|
||||
|
||||
>>> POST @token:/channel/:cid/room/:type/
|
||||
{
|
||||
name: <String>
|
||||
}
|
||||
|
||||
>>> GET @token:/channel/:cid/room/:type/ --> all channel's rooms of this type
|
||||
|
||||
>>> GET @token:/channel/:cid/room/:type/:rid --> room information of this type
|
||||
|
||||
>>> PUT @token:/channel/:cid/room/:type/:rid
|
||||
{
|
||||
name: <String>
|
||||
}
|
||||
|
||||
>>> DELETE @token:/channel/:cid/room/:type/:rid --> remove room
|
Loading…
Reference in New Issue