discord-client/webpack/lib/api-client.js

217 lines
5.2 KiB
JavaScript
Raw Normal View History

2018-03-21 17:44:27 +00:00
/* classe API */
export default class APIClient{
2018-03-21 17:44:27 +00:00
/* (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
2018-03-21 17:44:27 +00:00
};
this.xhr_stack = []; // Ajax request stack
this.buffer = null; // Last request buffer
2018-03-21 17:44:27 +00:00
}
fix_uri(_uri){
if( typeof _uri !== 'string' )
return '';
return _uri.split('/').filter((r) => r.trim().length).join('/')
2018-03-21 17:44:27 +00:00
}
/* (2) HTTP url dynamic getter
2018-03-21 17:44:27 +00:00
*
* @_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;
}
/* Server Transaction
*
* @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
2018-03-21 17:44:27 +00:00
*
***************************************************************************************************
*
* @usecase
* 1. api.call(
* 2. 'PUT newspaper/article/4'
* 3. { content: "new content" },
* 4. (r) => alert(r.error),
* 5. 'sometoken'
2018-03-21 17:44:27 +00:00
* 6. );
*
*/
call(_path, _args, _callback, _token=null){
2018-03-21 17:44:27 +00:00
/* (1) Argument management
2018-03-21 17:44:27 +00:00
---------------------------------------------------------*/
/* (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); };
2018-03-21 17:44:27 +00:00
/* (2) Check @path format */
if( !/^([A-Z]+) (.+)/i.test(_path) ){
_callback({ error: -1 });
2018-03-21 17:44:27 +00:00
return false;
}
var http_method = RegExp.$1;
var http_uri = RegExp.$2;
/* (3) Default @_token */
if( typeof _token !== 'string' )
_token = null;
2018-03-21 17:44:27 +00:00
/* (3) Create form data
---------------------------------------------------------*/
/* (1) Create virtual form */
var form_data = new FormData();
2018-03-21 17:44:27 +00:00
/* (2) Add attributes */
for( var key in _args ){
2018-03-21 17:44:27 +00:00
// {2.1} If a file -> send as it //
if( _args[key] instanceof File )
form_data.append(key, _args[key]);
2018-03-21 17:44:27 +00:00
// {2.2} Else -> JSON stringify //
else
form_data.append(key, JSON.stringify(_args[key]));
2018-03-21 17:44:27 +00:00
}
/* (4) Create XHR request
---------------------------------------------------------*/
/* (1) Clean ended requests */
for( var i = this.xhr_stack.length-1 ; i >= 0 ; i-- ){
2018-03-21 17:44:27 +00:00
if( this.xhr_stack[i] != null )
2018-03-21 17:44:27 +00:00
break;
this.xhr_stack.pop();
2018-03-21 17:44:27 +00:00
}
/* (2) Push a new entry -> fetch its index */
i = this.xhr_stack.push(null) - 1;
2018-03-21 17:44:27 +00:00
/* (3) Create XHR object */
this.xhr_stack[i] = (window.XMLHttpRequest) ? new XMLHttpRequest() : new ActiveXObject('Microsoft.XMLHttpRequest');
2018-03-21 17:44:27 +00:00
/* (5) Bind response event
---------------------------------------------------------*/
this.xhr_stack[i].onreadystatechange = function(i, parent){
2018-03-21 17:44:27 +00:00
/* (1) If request over */
if( this[i].readyState === 4 ){
2018-03-21 17:44:27 +00:00
/* (2) Update buffer (for debug) */
parent.buffer = this[i].responseText;
2018-03-21 17:44:27 +00:00
/* (3) If request success */
if( [0, 200].indexOf(this[i].status) > -1 ){
2018-03-21 17:44:27 +00:00
/* (3.1) Create default response (if JSON error) */
var response = { error: -2 };
2018-03-21 17:44:27 +00:00
/* (3.2) Try to parse JSON */
try{ response = JSON.parse(this[i].responseText); }catch(e){}
2018-03-21 17:44:27 +00:00
/* (3.3) Launch @_callback with response */
_callback(response);
2018-03-21 17:44:27 +00:00
/* (4) If request error */
}else
_callback({ error: -3 });
2018-03-21 17:44:27 +00:00
/* (5) Notify current xhr instance is done */
this[i] = null;
2018-03-21 17:44:27 +00:00
}
}.bind(this.xhr_stack, i, this);
2018-03-21 17:44:27 +00:00
/* (6) Finish & send request
---------------------------------------------------------*/
/* (1) Open the XHR */
console.log(http_method, this.build_url(http_uri, _token));
this.xhr_stack[i].open(http_method, this.build_url(http_uri, _token), true);
2018-03-21 17:44:27 +00:00
/* (2) Custom header to notify we're using Ajax */
this.xhr_stack[i].setRequestHeader('X-Requested-With', 'XMLHttpRequest');
2018-03-21 17:44:27 +00:00
/* (3) Make the call */
this.xhr_stack[i].send(form_data);
2018-03-21 17:44:27 +00:00
return true;
}
}