[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:
xdrm-brackets 2018-03-24 15:13:27 +01:00
parent 1cedd6284a
commit a1a5610f2c
6 changed files with 372 additions and 255 deletions

View File

@ -1,3 +1,4 @@
import {APIClient} from './lib/api-client'
import {GlobalStore} from './lib/gstore' import {GlobalStore} from './lib/gstore'
import VueRouter from 'vue-router' import VueRouter from 'vue-router'
import routes from './routes' import routes from './routes'
@ -6,8 +7,14 @@ import {ContentController} from './lib/content-controller'
import {RoomController} from './lib/room-controller' import {RoomController} from './lib/room-controller'
import {ChannelController} from './lib/channel-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.gs = new GlobalStore();
window.api = new APIClient('localhost', null, false);
window.xhrcd = XHRClientDriver;
window.wscd = WebSocketClientDriver;
/* (1) Global data /* (1) Global data
---------------------------------------------------------*/ ---------------------------------------------------------*/

View File

@ -1,81 +1,142 @@
/* classe API */ /* classe API */
export class APIClient{ export class APIClient{
constructor(target){
this.target = target;
this.xhr = []; // tableau d'objets pour les requêtes ajax /* (1) Constructs an API client manager
this.buffer = null; // Contiendra le buffer pour debugger si erreur de parsage *
this.error = { // error constants * @_hostname<String> Server hostname (without http, port number, etc)
'-1': 'Invalid target format: "METHOD module/method"', * @_baseuri<String> Server base URI
'-2': 'XHR error', * @_ssl<bool> [OPT] Whether SSL is activated (http vs https) (default: https)
'-3': 'Invalid JSON response', * @_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 _path<String> target path (format "HTTP_METHOD uri/uri/uri")
* @param pArgs<Object> Le tableu d'arguments passé en POST (attribut<->postfield) à http://{host}/api/ * @param _args<Object> formdata object (as raw object)
* @param pHandler<Function> Fonction qui s'éxécutera lors de la réponse (1 argument -> réponse<Object>) * @param _callback<Function> Response callback
* @param pToken<String> Optionnel, token d'auth pour l'api * @param _token<String> [OPT] http token
* *
*************************************************************************************************** ***************************************************************************************************
* *
* @usecase * @usecase
* 1. api.call( * 1. api.call(
* 2. "PUT newspaper/article/4" * 2. 'PUT newspaper/article/4'
* 2. { content: "New article content" }, * 3. { content: "new content" },
* 3. function(resp){ * 4. (r) => alert(r.error),
* 4. alert(resp.error); * 5. 'sometoken'
* 5. }
* 6. ); * 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 */ /* (1) Set default callback if @callback not callable */
if( !(pHandler instanceof Function) ) if( !(_callback instanceof Function) )
throw new Error("3rd argument must be a function, but is of type '"+typeof(pHandler)+"' !"); _callback = function(r){ console.warn('The API callback function is missing, default callback set.', 'Response', r); };
/* (2) Check @path format */
if( !/^([A-Z]+) (.+)/i.test(_path) ){
/* (2) Check @pTarget _callback({ error: -1 });
---------------------------------------------------------*/
/* (1) Check format */
if( !/^([A-Z]+) (.+)/i.test(pTarget) ){
pHandler({ error: -1, ErrorDescription: this.error['-1'] });
return false; return false;
} }
/* (2) Store locally data */ var http_method = RegExp.$1;
var lHttpMethod = RegExp.$1; var http_uri = RegExp.$2;
var lUri = RegExp.$2;
/* (3) Default @_token */
if( typeof _token !== 'string' )
_token = null;
/* (3) Create form data /* (3) Create form data
---------------------------------------------------------*/ ---------------------------------------------------------*/
/* (1) Create virtual form */ /* (1) Create virtual form */
var lForm = new FormData(); var form_data = new FormData();
/* (2) Add attributes */ /* (2) Add attributes */
for( var key in pArgs ){ for( var key in _args ){
// {2.1} If a file -> send as it // // {2.1} If a file -> send as it //
if( pArgs[key] instanceof File ) if( _args[key] instanceof File )
lForm.append(key, pArgs[key]); form_data.append(key, _args[key]);
// {2.2} Else -> JSON stringify // // {2.2} Else -> JSON stringify //
else 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 /* (4) Create XHR request
---------------------------------------------------------*/ ---------------------------------------------------------*/
/* (1) Clean ended requests */ /* (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; break;
this.xhr.pop(); this.xhr_stack.pop();
} }
/* (2) Push a new entry -> fetch its index */ /* (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 */ /* (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 /* (5) Bind response event
---------------------------------------------------------*/ ---------------------------------------------------------*/
var self = this; // to access the buffer this.xhr_stack[i].onreadystatechange = function(i, parent){
this.xhr[i].onreadystatechange = function(i){
/* (1) If request over */ /* (1) If request over */
if( this.xhr[i].readyState == 4 ){ if( this[i].readyState === 4 ){
/* (2) Update buffer (for debug) */ /* (2) Update buffer (for debug) */
self.buffer = this.xhr[i].responseText; parent.buffer = this[i].responseText;
/* (3) If request success */ /* (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) */ /* (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 */ /* (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 */ /* (3.3) Launch @_callback with response */
pHandler(response); _callback(response);
/* (4) If request error */ /* (4) If request error */
}else }else
pHandler({ error:-2, ErrorDescription: self.error['-2'] }); _callback({ error: -3 });
/* (5) Notify current xhr instance is done */ /* (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 /* (6) Finish & send request
---------------------------------------------------------*/ ---------------------------------------------------------*/
/* (1) Open the XHR */ /* (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 */ /* (2) Custom header to notify we're using Ajax */
if( pToken != null ) this.xhr_stack[i].setRequestHeader('X-Requested-With', 'XMLHttpRequest');
this.xhr[i].setRequestHeader('Authorization', 'Digest '+pToken);
/* (3) Custom header to notify we're using Ajax */ /* (3) Make the call */
this.xhr[i].setRequestHeader('X-Requested-With', 'XMLHttpRequest'); this.xhr_stack[i].send(form_data);
/* (4) Make the call */
this.xhr[i].send( lForm );
return true; return true;

View File

@ -1,15 +1,15 @@
export class ClientDriver{ export default class ClientDriver{
/* (0) Constants & Enums /* (0) Constants & Enums
---------------------------------------------------------*/ ---------------------------------------------------------*/
static get STATE(){ static get STATE(){
return Object.freeze({ return Object.freeze({
OPENING: 0, CLOSED: 0,
OPENED: 1, READY: 1,
CONNECTING: 2, CONNECTING: 2,
CONNECTED: 3, CONNECTED: 3,
CLOSED: 4 TRANFERING: 4
}); });
} }
@ -22,27 +22,81 @@ export class ClientDriver{
---------------------------------------------------------*/ ---------------------------------------------------------*/
constructor(_resource){ constructor(_resource){
/* (1) Initialize driver
---------------------------------------------------------*/
/* (1) Default attributes values */ /* (1) Default attributes values */
this.error = false; this.force_close = false;
this.state = ClientDriver.STATE.OPENING; this.state = ClientDriver.STATE.READY;
this.stack = []; this.stack = [];
/* (2) Default User callbacks */
this.callback = { this.callback = {
onready: function(){}, onconnected: function(){},
onclose: function(){}, onclose: function(){},
onreceive: 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' ) if( typeof _resource !== 'string' )
return ( this.error = true ); return ( this.error = true );
/* (3) Set explicit attributes */ /* (2) Set explicit attributes */
this.resource = _resource; this.resource = _resource;
return; return;
} }
/* (2) Binds the client to the resource /* (2) Binds the client to the resource
* *
* @return bound<boolean> Whether the binding has been successful * @return bound<boolean> Whether the binding has been successful
@ -50,17 +104,43 @@ export class ClientDriver{
---------------------------------------------------------*/ ---------------------------------------------------------*/
bind(){ bind(){
/* (1) Fail: not OPENING OR error */ /* (1) force_close -> fail */
if( this.error || this.state !== ClientDriver.STATE.OPENING ) if( this.force_close )
return false; 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; 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 * @_request<Object> Request data
* *
@ -69,111 +149,99 @@ export class ClientDriver{
---------------------------------------------------------*/ ---------------------------------------------------------*/
send(_request){ send(_request){
/* (1) Fail: if error */ /* (1) force_close -> fail */
if( this.error ) if( this.force_close )
return false; return false;
/* (2) Fail: invalid _request */ /* (2) bufferise 'state' */
let state = this.state;
/* (3) Fail: invalid _request */
if( !(_request instanceof Object) ) if( !(_request instanceof Object) )
return false; return false;
/* (3) If not already connected -> stack request */ /* (4) CLOSED -> abort */
if( this.state < ClientDriver.STATE.CONNECTED ){ if( state === ClientDriver.STATE.CLOSED )
this.stack.push(_request);
return false; 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; return true;
} }
/* (4) Bind event to connection opened /* (5) Bind event to connection successfully opened
* *
* @_callback<Function> Callback launched when connection is opened * @_callback<Function> Callback launched when connection is opened
* *
* @return bound<boolean> Whether the callback has successfully been bound * @return bound<boolean> Whether the callback has successfully been bound
* *
---------------------------------------------------------*/ ---------------------------------------------------------*/
onready(_callback){ set onconnected(_callback){
/* (1) Fail: already CONNECTED OR error */ /* (1) Fail: invalid _callback */
if( this.error || this.state >= ClientDriver.STATE.CONNECTED )
return false;
/* (2) Fail: invalid _callback */
if( !(_callback instanceof Function) ) if( !(_callback instanceof Function) )
return false; return false;
/* (3) Register _callback */ /* (2) Register _callback */
this.callback.onready = function(cback){ this.callback.onconnected = _callback;
// call callback /* (3) By default return success */
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 */
return true; return true;
} }
/* (5) Bind event to connection closed /* (6) Bind event to connection closed
* *
* @_callback<Function> Callback launched when connection is closed * @_callback<Function> Callback launched when connection is closed
* *
* @return bound<boolean> Whether the callback has successfully been bound * @return bound<boolean> Whether the callback has successfully been bound
* *
---------------------------------------------------------*/ ---------------------------------------------------------*/
onclose(_callback){ set onclose(_callback){
/* (1) Fail: already CLOSED OR error */ /* (1) Fail: invalid _callback */
if( this.error || this.state === ClientDriver.STATE.CLOSED )
return false;
/* (2) Fail: invalid _callback */
if( !(_callback instanceof Function) ) if( !(_callback instanceof Function) )
return false; return false;
/* (3) Register _callback */ /* (2) Register _callback */
this.callback.onclose = _callback; this.callback.onclose = _callback;
/* (4) By default return success */ /* (3) By default return success */
return true; return true;
} }
/* (6) Bind event to message reception /* (7) Bind event to message reception
* *
* @_callback<Function> Callback launched when a message is received * @_callback<Function> Callback launched when a message is received
* *
* @return bound<boolean> Whether the callback has successfully been bound * @return bound<boolean> Whether the callback has successfully been bound
* *
---------------------------------------------------------*/ ---------------------------------------------------------*/
onreceive(_callback){ set onreceive(_callback){
/* (1) Fail: already CONNECTED OR error */ /* (1) Fail: invalid _callback */
if( this.error || this.state >= ClientDriver.STATE.CONNECTED )
return false;
/* (2) Fail: invalid _callback */
if( !(_callback instanceof Function) ) if( !(_callback instanceof Function) )
return false; return false;
/* (3) Register _callback */ /* (2) Register _callback */
this.callback.onreceive = _callback; this.callback.onreceive = _callback;
/* (4) By default return success */ /* (3) By default return success */
return true; return true;
} }

View File

@ -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 /* (1) Creates a client driver
@ -21,9 +21,6 @@ export class WebSocketClientDriver extends ClientDriver{
this.ws = null; this.ws = null;
this.buffer = null; // useful when waiting for WebSocket to open 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); this.ws = new WebSocket(this.resource);
/* (2) Bind callback.onready */ /* (2) Bind callback.onready */
this.ws.onopen = function(){ this.ws.onopen = this.event.onconnected;
this.state = ClientDriver.STATE.CONNECTED;
this.callback.onready();
}.bind(this);
/* (3) Bind callback.onclose */ /* (3) Bind callback.onclose */
this.ws.onclose = function(){ this.ws.onclose = this.event.onclose;
this.state = ClientDriver.STATE.CLOSED;
this.callback.onclose();
}.bind(this);
/* (4) Bind callback.onerror */ /* (4) Bind callback.onerror */
this.ws.onerror = function(){ this.ws.onerror = this.event.onclose;
this.state = ClientDriver.STATE.CLOSED;
this.callback.onclose();
}.bind(this);
/* (5) Bind callback.onreceive */ /* (5) Bind callback.onreceive */
this.ws.onmessage = function(response){ this.ws.onmessage = (_message_event) => this.event.onreceive(_message_event.data);
this.state = ClientDriver.STATE.CONNECTED;
this.callback.onreceive(response);
}.bind(this);
/* (6) Return success */ /* (6) Return success */
return true; return true;
@ -85,11 +70,12 @@ export class WebSocketClientDriver extends ClientDriver{
return false; return false;
/* (1) Error: invalid _request.buffer */ /* (1) Error: invalid _request.buffer */
if( typeof _request.buffer !== 'string' ) if( typeof _request.buffer !== 'string' ){
this.state = ClientDriver.STATE.CONNECTED;
return false; return false;
}
/* (2) Send message */ /* (2) Send message */
console.log('sent', _request.buffer);
this.ws.send(_request.buffer); this.ws.send(_request.buffer);
/* (3) Return success */ /* (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 closed<boolean> Whether the connection has been closed
*
* @return bound<boolean> Whether the callback has successfully been bound
* *
---------------------------------------------------------*/ ---------------------------------------------------------*/
onready(_callback){ close(){
/* (0) Parent check */ /* (0) Parent check */
if( !super.onready(_callback) ) if( !super.close() )
return false; return false;
} /* (1) Close websocket */
this.ws.close();
/* (2) Return success */
/* (5) Bind event to connection closed return true;
*
* @_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;
} }

View File

@ -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 /* (1) Creates a client driver
@ -20,9 +20,6 @@ export class XHRClientDriver extends ClientDriver{
/* (2) Create useful attributes */ /* (2) Create useful attributes */
this.xhr = null; this.xhr = null;
/* (N) Set all is ok */
this.error = false;
} }
@ -51,17 +48,13 @@ export class XHRClientDriver extends ClientDriver{
// Got response // Got response
if( this.xhr.status === 200 ){ if( this.xhr.status === 200 ){
this.callback.onreceive(this.xhr.responseText); this.event.onreceive(this.xhr.responseText);
this.state = ClientDriver.STATE.CLOSED; this.event.onclose();
this.callback.onclose();
// Request error // Request error
}else{ }else
this.event.onclose();
this.state = ClientDriver.STATE.CLOSED;
this.callback.onclose();
}
break; break;
} }
@ -69,11 +62,11 @@ export class XHRClientDriver extends ClientDriver{
}.bind(this); }.bind(this);
/* (3) State is now CONNECTED (wrong but ..) */ /* (3) State is now CONNECTED (ready to send) */
this.state = ClientDriver.STATE.CONNECTED; this.state = ClientDriver.STATE.CONNECTED;
/* (4) Bind to callback onready() */ /* (4) Bind to callback onconnected() */
this.callback.onready(); this.event.onconnected();
/* (5) Return success */ /* (5) Return success */
return true; return true;
@ -97,14 +90,18 @@ export class XHRClientDriver extends ClientDriver{
return false; return false;
/* (2) Error: invalid _request.path */ /* (2) Error: invalid _request.path */
if( typeof _request.path !== 'string' ) if( typeof _request.path !== 'string' ){
this.state = ClientDriver.STATE.CONNECTED;
return false; return false;
}
/* (2) Manage _request.path argument /* (2) Manage _request.path argument
---------------------------------------------------------*/ ---------------------------------------------------------*/
/* (1) Error: invalid path format */ /* (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; return;
}
/* (2) Extract path data */ /* (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;
}
} }

81
webpack/mockup/api.list Normal file
View File

@ -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