Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- 'use strict';
- const express = require('express'),
- bodyParser = require('body-parser'),
- // cors = require('cors'),
- { Client } = require('pg');
- // Setup express
- const app = express();
- // app.use(cors());
- app.use(bodyParser.urlencoded({ extended: true }));
- app.use(bodyParser.json());
- app.set('x-powered-by', false);
- app.set('port', process.env.PORT || 5000);
- app.use(express.static('./public')); // for test purpose
- // Connect to the database
- const client = new Client({
- host: process.env.PGHOST || 'localhost',
- port: process.env.PGPORT || '5432',
- database: process.env.PGDATABASE || 'VirtualRadio',
- user: process.env.PGUSER || 'postgres',
- password: process.env.PGPASSWORD || 'vradio',
- });
- client.connect();
- /*
- Some very interesting stuff:
- http://mherman.org/blog/2015/02/12/postgresql-and-nodejs/#.WbBXENhpxpg
- postgresql port: 5432
- pwd: aron
- /v1/buckets
- /v1/bucket/objects/ --> list of ids
- /v1/bucket/object/:id/ --> download object
- stream object as linear audio ?
- /v1/bucket/object/:id/location
- /v1/bucket/object/:id/metadata
- /v1/sound/:id/metadata
- /v1/sound/:id/marks
- https://musicbrainz.org/doc/Style/Recording
- https://www.discogs.com/developers/
- */
- // Object store API
- // -----------------------------------------------------------------------------
- /// TODO validation perhaps using https://github.com/ctavan/express-validator
- /// https://medium.com/@jeffandersen/building-a-node-js-rest-api-with-express-part-two-9152661bf47
- // Append an objet
- app.post('/v1/object', function(req, res) {
- console.log('PARAMS:');
- console.log(req.params);
- console.log('BODY:');
- console.log(req.body);
- console.log('QUERY:');
- console.log(req.query);
- console.log('-------');
- if (
- typeof req.body.uuid === 'string' &&
- typeof req.body.location === 'string'
- ) {
- // 'metadata' parameter optional
- // var metadata = req.body.metadata || 'NULL';
- client.query(
- 'INSERT INTO objects (uuid, location, created, modified, ' +
- 'metadata, hash) VALUES($1, $2, $3, $4, $5, $6);',
- [
- req.body.uuid,
- req.body.location,
- req.body.created || new Date().toISOString(),
- req.body.modified || new Date().toISOString(),
- req.body.metadata,
- req.body.hash,
- ],
- (err, result) => {
- if (err) {
- res.status(500);
- res.send(err);
- console.log(JSON.stringify(err));
- /// error code, key already existing: 23505 unique_violation
- /*
- {
- "name": "error",
- "length": 249,
- "severity": "ERREUR",
- "code": "23505",
- "detail": "La clé « (uuid)=(d4763006-20af-4bab-bd7a-0201564a1864) » existe déjà.",
- "schema": "public",
- "table": "objects",
- "constraint": "objects_pkey",
- "file": "nbtinsert.c",
- "line": "433",
- "routine": "_bt_check_unique"
- }
- */
- } else {
- res.status(200);
- res.send(result);
- /// result.rowCount
- }
- },
- );
- } else {
- res.status(400);
- res.send({
- result: 'error',
- error: {
- code: 400,
- message: 'invalid or missing parameter(s)',
- },
- });
- }
- });
- // Remove an object
- app.delete('/v1/object/:uuid', function(req, res) {
- if (typeof req.params.uuid === 'string') {
- client.query(
- 'DELETE FROM objects WHERE uuid = $1;',
- [req.params.uuid],
- (err, result) => {
- if (err) {
- res.status(500);
- res.send(err);
- } else {
- res.status(200);
- res.send(result);
- /// result.rowCount
- }
- },
- );
- } else {
- res.status(400);
- }
- });
- app.get('/v1/object', function(req, res) {
- console.log('PARAMS:');
- console.log(req.params);
- console.log('BODY:');
- console.log(req.body);
- console.log('QUERY:');
- console.log(req.query);
- console.log('-------');
- res.setHeader('Access-Control-Allow-Origin', '*');
- if (req.query) {
- let fields = [],
- values = [];
- if (typeof req.query.uuid === 'string') {
- fields.push('uuid');
- values.push(req.query.uuid);
- }
- if (typeof req.query.location === 'string') {
- fields.push('location');
- values.push(req.query.location);
- }
- if (fields.length == 0 || values.length == 0) {
- res.status(400);
- return;
- }
- let sql = 'SELECT * FROM objects WHERE ',
- param = 1;
- for (let n = 0; n < fields.length; ++n) {
- if (n > 0) sql += ' AND ';
- sql += '(' + fields[n] + '=$' + param++ + ')';
- }
- sql += ';';
- client.query(sql, values, (err, queryRes) => {
- if (err) {
- res.status(500).send(err);
- } else {
- res.status(200).send(queryRes.rows[0] || {}); /// return a more complete object in case of not found
- }
- });
- } else {
- res.status(400);
- }
- });
- // Get an object by UUID
- app.get('/v1/object/:uuid', function(req, res) {
- res.setHeader('Access-Control-Allow-Origin', '*');
- if (typeof req.params.uuid === 'string') {
- client.query(
- 'SELECT * FROM objects WHERE uuid = $1;',
- [req.params.uuid],
- (err, queryRes) => {
- if (err) {
- res.status(500).send(err);
- } else {
- res.status(200).send(queryRes.rows[0] || {}); /// return a more complete object in case of not found
- }
- },
- );
- } else {
- res.status(400);
- }
- });
- // Modify an objet
- app.put('/v1/object/:uuid', function(req, res) {
- //// how to handle this case, which parameters are optional ?
- //// if parameter is omitted -> no modification so we need to pass an empty string to delete the content of a parameter ?
- if (
- typeof req.params.uuid === 'string' &&
- typeof req.body.location === 'string'
- ) {
- // 'metadata' parameter optional
- // var metadata = req.body.metadata || 'NULL';
- client.query(
- 'UPDATE objects SET location=$1, metadata=$2, modified=$3, hash=$4 WHERE uuid=$5;',
- [
- req.body.location,
- req.body.metadata,
- req.body.modified || new Date().toISOString(),
- req.body.hash,
- req.params.uuid,
- ],
- (err, result) => {
- if (err) {
- console.log(err);
- res.status(500);
- res.send(err);
- /// error code, key already existing: 23505 unique_violation
- /*
- {
- "name": "error",
- "length": 249,
- "severity": "ERREUR",
- "code": "23505",
- "detail": "La clé « (uuid)=(d4763006-20af-4bab-bd7a-0201564a1864) » existe déjà.",
- "schema": "public",
- "table": "objects",
- "constraint": "objects_pkey",
- "file": "nbtinsert.c",
- "line": "433",
- "routine": "_bt_check_unique"
- }
- */
- } else {
- res.status(200);
- res.send(result);
- /// result.rowCount
- }
- },
- );
- } else {
- res.status(400);
- res.send({
- result: 'error',
- error: {
- code: 400,
- message: 'invalid or missing parameter(s)',
- },
- });
- }
- });
- // Sounds database API
- // -----------------------------------------------------------------------------
- app.post('/v1/sound', function(req, res) {
- console.log('PARAMS:');
- console.log(req.params);
- console.log('BODY:');
- console.log(req.body);
- console.log('QUERY:');
- console.log(req.query);
- console.log('-------');
- if (
- typeof req.body.uuid === 'string' &&
- typeof req.body.obj_uuid === 'string' &&
- typeof req.body.title === 'string'
- ) {
- let duration = req.body.duration || 0,
- cue_in = req.body.cue_in || 0,
- cue_out = req.body.cue_out || duration,
- eff_duration = req.body.eff_duration || duration;
- // 'metadata' parameter optional
- // var metadata = req.body.metadata || 'NULL';
- client.query(
- 'INSERT INTO sounds (uuid, obj_uuid, duration, cue_in, ' +
- 'cue_out, eff_duration, created, modified, title, ' +
- 'artist) VALUES($1, $2, $3, $4, $5, $6, $7, $8, $9, $10);',
- [
- req.body.uuid,
- req.body.obj_uuid,
- duration,
- cue_in,
- cue_out,
- eff_duration,
- req.body.created || new Date().toISOString(),
- req.body.modified || new Date().toISOString(),
- req.body.title,
- req.body.artist,
- ],
- (err, result) => {
- if (err) {
- res.status(500);
- res.send(err);
- console.log(JSON.stringify(err));
- /// error code, key already existing: 23505 unique_violation
- /*
- {
- "name": "error",
- "length": 249,
- "severity": "ERREUR",
- "code": "23505",
- "detail": "La clé « (uuid)=(d4763006-20af-4bab-bd7a-0201564a1864) » existe déjà.",
- "schema": "public",
- "table": "objects",
- "constraint": "objects_pkey",
- "file": "nbtinsert.c",
- "line": "433",
- "routine": "_bt_check_unique"
- }
- */
- } else {
- res.status(200);
- res.send(result);
- /// result.rowCount
- }
- },
- );
- } else {
- res.status(400);
- res.send({
- result: 'error',
- error: {
- code: 400,
- message: 'invalid or missing parameter(s)',
- },
- });
- }
- });
- app.put('/v1/sound/:uuid', function(req, res) {
- console.log('PARAMS:');
- console.log(req.params);
- console.log('BODY:');
- console.log(req.body);
- console.log('QUERY:');
- console.log(req.query);
- console.log('-------');
- if (
- typeof req.body.uuid === 'string' &&
- typeof req.body.obj_uuid === 'string' &&
- typeof req.body.title === 'string'
- ) {
- let duration = req.body.duration || 0,
- cue_in = req.body.cue_in || 0,
- cue_out = req.body.cue_out || duration,
- eff_duration = req.body.eff_duration || duration;
- // 'metadata' parameter optional
- // var metadata = req.body.metadata || 'NULL';
- client.query(
- 'UPDATE sounds SET obj_uuid=$1, duration=$2, cue_in=$3, ' +
- 'cue_out=$4, eff_duration=$5, created=$6, modified=$7, ' +
- 'title=$8, artist=$9 WHERE uuid=$10;',
- [
- req.body.obj_uuid,
- duration,
- cue_in,
- cue_out,
- eff_duration,
- req.body.created || new Date().toISOString(),
- req.body.modified || new Date().toISOString(),
- req.body.title,
- req.body.artist,
- req.body.uuid,
- ],
- (err, result) => {
- if (err) {
- res.status(500);
- res.send(err);
- console.log(JSON.stringify(err));
- /// error code, key already existing: 23505 unique_violation
- /*
- {
- "name": "error",
- "length": 249,
- "severity": "ERREUR",
- "code": "23505",
- "detail": "La clé « (uuid)=(d4763006-20af-4bab-bd7a-0201564a1864) » existe déjà.",
- "schema": "public",
- "table": "objects",
- "constraint": "objects_pkey",
- "file": "nbtinsert.c",
- "line": "433",
- "routine": "_bt_check_unique"
- }
- */
- } else {
- res.status(200);
- res.send(result);
- /// result.rowCount
- }
- },
- );
- } else {
- res.status(400);
- res.send({
- result: 'error',
- error: {
- code: 400,
- message: 'invalid or missing parameter(s)',
- },
- });
- }
- });
- app.get('/v1/sound/search', function(req, res) {
- res.setHeader('Access-Control-Allow-Origin', '*');
- if (req.query.query) {
- // Prepare the query
- let sql =
- 'SELECT sounds.*, objects.location, count(*) OVER() AS total_rows ' +
- 'FROM sounds INNER JOIN objects ON sounds.obj_uuid = ' +
- 'objects.uuid WHERE ',
- paramIdx = 1,
- params = [],
- where = [],
- queries = req.query.query.split(' ');
- queries.forEach(q => {
- where.push(
- '(LOWER(title) LIKE $' +
- paramIdx++ +
- ' OR LOWER(artist) ' +
- 'LIKE $' +
- paramIdx++ +
- ')',
- );
- let pattern = `%${q.trim().toLowerCase()}%`;
- params.push(pattern);
- params.push(pattern);
- });
- for (let n = 0; n < where.length; ++n) {
- if (n > 0) sql += ' AND ';
- sql += where[n];
- }
- sql +=
- ' ORDER BY artist ASC, title ASC LIMIT $' +
- paramIdx++ +
- ' OFFSET $' +
- paramIdx++ +
- ';';
- params.push(req.query.limit || 100);
- params.push(req.query.offset || 0);
- // Run the query
- client.query(sql, params, (err, queryRes) => {
- if (err) {
- res.status(500).send(err);
- } else {
- let answer = {};
- answer.result = 'success';
- answer.totalRowCount = 0;
- answer.rowCount = queryRes.rowCount;
- if (answer.rowCount) {
- answer.totalRowCount = queryRes.rows[0].total_rows;
- // Remove total_rows column from all rows
- queryRes.rows.forEach(row => {
- delete row.total_rows;
- });
- answer.rows = queryRes.rows;
- }
- res.status(200).send(answer);
- }
- });
- } else {
- res.status(400).send({
- result: 'error',
- error: {
- code: 400,
- message: 'invalid or missing parameter(s)',
- },
- });
- }
- });
- app.get('/v1/sound/:uuid', function(req, res) {
- res.setHeader('Access-Control-Allow-Origin', '*');
- if (typeof req.params.uuid === 'string') {
- client.query(
- 'SELECT * FROM sounds WHERE uuid=$1;',
- [req.params.uuid],
- (err, queryRes) => {
- if (err) {
- res.status(500).send(err);
- } else {
- res.status(200).send(queryRes.rows[0] || {});
- }
- },
- );
- } else {
- res.status(400);
- res.send({
- result: 'error',
- error: {
- code: 400,
- message: 'invalid or missing parameter(s)',
- },
- });
- }
- });
- // Error management
- // -----------------------------------------------------------------------------
- // Custom 404 page
- app.use(function(req, res) {
- res.type('text/plain');
- res.status(404);
- res.send('404 - Not Found');
- });
- // Custom 500 page
- app.use(function(err, req, res, next) {
- console.log(err.stack);
- res.type('text/plain');
- res.status(500);
- res.send('500 - Server Error');
- });
- app.listen(app.get('port'), function() {
- console.log('server started on port ' + app.get('port'));
- console.log('Press Ctrl-C to terminate');
- });
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement