I am following a node.js tutorial and am making a simple server that will display contents of a directory.
function start(response) {
console.log("Request handler 'start' was called.");
// if I put response.write("blah") here it works
console.log(response);
exec("ls -lah", function (error, stdout, stderr) {
console.log(response);
response.writeHead(200, {"Content-Type": "text/plain"});
response.write(stdout);
response.write("asdfasdf");
console.log("asdf");
console.log(stdout);
response.end();
});
}
This prints nothing on the browser, but shows up on the console.
I tried putting response.write() outside of the exec callback function, and it shows up perfectly on the browser.
Firefox is reporting that the request is not being set at all, not even the content-type header is being set. If I move that outside the exec callback function, it does get set.
Related
I have just started with node.js. I find the asynchronous coding style it uses to be very impressive indeed. However, for those of us who are used to Java and Python it does take some time to get used to it.
I know the following code works fine. This is verified by several questions on this forum. I have also tried it on my own.
var http = require('http'),
fs = require('fs');
fs.readFile('./index.html', function (err, html) {
if (err) {
//throw err;
}
http.createServer(function(request, response) {
console.log("Server started");
response.writeHeader(200, {"Content-Type": "text/html"});
response.write(html);
response.write("Other things");
response.end();
}).listen(3000);
});
The way I am interpretting this is as follows:
1. Try reading the html file
i. When done create a server
ii. Send it over to the client
2. Do everything else.
However, we can also have a chain of thoughts as follows:
1. Create the server
2. Try reading the file
i. When done. Send it over to the client
3. In the meanwhile do anything else the server might be asked to do.
The code corresponding to the second chain of thoughts is:
var http = require('http'),
fs = require('fs');
http.createServer(function(request, response) {
console.log("Server started");
response.writeHeader(200, {"Content-Type": "text/html"});
fs.readFile('./index.html', function (err, html) {
if (err) {
//throw err;
}
response.write(html);
response.write("Other things");
});
response.end();
}).listen(3000);
While the first code works as expected. The second one displays nothing at all in the browser.
Why is the second chain of thoughts wrong?
Actually, what happens here is that the following function gets called each time there is an incoming request:
function(request, response) {
console.log("Server started");
response.writeHeader(200, {"Content-Type": "text/html"});
response.write(html);
response.write("Other things");
response.end();
}
You replaced that with:
function(request, response) {
console.log("Server started");
response.writeHeader(200, {"Content-Type": "text/html"});
fs.readFile('./index.html', function (err, html) {
if (err) {
//throw err;
}
response.write(html);
response.write("Other things");
});
response.end();
}
Now here, it will run the following:
Write the header
Queue the readFile
Immediately execute the following: response.end();
By the time it is done reading the file and wants to write the contents, you already ended the response
i´m trying to check several requirements on a html body, received by the node-module request with jasmine-node.
The normal case would be to write something like this:
describe("check website body", function() {
it("should contain 1st requirement", function(done) {
request("url...", function(error, response, body) {
//check here the body for the first requirement
done();
});
});
it("should contain 2nd requirement", function(done) {
request("url...", function(error, response, body) {
//check here the body for the 2nd requirement
});
done();
});
});
What i would like to have is to call the website directly after the describe line and than pass body to the specific tests.
UPDDATE: To clarify: My intention is to only call the url once for my tests, not twice.
could someone can give me a hint how to do this?
Thanks and kind regards
You already had the right place in your example, just missing the code!
request("url...", function(error, response, body) {
//check here the body for the first requirement
expect(body).toContain('something');
done();
});
When creating a basic HTTP server with Node.js, I noticed that the res.write and res.end methods of the 'http.ServerResponse' object can both accept a callback function like so:
require('http').createServer(function (req, res) {
res.writeHead(200, {'Content-Type': 'text/plain'});
res.write('Hello ', function() { console.log('here 1'); });
res.end(' World', function() { console.log('here 2'); });
}).listen(1337, '127.0.0.1');
'Hello World' is output in the browser, and 'here 1' and 'here 2' is output into the terminal.
However, these callback arguments aren't documented anywhere, for instance http://nodejs.org/api/http.html#http_response_end_data_encoding unless I'm missing something.
Can I really use these callback functions? I have an interesting use case for them. Or are they some internal use thing and should be avoided?
This appears to be a 'feature'. It is actually meant to be the encoding to be used in the body but the way the net module works is the second argument is an optional callback.
The stack is like this (about)
res.write(data, encoding)
res._send(data, encoding)
res._writeRaw(data, encoding)
res.socket.write(data, encoding, cb)
At that last point the number of arguments changes from 2 to 3. data and encoding to data, encoding, optional callback. So what is happening is your function (as the encoding argument) is being passed to socket.write where encoding can be optional.
This could be considered a bug as you cannot push all three arguments from the response write method. I'd advise using it with extreme care.
I'm doing this tutorial on NodeJS: http://www.nodebeginner.org.
Here is the code I find confusing:
var exec = require("child_process").exec;
function start(response) {
console.log("Request handler 'start' was called.");
var content = "empty";
exec("ls -lah", function(error, stdout, stderr) {
response.writeHead(200, {"Content-type":"text/plain"});
response.write(stdout);
console.log(stdout);
response.end();
});
}
I have a router that passes the http response to a request handler that calls the start function. This is happening without a problem. However, the stdout parameter is not returning anything in the browser or in the console. I understand that ls -lah is supposed to give a list of files in the current directory. I have 5 other files in my directory, but nothing is being returned. Any ideas on what is happening here?
I'm using child_process to run wkhtmltopdf to build a PDF from an html document. I want to wait until wkhtmltopdf is finished processing the document into a PDF before I proceed. I think that reading from stdout to capture when wkhtmltopdf sends its done signal is the best way to do this, but the following code reports stdout to be empty at res.send(). How do I set up an event to fire when stdout gives me data?
Code:
var buildPdf = function(error){
var pdfLetter;
var child = exec('wkhtmltopdf temp.html compensation.pdf', function(error, stdout, stderr) {
if (error)
res.send({
err:error.message
});
else
res.send({
output : stdout.toString()
});
// sendEmail();
});
};
You've encountered a wkhtmltopdf gotcha. It doesn't write status information to STDOUT, it writes it to STDERR.
$ node -e \
"require('child_process').exec( \
'wkhtmltopdf http://stackoverflow.com/ foo.pdf', \
function(err, stdout, stderr) { process.stdout.write( stderr ); } );"
Loading pages (1/6)
content-type missing in HTTP POST, defaulting to application/octet-stream
Counting pages (2/6)
Resolving links (4/6)
Loading headers and footers (5/6)
Printing pages (6/6)
Done
I've just finished getting this to work via Node.js on Heroku and wanted to post since I had to get over a couple of tiny hurdles.
// Spin up a new child_process to handle wkhtmltopdf.
var spawn = require('child_process').spawn;
// stdin/stdout, but see below for writing to tmp storage.
wkhtmltopdf = spawn('./path/to/wkhtmltopdf', ['-', '-']);
// Capture stdout (the generated PDF contents) and append it to the response.
wkhtmltopdf.stdout.on('data', function (data) {
res.write(data);
});
// On process exit, determine proper response depending on the code.
wkhtmltopdf.on('close', function (code) {
if (code === 0) {
res.end();
} else {
res.status(500).send('Super helpful explanation.');
}
});
res.header('Content-Type', 'application/octet-stream');
res.header('Content-Disposition', 'attachment; filename=some_file.pdf');
res.header('Expires', '0');
res.header('Cache-Control', 'must-revalidate, post-check=0, pre-check=0');
// Write some markup to wkhtmltopdf and then end the process. The .on
// event above will be triggered and the response will get sent to the user.
wkhtmltopdf.stdin.write(some_markup);
wkhtmltopdf.stdin.end();
On the Cedar-14 stack at Heroku, I couldn't get wkhtmltopdf to write to stdout. The server always responded with Unable to write to destination. The trick there was to write to ./.tmp and then stream the written file back out to the user – easy enough:
wkhtmltopdf = spawn('./path/to/wkhtmltopdf', ['-', './.tmp/some_file.pdf']);
wkhtmltopdf.on('close', function (code) {
if (code === 0) {
// Stream the file.
fs.readFile('./.tmp/some_file.pdf', function(err, data) {
res.header('Content-Type', 'application/octet-stream');
res.header('Content-Disposition', 'attachment; filename=' + filename);
res.header('Expires', '0');
res.header('Cache-Control', 'must-revalidate, post-check=0, pre-check=0');
res.send(data);
});
} else {
res.status(500).send('Super helpful explanation.');
}
});
res.header('Content-Type', 'application/octet-stream');
res.header('Content-Disposition', 'attachment; filename=' + filename);
res.header('Expires', '0');
res.header('Cache-Control', 'must-revalidate, post-check=0, pre-check=0');