// ********************************************************** // 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