added basic rest api
This commit is contained in:
parent
e3a30f9396
commit
0fa7ca78a6
7 changed files with 122 additions and 30 deletions
59
classes/Api.js
Normal file
59
classes/Api.js
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
const AudioServer = require("./AudioServer");
|
||||||
|
|
||||||
|
class Api {
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this.get = new Map();
|
||||||
|
this.post = new Map();
|
||||||
|
this.#setup();
|
||||||
|
}
|
||||||
|
|
||||||
|
async handleRequest(request) {
|
||||||
|
if (request === undefined) {
|
||||||
|
return this.#createRequestResult(500);
|
||||||
|
}
|
||||||
|
const fn = this.#getFunction(request.url, request.method.toLowerCase());
|
||||||
|
if (fn === undefined) {
|
||||||
|
return this.#createRequestResult(501);
|
||||||
|
}
|
||||||
|
await fn();
|
||||||
|
return this.#createRequestResult();
|
||||||
|
}
|
||||||
|
|
||||||
|
#createRequestResult(code, message) {
|
||||||
|
if (code === undefined) {
|
||||||
|
code = 200;
|
||||||
|
}
|
||||||
|
const result = {
|
||||||
|
code: code
|
||||||
|
};
|
||||||
|
if (message !== undefined) {
|
||||||
|
result.message = message;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
#setup() {
|
||||||
|
this.#registerEndpoint(constants.API_PLAY, constants.REQUEST_METHOD_POST, () => {
|
||||||
|
new AudioServer('/mnt/kingston/public/LEFTOVER.flac');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#getFunction(url, method) {
|
||||||
|
if (url === undefined || method === undefined || this[method] === undefined) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
return this[method].get(url);
|
||||||
|
}
|
||||||
|
|
||||||
|
#registerEndpoint(url, method, fn) {
|
||||||
|
if (url === undefined || method === undefined || fn === undefined || this[method] === undefined) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
this[method].set(url, fn);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = Api;
|
43
classes/ApiServer.js
Normal file
43
classes/ApiServer.js
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
const Api = require('./Api.js');
|
||||||
|
const http = require('http');
|
||||||
|
|
||||||
|
class ApiServer {
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this.listen = config.api?.listen || "0.0.0.0";
|
||||||
|
this.port = config.api?.port || 9000;
|
||||||
|
this.api = new Api();
|
||||||
|
this.server = http.createServer();
|
||||||
|
this.requestId = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
start() {
|
||||||
|
return new Promise((resolve, reject) => {
|
||||||
|
this.server.listen(this.port, this.listen).on('listening', () => {
|
||||||
|
this.port = this.server.address().port;
|
||||||
|
logger.info('api server listening on ' + this.listen + ':' + this.port + '...');
|
||||||
|
this.#handleRequests();
|
||||||
|
resolve();
|
||||||
|
});
|
||||||
|
this.server.on('error', (err) => {
|
||||||
|
reject('an unexpected error occured: ' + err);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#handleRequests() {
|
||||||
|
this.server.on('request', async (request, response) => {
|
||||||
|
request.timestamp = Date.now();
|
||||||
|
request.id = this.requestId;
|
||||||
|
this.requestId++;
|
||||||
|
logger.debug('handling api request #' + request.id + ' \'' + request.url + '\'...');
|
||||||
|
const result = await this.api.handleRequest(request);
|
||||||
|
response.writeHead(result.code);
|
||||||
|
response.end(result.message);
|
||||||
|
logger.debug('handling api request #' + request.id + '\'' + request.url + '\' took ' + (Date.now() - request.timestamp) + 'ms');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = ApiServer;
|
|
@ -48,30 +48,6 @@ class Logger {
|
||||||
this.timestamp = value || 'DD.MM.YYYY HH:mm:ss:SS';
|
this.timestamp = value || 'DD.MM.YYYY HH:mm:ss:SS';
|
||||||
}
|
}
|
||||||
|
|
||||||
// log a http request - response object
|
|
||||||
http(object) {
|
|
||||||
if (object === undefined) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
let message = '[' + object.request.method + ':' + object.code + '] url: \'' + object.request.url + '\'';
|
|
||||||
let counter = 1;
|
|
||||||
for (let param in object.request.body) {
|
|
||||||
message += ', parameter ' + counter + ': \'' + param + '=' + object.request.body[param] + '\'';
|
|
||||||
counter++;
|
|
||||||
}
|
|
||||||
if (object.request.timestamp) {
|
|
||||||
message += ' > ' + (new Date().getTime() - object.request.timestamp) + 'ms';
|
|
||||||
}
|
|
||||||
if (object.data) {
|
|
||||||
message += ' > data: ' + object.data;
|
|
||||||
}
|
|
||||||
if (object.code != 200) {
|
|
||||||
error(message.trim());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
this.debug(message.trim());
|
|
||||||
}
|
|
||||||
|
|
||||||
// prefix log with 'info'
|
// prefix log with 'info'
|
||||||
info(message) {
|
info(message) {
|
||||||
if (this.loglevel > LOGLEVEL_INFO) {
|
if (this.loglevel > LOGLEVEL_INFO) {
|
||||||
|
|
|
@ -1,8 +1,6 @@
|
||||||
const net = require('net');
|
|
||||||
|
|
||||||
const Client = require('./Client.js');
|
const Client = require('./Client.js');
|
||||||
|
|
||||||
const AudioServer = require('./AudioServer.js');
|
const AudioServer = require('./AudioServer.js');
|
||||||
|
const net = require('net');
|
||||||
|
|
||||||
class Server {
|
class Server {
|
||||||
|
|
||||||
|
@ -18,6 +16,7 @@ class Server {
|
||||||
this.server.listen(this.port, this.listen).on('listening', () => {
|
this.server.listen(this.port, this.listen).on('listening', () => {
|
||||||
this.port = this.server.address().port;
|
this.port = this.server.address().port;
|
||||||
logger.info('communication server listening on ' + this.listen + ':' + this.port + '...');
|
logger.info('communication server listening on ' + this.listen + ':' + this.port + '...');
|
||||||
|
resolve();
|
||||||
});
|
});
|
||||||
this.server.on('connection', (socket) => {
|
this.server.on('connection', (socket) => {
|
||||||
this.#addClient(socket);
|
this.#addClient(socket);
|
||||||
|
@ -44,7 +43,6 @@ class Server {
|
||||||
|
|
||||||
#addClient(socket) {
|
#addClient(socket) {
|
||||||
this.clients.push(new Client(socket));
|
this.clients.push(new Client(socket));
|
||||||
new AudioServer('/mnt/kingston/public/DOPESMOKER.flac');
|
|
||||||
}
|
}
|
||||||
|
|
||||||
removeClient(client) {
|
removeClient(client) {
|
||||||
|
|
|
@ -5,6 +5,11 @@
|
||||||
"port": 3000,
|
"port": 3000,
|
||||||
"heartbeat": 10000
|
"heartbeat": 10000
|
||||||
},
|
},
|
||||||
|
"api": {
|
||||||
|
"enabled": true,
|
||||||
|
"listen": "0.0.0.0",
|
||||||
|
"port": 9000
|
||||||
|
},
|
||||||
"log": {
|
"log": {
|
||||||
"level": "debug",
|
"level": "debug",
|
||||||
"timestamp": "DD.MM.YYYY HH:mm:ss:SS"
|
"timestamp": "DD.MM.YYYY HH:mm:ss:SS"
|
||||||
|
@ -22,7 +27,7 @@
|
||||||
"password": "kannon"
|
"password": "kannon"
|
||||||
},
|
},
|
||||||
"audio": {
|
"audio": {
|
||||||
"threshold": 30,
|
"threshold": 10,
|
||||||
"bufferlimit": 64
|
"bufferlimit": 64
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -8,6 +8,7 @@ const Database = require('./classes/Database.js');
|
||||||
const Queue = require('./classes/Queue.js');
|
const Queue = require('./classes/Queue.js');
|
||||||
const Watcher = require('./classes/Watcher.js');
|
const Watcher = require('./classes/Watcher.js');
|
||||||
const EventParser = require('./classes/EventParser');
|
const EventParser = require('./classes/EventParser');
|
||||||
|
const ApiServer = require('./classes/ApiServer.js');
|
||||||
|
|
||||||
const INTERRUPTS = ['beforeExit', 'SIGINT', 'SIGTERM'];
|
const INTERRUPTS = ['beforeExit', 'SIGINT', 'SIGTERM'];
|
||||||
|
|
||||||
|
@ -36,6 +37,11 @@ async function main() {
|
||||||
global.server = new Server();
|
global.server = new Server();
|
||||||
await global.server.start();
|
await global.server.start();
|
||||||
}
|
}
|
||||||
|
// api server
|
||||||
|
if (util.isEnabled(global.config.api)) {
|
||||||
|
global.apiserver = new ApiServer();
|
||||||
|
global.apiserver.start();
|
||||||
|
}
|
||||||
// queue and watcher
|
// queue and watcher
|
||||||
if (util.isEnabled(global.config.library)) {
|
if (util.isEnabled(global.config.library)) {
|
||||||
global.queue = new Queue();
|
global.queue = new Queue();
|
||||||
|
|
|
@ -10,5 +10,10 @@ module.exports = {
|
||||||
CLIENT_STATE_PLAYING: 'playing',
|
CLIENT_STATE_PLAYING: 'playing',
|
||||||
CLIENT_STATE_PAUSED: 'paused',
|
CLIENT_STATE_PAUSED: 'paused',
|
||||||
CLIENT_STATE_STOPPED: 'stopped',
|
CLIENT_STATE_STOPPED: 'stopped',
|
||||||
CLIENT_STATE_ERROR: 'error'
|
CLIENT_STATE_ERROR: 'error',
|
||||||
|
|
||||||
|
REQUEST_METHOD_GET: 'get',
|
||||||
|
REQUEST_METHOD_POST: 'post',
|
||||||
|
|
||||||
|
API_PLAY: '/play'
|
||||||
}
|
}
|
Loading…
Reference in a new issue