How to put router in function and export it? - node.js

I try to put router.post in a function and export it to app.js. But it didn't take effect. Here is my code.
crypto.js
function getPublicKey() {
console.log('111');
router.post('/get-public-key', (req, res) => {
fs.readFile(__dirname + '/keys/rsa-pub.pem', 'utf8', (err, data) => {
if (err) {
throw err
} else {
res.send(data)
}
})
});
}
module.exports = {
getPublicKey
}
app.js
const cryptoRouter = require('./modules/crypto/router');
cryptoRouter.getPublicKey();
It printed '111'.But I cannot POST /get-public-key.
How should I do?Thanks!

I think getPublicKey should return the public key instead
function getPublicKey() {
fs.readFile(__dirname + '/keys/rsa-pub.pem', 'utf8', (err, data) => {
if (err) {
throw err
}
return data
})
}
Then, in app.js
app.post('/get-public-key', (req, res) => {
res.send(getPublicKey)
})
Edit
If you wanna use router, you should do like this:
// ./routes/somewhere.js
const router = require('express').Router()
router.post('/something', (req, res) => {
res.send('You made it!')
})
module.exports = router
Then
// ./app.js
app.use('/somewhere', require('./routes/somewhere'))
Finally, you can make a post request to /somewhere/something.

You can pass the instance of app to your function and return the route
function getPublicKey(app) {
console.log('111');
return app.post('/get-public-key', (req, res) => {
fs.readFile(__dirname + '/keys/rsa-pub.pem', 'utf8', (err, data) => {
if (err) {
throw err
} else {
res.send(data)
}
})
})
}
module.exports = {
getPublicKey
}
Then in your app.js you could simply invoke by passing in the instance of app:
const cryptoRouter = require('./modules/crypto/router');
cryptoRouter.getPublicKey(app);

Related

Node.js Multer with Imagemin for file compression

This is my code :
const imagemin=require('imagemin');
const imageminMozjpeg = require('imagemin-mozjpeg');
const multer=require('multer');
const upload=multer({storage:storage});
var imageUpload=upload.single('file');
var storage=multer.diskStorage(
{
destination:function(req,file,cb)
{
cb(null,'./tempuploads/')
},
filename:function(req, file, cb)
{
cb(null,file.originalname)
}
});
exports.filecompressor=async(req,res)=>
{
imageUpload(req, res, function(err)
{
let filetoupload=req.file;
let filename=filetoupload.originalname;
if(err)
{
console.log(err)
}
let temppath="./tempuploads/"+filename;
imagemin([temppath],
{
destination: './cachedimages/',
plugins:[imageminMozjpeg({quality: 50})]
}).then(result=>
{
console.log(result)
});
});
};
I want imageUpload(req, res, function(err){}); to return temppath so that I can use imagemin() function outside it and add await to it.
Can anybody please help me??
You can convert imageUpload callback to a promise, for example:
exports.filecompressor = async (req, res) => {
return new Promise((resolve, reject) => {
imageUpload(req, res, function (err) {
let filetoupload = req.file;
let filename = filetoupload.originalname;
if (err) {
console.log(err);
return reject(err);
}
let temppath = "./tempuploads/" + filename;
resolve(temppath);
});
});
};

Return call is not working in Node.js with Express

