You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

240 lines
8.7 KiB

// **********************************************************
// minimal restful api with mariadb connection
// extended from basic
// references
// https://mariadb.com/kb/en/nodejs-connector/
// uses mariadb
// **********************************************************
// sur base l'exemple de cours :
// https://git.polux.studio/Juan/cours-MDS/src/branch/master/b3-dev/node/session2/mariadb/server.js
// Reqs and defines
const http = require ('http'); // to create server
const url = require('url'); // to parse url
const BASIC_API_PORT = 3998;
//user database and password
const MARIADB_PSWD = "ov62p67t7PId9N3",
MARIADB_USER = "eval_db_user",
MARIADB_HOST = "127.0.0.1",
MARIADB_PORT = "3306",
MARIADB_NAME = "eval_db";
//require mariadb module
const mariadb = require('mariadb');
//create a pool
const pool = mariadb.createPool({
host: MARIADB_HOST,
user: MARIADB_USER,
password: MARIADB_PSWD,
port: MARIADB_PORT, // optional
database: MARIADB_NAME, // optional
connectionLimit: 5
});
// *************************************************************
// create basic server and implement handling different requests
const app = http.createServer
(
async (req, res) =>
{
// parse the incoming url
const parsedURL = url.parse(req.url, true);
//prepare global response
var response_text = "";
//a bit of followup of client requests
console.log('called with path : '+parsedURL.pathname);
console.log('called with method : '+req.method);
// ------------------------------------------------------------------------
// list tables
if(parsedURL.pathname.startsWith('/api/tables') && req.method === 'GET')
{
//create a temp local scope connection
let cnx;
// use try catch to get errors
try
{
cnx = await pool.getConnection();
const tables = await cnx.query("SHOW TABLES;");
response_text += tables.length+" table"+(tables.length===1?"":"s");
console.log(' found '+response_text+' to list');
if(tables.length > 0)
{
Object.keys(tables).forEach(function(key) {
var row = tables[key];
// meta holds the global response info...
// we don't really need it ... for now.
if(key !== 'meta')
{
response_text += "\n - "+row['Tables_in_'+MARIADB_NAME];
}
});
}
}
catch(err)
{
console.log('ERROR');
res.statusCode = 400;
res.end("something went wrong");
if(cnx)
{
return cnx.end();
}
throw(err);
}
finally
{
res.statusCode = 200;
res.end(response_text);
if(cnx)
{
return cnx.end();
}
}
}
// ------------------------------------------------------------------------
// if we want to list data of a specific table
if(parsedURL.pathname.startsWith('/api/table/') && req.method === 'GET')
{
table_name = extractLastItem(parsedURL.pathname);
console.log('listing '+table_name);
//create a temp local scope connection
let cnx;
try
{
cnx = await pool.getConnection();
const table_rows = await cnx.query("SELECT * FROM "+table_name+";");
response_text += table_rows.length+" row"+(table_rows.length===1?"":"s");
console.log(' found '+response_text+' to list');
header_done=false;
if(table_rows.length > 0)
{
dashline = "";
Object.keys(table_rows).forEach(function(key) {
var row = table_rows[key];
console.log(key);
// meta holds the global response info...
// we don't really need it ... for now.
if(key !== 'meta')
{
response_text += "\n ";
//response_text += JSON.stringify(row);
if(!header_done) {
dashline = "\n +"+'-'.repeat(Object.keys(row).length * 23 -2)+'-+ ';
response_text += dashline +"\n ";
Object.keys(row).forEach(function(fieldkey) {
response_text += ' + ' + fieldkey.substring(0,20).padEnd(20,' ');
});
response_text += ' + '
response_text += dashline;
response_text += "\n ";
header_done=true;
}
Object.keys(row).forEach(function(fieldkey) {
console.log(fieldkey);
response_text += ' | '+ row[fieldkey].toString().substring(0,20).padEnd(20,' ');
});
response_text += ' | ';
}
});
response_text += dashline;
}
}
catch(err)
{
console.log('ERROR');
res.statusCode = 400;
res.end("something went wrong");
if(cnx)
{
return cnx.end();
}
throw(err);
}
finally
{
res.statusCode = 200;
res.end(response_text);
if(cnx)
{
return cnx.end();
}
}
}
// ------------------------------------------------------------------------
if(parsedURL.pathname.startsWith('/api/table') && req.method === 'DELETE')
{
table_name = extractLastItem(parsedURL.pathname);
console.log('deleting in '+table_name);
//get the get param
row_to_del = parseInt(parsedURL.query.row);
console.log('deleting row '+row_to_del);
let cnx;
try
{
cnx = await pool.getConnection();
queryresult= await cnx.query("DELETE FROM "+table_name+" WHERE id_"+table_name+"='"+row_to_del+"';");
console.log('query result : '+JSON.stringify(queryresult));
if(parseInt(queryresult.affectedRows) === 0) {
response_text="No matching row found. Does it exist ?";
}
else {
response_text= queryresult.affectedRows+" row(s) deleted";
}
}
catch(err)
{
console.log('ERROR');
res.statusCode = 400;
res.end("something went wrong");
if(cnx)
{
return cnx.end();
}
throw(err);
}
finally
{
res.statusCode = 200;
res.end(response_text);
if(cnx)
{
return cnx.end();
}
}
}
// else if this is a simple get
if (parsedURL.pathname.startsWith('/api') && req.method === 'GET')
{
res.statusCode = 200;
res.end("You got me !");
}
// if url doent match any send error
else
{
res.statusCode = 400;
res.end("API Endpoint Not Supported");
}
}
);
// EOF create server.
// call server specifying on wich port to listen
app.listen(BASIC_API_PORT);
console.log('Mariadb RESTful API server started on: ' + BASIC_API_PORT);
// *************************************************
// define internal functions
// -------------------------------------------------
// get last item of path used as param of request
function extractLastItem(path)
{
return path.substring(path.lastIndexOf("/")+1,path.length);
}
// EOF extractIPAddress