I have a code as follow:
app.get('/list', function(req, res) {
serialport.list(function (err, ports) {
ports.forEach(function(port) {
var temp = port.manufacturer;
console.log(temp);
res.send(temp);
});
});
});
As it can be seen, port.manufacturer value is saved onto a variable temp and the resulting content of the temp is displayed onto console.
When I run the above code, i get something like this on my console:
Listening on port 3000...
Tinkerforge GmbH
GET /list 200 219ms - 16
Arduino (www.arduino.cc)
GET /favicon.ico 404 4ms
But when I call the api http://localhost:3000/list,
Only Tinkerforge GnbH is displayed and not Arduino.
Is there something i am missing over here??
Do I have to save the list in a array or something??
Any help would be really appreciated.
Thanks a lot in advance. And BTW i am kinda begineer in both node.js and javascript.
The problem here is that .send, unlike .write, can be called only once. When called, Express will analyze the data and detect the correct headers (res.writeHead) to send before writing (res.write) to the socket and finally close the connection (res.close).
The solution is to either use .write or send all of your data in one go.
Using .write
app.get('/list', function(req, res) {
serialport.list(function (err, ports) {
ports.forEach(function(port) {
var temp = port.manufacturer;
res.write(temp);
});
res.send();
});
});
Using .send
app.get('/list', function(req, res) {
serialport.list(function (err, ports) {
var manufacturers = [];
ports.forEach(function (port) {
manufacturers.push(port.manufacturer);
});
res.send(manufacturers.join(" "));
});
});
I'd probably go with something like JSON.stringify(manufacturers) instead of using .join, since JSON is so easy to work with.
Related
I'm trying to generate a PDF from an HTML file from the frontend and the users may download the PDF (never be stored on the server).
For this I am using the module: html5-to-pdf
My code is like this:
var pdf = require('html5-to-pdf');
var fs = require('fs');
router.post('/pdf', function(req, res) {
var html = req.body.html;
if (!html) {
return res.sendStatus(400);
}
pdf().from.string(html).to.buffer({
renderDelay: 1000
}, function(err, data) {
if (err) {
return res.sendStatus(500);
}
var file = fs.createWriteStream('myDocument.pdf');
file.write(data, function(err) {
if (err) {
res.sendStatus(500);
}
res.download('myDocument');
});
});
});
Whenever I download a file size of 0Bytes and also creates the file on the server
Someone could help me?
Maybe it send file before write finish
file.on('end',function(){
res.download('myDocument');
})
The problem is that html5-to-pdf used phantom to generate the PDF, so it phantom deploys a little server at "localhost" and the port 0, the fact is that OpenShift not recognize "localhost"[1] and if instead of using "localhost" variable is used: process.env.OPENSHIFT_NODEJS_IP the application works correctly.
[1] https://github.com/amir20/phantomjs-node/tree/v1#use-it-in-restricted-enviroments
Background
Yes, there are a lot of different Node.js logging library winston, bunyan and console.log. It's easy to log down the information of the specific request when it has called and when and what information would be in response.
The problem
The problem begins with the sub function calls. When under one request your calling multiple functions which also uses the same logging, how would you pass the request meta - data to these log calls (function parameters seems to be one possible way but these are really messy) ?
Example
Small visual for coders:
// Middleware to set some request based information
app.use(function (req, res, next) {
req.rid = 'Random generated request id for tracking sub queries';
});
app.get('/', function (req, rest) {
async.series({
'users': async.apply(db.users.find),
'posts': async.apply(db.posts.find),
}, function (err, dbRes) {
console.log('API call made ', req.rid)
res.end(dbRes);
});
});
// Now the database functions are in other file but we also need to track down the request id in there
(db.js)
module.exports = {
users: {
find: function () {
console.log('Calling users listing ', req.rid); // ERROR this is not possible to access, not in this scope
// Make query and return result
}
},
posts: {
find: function () {
console.log('Calling post listing ', req.rid); // ERROR this is not possible to access, not in this scope
// Make query and return result
}
}
};
You can log your requests with simple conf in your app.js with;
app.use(function(req, res, next){
console.log('%s %s', req.method, req.url);
next();
});
However, you need to provide logs for specific functions in your controller.
The following code is the user-facing part of a new node app we are building:
var loadInvoice = function(req, res, next) {
Invoice.findById(req.params.invoiceId, function (err, invoice) {
if (err) {
res.send(404, 'Page not found');
} else {
req.invoice = invoice;
next();
}
});
};
app.namespace('/invoices/:invoiceId', loadInvoice, function () {
app.get('', function(req, res){
var templateVals = {
//some template data
};
res.render('paymentselection', templateVals);
});
app.post('', function(req, res){
var data = {
// some data for the apiCall
};
someAPI.someRequest(data, function(err, data) {
console.log(res.status());
res.redirect(data.url);
});
});
});
The first method returns a confirmation page where the user presses a button to post to the same url, which triggers a redirect to an external website.
This all works exactly once. Every second request will crash the app with the message Cant set headers after they are sent. After carefull inspection of the code I could find no reason for this to happen so I added the console.log line which indeed confirms the location header has been set. But it is set to the value i got from someAPI on the previous request not the current one.
This makes absolutely no sense to me. I do not store this value anywhere nor do I do caching or persistence of this data in any way.
Does anybody know what could be causing this?
I use express, express-namespace, mogoose and swig
I found out the problem was being caused bij the 'Restler' libaray used within 'someAPI'. I have no idea how this is possible but swapping it out with something else fixed the problem.
I have this piece of code:
var app = require('http').createServer(function(req, res){
console.log(req);
req.addListener('end', function () {
fileServer.serve(req, res);
});
});
var statics = require('node-static');
var fileServer = new statics.Server('./');
app.listen(1344, '127.0.0.1');
app.on('error', function(err){
console.log(err);
})
It was working just fine, till I made a couple of changes, node gives an error, and when I went back, that error wasn't there anymore, but instead of work like it was working before the end event is not being fired. So, anything inside req.addListener('end', function (){});is not called.
And even if I run another node.js that uses the same event, is not being fired either. So is like if the end event of the request is broken. But how can that be possible?
Is not the first time it happens. Last time I ended up re-installing node (after try lots of different things). I would prefer to find a solution, so I can understand the problem!
NOTE: The original code include socket.io and other kind of connections, but I've just pasted the piece of code were the app is stuck on.
It could also be useful to know how to debug the problem!
#InspiredJW should get credit for pointing this out, since I had forgotten about it, but undoubtedly your problem is because of the changes in the readable streams. In order for the end event to get called you either have to attach a listener to the data event, or you have to call stream.resume().
require('http').createServer(function(req, res){
req.addListener('end', function () {
// won't ever get called in node v0.10.3
});
});
require('http').createServer(function(req, res){
req.addListener('end', function () {
// will get called in node v0.10.3 because we called req.resume()
});
req.resume();
});
require('http').createServer(function(req, res){
req.on('data', function (chunk) { });
req.addListener('end', function () {
// also will get called because we attached a data event listener
});
});
http://nodejs.org/api/stream.html#stream_compatibility
I am trying to setup a simple mongoose test server that reads users in the Users collections and prints the username. I can't seem to get the res.write for the query data to show up at the client side
var mongoose = require('mongoose');
var db = mongoose.createConnection('localhost', 'bugtraq');
var schema = mongoose.Schema({ username : 'string', email : 'string' });
var User = db.model('User', schema);
var http = require('http');
http.createServer(function (req, res) {
res.writeHead(200, {'Content-Type': 'text/html'});
User.find().exec(function (err, users) {
if(err) { res.write(err.message); }
if(users) {
users.forEach(function(u){
console.log(u.username);
return '<b>'+u.username+'</b>';
});
}
});
res.write('</body></html>');
res.end();
}).listen(8124, "127.0.0.1");
console.log('Server running at http://127.0.0.1:8124/');
The server side output is
<html><head></head><body></body></html>
I do see the username in the console output
Any pointers welcome
You have two problems. First, the mongoose query is anynchronous, yet you're ending your response outside of it's callback, before the query actually happens (I had to reindent the code to make sure).
To make it work you'd need to end the response inside the callback function for User.find.
Secondly, you're not collecting output as you think. This line is wrong:
return '<b>'+u.username+'</b>';
You're returning the output of the find into thin air. You'll need to capture it if you want to return it in the response.
Putting it together, it might look something like this:
User.find().exec(function (err, users) {
if(err) { res.write(err.message); }
if(users) {
// here make a buffer to store the built output ...
var output = [];
users.forEach(function(u){
// (you saw this console output because this loop is happening, it's
// just happening after your response has been ended)
console.log(u.username);
// ... then in each iteration of the loop, push to the buffer
output.push('<b>'+u.username+'</b>');
});
}
// finally, finish the response in the `find` callback.
res.end(output.join() + '</body></html>');
});