My code block for crud.js is as follows,
const listall = () => {
return client.connect(() => {
return client.invoke("ZSD_CP_PRICE_GET_ALL", {}, (err, res) => {
if (err) {
console.log('error in invoke', err);
}
console.log("ZSD_CP_PRICE_GET_ALL", res);
return res;
});
});
}
My code block for viewpage.js is as follows,
router.get('/', function(req, res) {
res.render('viewpage', {title: 'SAP', data: sapview.listall()})
})
module.exports = router;
My code block for viewpage.jade is as follows,
extends layout
block content
h1= title
p Welcome to #{title}
p Data #{data}
When I run the node application terminal logs the result like,
ZSD_CP_PRICE_GET_ALL {
IS_RETURN: {
TYPE: ''
}
But the res is never returned as I mentioned in "return res" after the console.log block in crud.js file
client.connect() is asynchronous; you have no way of getting the actual return value of whatever further asynchronous code (such as client.invoke) you call.
I suggest promisifying the invocation,
const listall = () => {
return new Promise((resolve, reject) => {
client.connect(() => {
client.invoke("ZSD_CP_PRICE_GET_ALL", {}, (err, res) => {
if (err) {
return reject(err);
}
resolve(res);
});
});
});
};
and then getting the data in an async function:
router.get("/", async (req, res) => {
const data = await sapview.listall();
res.render("viewpage", { title: "SAP", data });
});
(A further refactoring would involve a generic promisified "invoke method" function.)

With epilogue / finale-rest, how can I accept binary files via multer?

I'm doing:
const audioResource = finale.resource({
model: db.models.Audio,
endpoints: ['/audios', '/audios/:id']
})
audioResource.use(multer().single("file"))
audioResource.use(resources.audio)
Where resources.audio is:
module.exports = {
create: {
write: {
before: (req, res, context) => {
console.log(Object.keys(req))
console.log(req.body)
console.log("HERE I AM!")
console.log(req.file)
}
}
}
}
However, I can't access req.file. Is it possible to set up with the multer middleware?
I think the right way to use it would be
module.exports = {
create: {
write: {
before: (req, res, context) => {
upload.single('file')(req, res, () => {
console.log(Object.keys(req))
console.log(req.body)
console.log("HERE I AM!")
console.log(req.file)
}
}
}
}
}

Unable to return value from function

I'm getting undefined on return value from the function
function checkAveStorage(path) {
console.log("path " + path);
disk.check(path, function(err, info) {
if (err) {
console.log(err);
return -1;
} else {
console.log("info " + info.available);
return ((info.available / info.total) * 100).toFixed(2);
}
});
}
app.get("/sysinfo", (req, res, next) => {
var storage = checkAveStorage('/mnt/usb');
console.log(storage);
})
undefined value appear in console.
You are using callback which cannot return value, but you can use it inside that call back only. Other options are use promise or async/await.
function checkAveStorage (path) {
console.log('path ' + path)
return new Promise((resolve, reject) => {
disk.check(path, function (err, info) {
if (err) {
console.log(err)
reject(-1)
} else {
console.log('info ' + info.available)
resolve(((info.available / info.total) * 100).toFixed(2))
}
})
})
}
app.get('/sysinfo', (req, res, next) => {
checkAveStorage('/mnt/usb').then((storage => {
console.log(storage)
}), (err) => {
console.log(err)
})
})
Another way with async/await
async function checkAveStorage(path) {
try{
const info = await disk.check(path);
return ((info.available / info.total) * 100).toFixed(2);
} catch(err){
console.log(err);
return -1;
}
}
app.get("/sysinfo", async (req, res, next) => {
var storage = await checkAveStorage('/mnt/usb');
console.log(storage);
})
You are using callback so you must :
app.get("/sysinfo", (req, res, next) => {
checkAveStorage('/mnt/usb').then((storage)=>{
console.log(storage)
})

Avoiding callback hell

I have this code that serves every markdown file in the './markdown' folder. At '/api/markdown/filename'.
var apiRouter = express.Router();
markdownFolder = './markdown/';
apiRouter.get('/:markdown_file_noext', function(req, res) {
fs.readdir(markdownFolder, function(err, markdown) {
if (err) throw err;
markdown.forEach(function(file) {
fs.readFile(markdownFolder + file, 'utf8', function(err, file_content) {
if (err) throw err;
fileNoExtension = file.slice(0, file.indexOf('.'));
if (req.params.markdown_file_noext == fileNoExtension) {
res.json({
'title': fileNoExtension,
'markdown': marked(file_content)
});
};
});
});
});
});
But i end having a ton of callbacks do the the nature of the 'fs' methods. How do i avoid this?
Using Q as promise library:
const Q = require('q');
const fs = require('fs');
const markdownFolder = './markdown/';
const readdir = Q.nfbind(fs.readdir);
const readFile = Q.nfbind(fs.readFile);
readdir(markdownFolder).then(markdown => {
const promises = [];
markdown.forEach(file => promises.push(readFile(markdownFolder + file, 'utf8')));
return Q.all(promises);
}).then(files => {
// Do your magic.
}).catch(error => {
// Do something with error.
});
You have different option.
Use named Function instead of anonymus functinos. It would make it a little bit more readable but you will still be using callbacks.
Use Promises, but you will need to use bluebird to wrap the fs module.
For a more advance option, you can use generators and Promises to make your code look more like a sync way. Take a look at co or bluebird.coroutine.
With Promises you could do like this:
const path = require('path');
var apiRouter = express.Router();
markdownFolder = './markdown/';
apiRouter.get('/:markdown_file_noext', function(req, res) {
readdir(markdownFolder)
.then((files) => {
const tasks = files.map((file) => {
const filePath = path.resolve(markdownFolder, file);
return readFile(filePath);
});
return Promise.all(tasks); // Read all files
})
.then((fileContents) => {
return fileContents.map((content) => {
fileNoExtension = file.slice(0, file.indexOf('.'));
if (req.params.markdown_file_noext == fileNoExtension) {
return {
'title': fileNoExtension,
'markdown': marked(content)
};
};
})
})
.then((results) => {
// It's better if you aggregate all results in one array and return it,
// instead of calling res.json for each result
res.json(results);
})
.catch((err) => {
// All errors are catched here
console.log(err);
})
});
function readdir(folderPath) {
return new Promise((resolve, reject) => {
fs.readdir(folderPath, (err, files) {
if (err) {
return reject(err);
}
resolve(files);
});
});
}
function readFile(filePath) {
return new Promise((resolve, reject) => {
fs.readFile(filePath, 'utf8', (err, file_content) => {
if (err) {
return reject(err);
}
resolve(file_content);
});
});
}

Resources