Error POST http:abc/ 404 (Not Found) in angular2+ and nodejs - mysql

I am making a http request from my angular2+ code to database present in node.js file. The ajax call from angular2+ hits the controller.js file and then redirects to service.js file which has the connection to the database:
angular.ts ==> controller.js ==> service.js
From the database the service.js file gives the output to controller.js file and then answers the ajax call to angular.ts file:
service.js ==> controller.js ==> angular.ts
However, I am getting the error:
POST http://localhost:8096/dashboard/abcEntireSuccess1/ 404 (Not Found)
UPDATED
Cannot GET /dashboard/experianEntireSuccess1/
And one more issue -
UnauthorizedError: No authorization token was found
And one more issue -
After coming back from the hit in service.js which has the data i want ==> to => controller.js , here the data is acquired is undefined. As seen below -
The output on Nodejs -
output -
service.js
closed connection
yessss [ RowDataPacket { ....
controller.js
we are coming back to controller undefined
some error occured of abcEntireSuccess1
My Entire Code:
UPDATED
abc.component.ts
viewAbcEntireSuccess1() {
var url = config.url;
var port = config.port;
this.http.post("http://" + url + ":" + port + "/dashboard
/abcEntireSuccess1/", this.emptyObj
, { headers: new Headers({ 'Authorization': 'Bearer ' +
localStorage.getItem('Token') }) })
.map(resultConnection => this.resultConnection =
resultConnection.json(), )
.subscribe((res: Response) => {
this.records = res;
this.resultConnectionlength = this.resultConnection.length;
});
}
abc.controller.js
router.post('/experianEntireSuccess1',experianEntireSuccess1);
module.exports = router;
function abcEntireSuccess1(req, res) {
dashboardService.abcEntireSuccess1(req.body)
.then(function (result) {
console.log("we are coming back to controller",result)
if (result.length > 0) {
console.log("we get data in node of abcEntireSuccess1 ::
" + Object.values(result));
console.log(result.length + " record found ");
res.send(result);
}
else {
result=[];
res.send(result);
}
})
.catch(function (err) {
res.status(400).send(err);
console.log("some error occured of abcEntireSuccess1");
});
}
abc.service.js
async function abcEntireSuccess1() {
console.log("function called")
const db = new Database();
await db.query(`select * from TRANSACTION_PAYLOAD where INTERFACE_NAME
= 'Abc' AND (STATUS ='SUCCESS_RESPONSE')`
).then(rows => {
console.log("closed connection");
console.log("yessss",rows)
return rows;
});
};
class Database {
constructor() {
this.connection = mysql.createConnection({
host: "127.0.0.1",
user: "abc",
password: "abc",
database: "DB"
});
}
query(sql, args) {
console.log("sql is", sql)
return new Promise((resolve, reject) => {
this.connection.query(sql, (err, rows) => {
console.log("connection function called")
if (err) {
console.log("error is", err)
return reject(err);
}
console.log("rows are",rows);
resolve(rows);
});
});
}
close() {
console.log("calling connection close")
return new Promise((resolve, reject) => {
console.log("called connection close")
this.connection.end(err => {
if (err){
return reject(err);
}
resolve();
});
});
}
}

Related

TypeError: Cannot read properties of undefined (reading 'filename') in multer

I have a very similar problem with respect to this fellow community contributor. How do i produce multer error message in my postman I followed through the comments made by other users and it was successful! However, when i tried to post a image that is a jpg formatted image( which i managed to do before the editing), it now fails and state that TypeError: Cannot read property 'filename' of undefined.
// multer.js file
successfully setup multer
**please tell me why this error comes on my code and give me a solution**
const multer = require('multer');
const storage = multer.diskStorage({
fileSize: 1024*1024*2,
destination: function (req, file, cb) {
cb(null, './uploads')
},
filename: function (req, file, cb) {
const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1E9)
cb(null, file.fieldname + '-' + uniqueSuffix)
}
})
const filter = function (req, file, cb) {
if (file.mimetype === 'image/jpeg' || file.mimetype === 'image/png') {
cb(null, true);
} else {
cb(new Error('unsupported files'), false)
}
}
var upload = multer({
storage: storage,
limits: {
fileSize: 1024 * 1024 * 5
},
fileFilter : filter
});
module.exports = upload;
//controller.js file
//create function
here's my logic to create a new user
exports.create = (req, res, next) => {
if (!req.body) {
res.status(400).send({ message: "content cannot be empty !!" })
return
}
let data = { name: req.body.name, description: req.body.description, brand_url:
req.body.brand_url, image_file: req.body.file.filename }; getting error here
let sql = "INSERT INTO influencer SET ?";
db.query(sql, data, (err, results) => {
if (err) throw err;
console.log('data inserted succesfully')
res.redirect('/admin');
});
}
//api.js file
//post API
router.post('/api/create', upload.single('image') ,controller.create) //when I am
sending file its throw back error undefined filename
Please make sure you have added enctype="multipart/form-data"
<form action="/api/create" enctype="multipart/form-data" method="post">
I have tested the codes & found the problem.
exports.create = (req, res, next) => {
if (!req.body) {
res.status(400).send({ message: "content cannot be empty !!" })
return
}
let data = {
name: req.body.name,
description: req.body.description,
brand_url: req.body.brand_url,
image_file: req.file.filename
}; // Remove "body", I have tested, it works well.
let sql = "INSERT INTO influencer SET ?";
db.query(sql, data, (err, results) => {
if (err) throw err;
console.log('data inserted succesfully')
res.redirect('/admin');
});
}

How to send HTML as a response in REST?

I have created an API in Nodejs. I have tried creating a call which returns HTML to display a site in the browser.
My Call looks like this:
router.get('/displayHTML', checkAccessToken, (req, res, next) => {
if (req.query.data === undefined) {
return res.status(900).json({
message: 'Data does not exist'
});
}
Data.find({ data: req.query.data}).exec()
.then(data => {
if (data.length < 1) {
return res.status(400).json({
message: "Nothing found"
});
}
// I need to return HTML here so the user sees something in his browser
return res.status(200).json({
data: data
});
}).catch(error => {
return res.status(500).json({
message: error
});
});
});
Check the fs_library: https://nodejs.org/docs/v0.3.1/api/fs.html
var http = require('http'),
lib = require('fs');
lib.readFile('./page.html', function (err, html) {
if (err) {
throw err;
}
http.createServer(function(request, response) {
response.writeHeader(200, {"Content-Type": "text/html"});
response.write(html);
response.end();
}).listen(8000);
});

My data in Json file is not permanently saved (Express REST API)

I built a REST API using Express, a JSON file (database), and deployed it on Heroku. I consume this API from my React.JS app which I run on localhost. It seems my data is not persist after I restart my React.JS app.
Here is my server.js file:
const express = require('express');
const bodyParser = require('body-parser');
const path = require('path');
const fs = require('fs');
const port = process.env.PORT || 3000;
const app = express();
app.use((req, res, next) => {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept');
res.header('Access-Control-Allow-Methods', 'GET, PUT, POST, DELETE, PATCH, OPTIONS');
if (req.method === 'OPTIONS') {
res.send(200);
} else {
next();
}
});
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
// GET ALL TODOS
app.get('/api/todos', (req, res) => {
let data = '';
fs.readFile(path.resolve(__dirname, 'data.json'), (err, resp) => {
if (err) return console.log('Error::reading tasks from data.json file ', err);
data = JSON.parse(resp);
res.send(data.todos);
});
});
// GET A TODO
app.get('/api/todos/:id', (req, res) => {
fs.readFile(path.resolve(__dirname, 'data.json'), (err, resp) => {
if (err) return console.log('Error::reading tasks from data.json file ', err);
let data = JSON.parse(resp);
let todoData = data.todos.filter(todo => todo.id === parseInt(req.params.id))
if (todoData.length > 0) {
res.status(200).send(todoData[0]);
} else {
res.status(500).send({ message: 'Error: not found any task with that id' });
}
});
});
// POST A TODO
app.post('/api/todo', (req, res) => {
fs.readFile(path.resolve(__dirname, 'data.json'), (err, resp) => {
if (err) return console.log('Error::reading tasks from data.json file ', err);
const { id, task, status } = req.body
if (id && task && status) {
let json = JSON.parse(resp);
json.todos.push(req.body);
fs.writeFile(path.resolve(__dirname, 'data.json'), JSON.stringify(json), err => {
if (err) return console.log('Error::writing task to the data.json file ', err);
});
res.status(200).send({ message: 'Success: data have been added' });
} else {
res.status(500).send({ message: 'Error: all fields must be filled with data' })
}
});
});
// EDIT A TODO
app.put('/api/todo/:id', (req, res) => {
fs.readFile(path.resolve(__dirname, 'data.json'), (err, resp) => {
if (err) return console.log('Error::reading tasks from data.json file ', err);
const id = parseInt(req.params.id)
const { task, status } = req.body
if (task && status) {
let json = JSON.parse(resp);
let newTodo = json.todos.map(todo => {
if(todo.id === id) {
return {
id,
task,
status
}
} else {
return todo
}
})
let result = {
todos: newTodo
}
fs.writeFile(path.resolve(__dirname, 'data.json'), JSON.stringify(result), err => {
if (err) return console.log('Error::editing task to the data.json file ', err);
res.status(200).send({ message: 'Success: task have been edited' });
});
} else {
res.status(500).send({
message: 'Error: all fields must be filled with data'
})
}
});
});
// DELETE A TODO
app.delete('/api/todo/:id', (req, res) => {
fs.readFile(path.resolve(__dirname, 'data.json'), (err, resp) => {
if (err) return console.log('Error::reading tasks from data.json file ', err);
let json = JSON.parse(resp);
let isDataExist = json.todos.some(todo => todo.id === parseInt(req.params.id))
if (isDataExist) {
let leftTodo = json.todos.filter(todo => todo.id !== parseInt(req.params.id))
let result = {
todos: leftTodo
}
fs.writeFile(path.resolve(__dirname, 'data.json'), JSON.stringify(result), err => {
if (err) return console.log('Error::deleting task to the data.json file ', err);
res.status(200).send({ message: 'Success: a task has been deleted' });
});
} else {
res.status(500).send({ message: 'Error: a task you want to delete is not exist' })
}
});
});
app
.listen(port, () => {
console.info(`Your api server is running on http://localhost:${port}`);
})
.on('error', () => {
console.error('Error::server ', error);
});
I save the data in data.json file. You could see the logic in every API block URL / route. What are wrong in my server code?
Note: If you want to see my repo for this project: https://github.com/ridoansaleh/api
a JSON file (database)
A JSON file isn't a proper database, and Heroku's ephemeral filesystem makes this an especially bad choice: any changes you make to it will be lost the next time your dyno restarts. This happens frequently (at least once per day).
If you want to persist data permanently you need to use a proper client-server database. Heroku provides a hosted PostgreSQL service that has a free tier. I recommend starting there.

MySQL Transactions in Node

Before I commit anything to the database, I want all my update promises resolve; otherwise, I rollback. In other words, I want atomicity. I suppose I could handle the rollback by deleting out rows, but this has its own risks. I noticed if there is an error in any of the promises, the data still gets updated in database. What am I doing wrong?
I have written a simple program to illustrate the issue.
This is the main process:
const db = require('./db.js');
const async = require('async');
let insertList = [];
for (let i = 0; i<3; i++) {
insertList.push(i);
}
async function func1 () {
return new Promise((resolve, reject) => {
console.log("In Func1");
async.forEachOf(insertList, function(value, key, callback) {
console.log('>>>>' + value + '<<<<<<' + key );
db.insertOne('coll1', {value}).then(() => {
callback();
}).catch(err => {callback(err)})
}, function(err) {
// if any of the file processing produced an error, err would equal that error
if( err ) {
// One of the iterations produced an error.
// All processing will now stop.
console.log('err:', err);
reject(err);
} else {
console.log('Col1 All inserts have been processed successfully');
resolve("Success");
}
});
})
}
function func2 () {
return new Promise((resolve, reject) => {
console.log("In Func2");
async.forEachOf(insertList, function(value, key, callback) {
console.log('>>>>' + value + '<<<<<<' + key );
db.insertOne('coll2', {value}).then(() => {
callback();
}).catch(err => {callback(err)})
}, function(err) {
// if any of the file processing produced an error, err would equal that error
if( err ) {
// One of the iterations produced an error.
// All processing will now stop.
console.log('err:', err);
reject(err);
} else {
console.log('Col2 All inserts have been processed successfully');
resolve("Success");
}
});
})
}
function func3 () {
return new Promise((resolve, reject) => {
console.log("In Func3");
async.forEachOf(insertList, function(value, key, callback) {
console.log('>>>>' + value + '<<<<<<' + key );
if(key === 1) {
value = 'a';
}
db.insertOne('coll3', {value}).then(() => {
callback();
}).catch(err => {callback(err)})
}, function(err) {
// if any of the file processing produced an error, err would equal that error
if( err ) {
// One of the iterations produced an error.
// All processing will now stop.
console.log('err:', err);
reject(err);
} else {
console.log('Col3 All inserts have been processed successfully');
resolve("Success");
}
});
})
}
db.connect().then((pool) => {
pool.getConnection((err, connection) =>{
if (err)
return console.error(err);
else {
}
connection.beginTransaction((err) => {
if (err) {
return console.error(err);
}
let func1Promise = new Promise((resolve, reject) => {func1().then(() => {
console.log("Func1 complete");
resolve("Func1 complete");
}).catch((err) => {
console.error("Func1 ERROR: ", err);
reject("Func1 ERROR: ", err);
})});
let func2Promise = new Promise((resolve, reject) => {func2().then(() => {
console.log("Func2 complete");
resolve("Func2 complete");
}).catch((err) => {
console.error("Func2 ERROR: ", err);
reject("Func2 ERROR: ", err);
})});
let func3Promise = new Promise((resolve, reject) => {func3().then(() => {
console.log("Func3 complete");
resolve("Func3 complete");
}).catch((err) => {
console.error("Func3 ERROR: ", err);
reject("Func3 ERROR: ", err);
})});
Promise.all([func1Promise, func2Promise, func3Promise])
.then(()=> {
console.log("All Processes completed successfully.");
connection.commit(err => {
if (err) {
connection.rollback(() => {
throw err;
});
}
console.log('Commit Complete.');
connection.release();
});
})
.catch((err)=> {
console.error(err);
console.error("An update process has failed.");
connection.rollback(() => {
console.error(err);
connection.release();
});
})
});
})
});
The db.js looks like this:
const mysql = require('mysql');
const config = {
db: {
host: 'localhost',
user: process.env.DBUSER,
password: process.env.DBPASSWORD,
database: 'test',
}
};
var pool;
class DB {
constructor(host, user, password, database) {
this.host = host;
this.user = user;
this.password = password;
this.database = database;
}
connect() {
return new Promise((resolve, reject) => {
pool = mysql.createPool({
connectionLimit: 10,
host : this.host,
user : this.user,
password : this.password,
database : this.database
});
resolve(pool);
});
}
objToArray(obj) {
let arr = obj instanceof Array;
return (arr ? obj : Object.keys(obj)).map((i) => {
let val = arr ? i : obj[i];
if(typeof val === 'object' && val !== null)
return this.objToArray(val);
else
return val;
});
}
insertOne(collection, insertObj) {
return new Promise((resolve, reject) => {
pool.getConnection((err, connection) => {
if (err) {
resolve(err);
} else {
let sql = "INSERT INTO " + collection + " VALUES (?)";
// Convert the array of objects into an array of arrays.
let responseJson = this.objToArray(insertObj);
// The query object expects an array of objects so you pass in 'responseJson' as is
console.log(responseJson);
connection.query(sql, [responseJson], (err, result) => {
if (err) {
console.error(err);
return reject(err);
}
//console.log(result);
resolve("SUCCESS: object inserted into database");
});
}
});
});
}
}
const db = new DB(config.db.host, config.db.user, config.db.password, config.db.database);
Object.freeze(db);
module.exports = db;
My database "test" is simple and consists of 3 tables, coll1, coll2, coll3 and each has on field which is type int. In the third function I replace the 1 with 'a' This causes an error and the code catches this error and attempts a rollback, which does not work. If I set a breakpoint after func1 is executed and check the database, the values are already in the database.
Here is the version of MySQL that I am running:
Variable_name,Value
innodb_version,8.0.11
protocol_version,10
slave_type_conversions,
tls_version,"TLSv1,TLSv1.1,TLSv1.2"
version,8.0.11
version_comment,"MySQL Community Server - GPL"
version_compile_machine,x86_64
version_compile_os,macos10.13
version_compile_zlib,1.2.11
I am using the following NPM packages in node:
"async": "^2.6.2",
"mysql": "^2.15.0"
You're creating a transaction on a connection created in your test program, but your db.js's insertOne is grabbing a new connection from the pool that does not have a transaction. You should be passing in the connection you created in the test program.

How to avoid deadlock in nodejs mysql with a lot of queries?

I have a lot of urls, for every url I call the function load(url), this function parse the html, extracts the needed data and builds a bulk insert query as you can see in my test.js code. The problem is, if I have to many urls (like 100+), I get a Error: ER_LOCK_DEADLOCK from mysql. I tried to use async.queue but this is somehow not working (I don't know why, maybe I am using is wrongly). How can I run many urls + queries one after another, avoiding parallel execution which I think resulted in a deadlock? Even using async.queue results to a DEADLOCK (not always).
test.js
const request = require('request');
const async = require('async');
const pool = require('./database');
const urls = [
'https://www.quora.com/What-is-the-best-way-to-have-delayed-job-queue-with-node-js',
'https://de.wikipedia.org/wiki/Reinhardt-Zimmermann-L%C3%B6sung',
'https://towardsdatascience.com/the-5-clustering-algorithms-data-scientists-need-to-know-a36d136ef68'
]
let load = function(url) {
request({url: url}, function(error, response, html) {
if(!error) {
console.log(html);
/**
* 1. Parse HTML
* 2. Create Array of Values
* 3. Call pool.query(sql, [values], function(error) { ... })
*/
let data = [{}];
let sql = "INSERT IGNORE INTO tbl_test (title, content) VALUES ?";
let values = [];
data.forEach((item) => { values.push(item) });
pool.query(sql, [values], function(error) {
if(error) throw error;
})
} else {
console.log("handle error...");
}
})
}
let jobs = []
/*urls.forEach((url) => {
//jobs.push(load(url)); // --> Works but fails if the urls list is to big -> mysql deadlock error!
jobs.push(function(callback) { callback(load(url)) });
})*/
let q = async.queue(function(task, callback) {
console.log("Task:", task.uri);
callback();
})
q.drain = function() {
console.log('all task completed');
pool.end();
}
urls.forEach((url) => {
q.push({uri: url}, function(err) {
console.log('finished processing ...')
});
});
databse.js
require('dotenv').config();
const mysql = require('mysql');
let pool = mysql.createPool(
{
connectionLimit: 10,
host: process.env.DB_HOST,
port: process.env.DB_PORT,
user: process.env.DB_USER,
password: process.env.DB_PASSWORD,
database: process.env.DB_NAME
}
);
pool.getConnection((err, connection) => {
if(err) {
if(err.code === 'PROTOCOL_CONNECTION_LOST') {
console.log('Database connection lost.')
}
if(err.code === 'ER_CON_COUNT_ERROR') {
console.log('Database has too many connections.')
}
if(err.code === 'ECONNREFUSED') {
console.log('Database connection refused.')
}
if(err.code === 'POOL_CLOSED') {
console.log('Pool is closed.')
}
}
if(connection) {
connection.release()
}
return;
});
module.exports = pool;
I have changed the code to use async.series instead of async.queue, beacuse the tasks would run in parallel in queue (see: https://caolan.github.io/async/docs.html#queue).
test.js
...
let tasks = [];
context.forEach((ctx) => {
tasks.push(function(callback) { load(ctx, callback) });
});
async.series(tasks, function(err) {
if(err) return next(err);
});