I really can't figure out what I've done wrong. I've spent about half an hour looking at this code and re-reading code that essentially does the same thing and works. The 'data' event and corresponding callback is never triggered.
var http = require("http");
http.createServer(function(request, response){
response.writeHead(200);
console.log('Executing');
request.on('data', function(chunk){
console.log('data being read');
console.log(chunk.toString());
});
request.on('end', function(){
console.log('done');
response.end();
});
}).listen(8080);
Please help
You probably aren't sending a request body, so the data and end event don't fire. Trying sending a POST or PUT request. If you use a GET request with a query string, you will fire the end event, but not data.
Related
I am currently buildings proxy using nodejs, which use following syntax for sending and receiving https request and response. However in my project, the response is a liitle bit larger, so typically, req.on('data', callback) will be called 5~7 times before req.on('end', callback) being called.
Here is the simplified code structure:
var http = require("https");
var options = {
hostname: '<WEB SERVICE>',
port: 80,
path: '<WEB PATH>',
method: 'POST',
headers: {
'Content-Type': 'application/json',
}
};
var response = "";
var req = http.request(options, function(res) {
res.setEncoding('utf8');
res.on('data', function (body) {
console.log("data");
response += body;
});
res.on('end', function () {
console.log("end");
response = "";
});
});
req.on('error', function(e) {
console.log('problem with request: ' + e.message);
});
// write data to request body
req.write('<SOMETHING>');
req.end();
Ideally, when multiple request comes in, the logging sequence shall be:
data, data, data, data, data, end, data, data, data, data, end
i.e. once one request is done, end will be called once.
However, after doing several tests, when response is big. The sequence becomes:
<response 1 comes>data, data, data ..... data <response 2 comes> data, data, data, ..., data, end
i.e. the end for request 1 is missing.
In short, we need to make sure the callback of 'end' is called exactly once immediate after doing several call back of req.on('data', callback).
I believe there must be some common method for solving this issues (seems a classic bugs in node) and would be appreciated if anyone can indicate how to solve this property.
Thanks for the help!
From the code that you included it is impossible to make two requests. It makes one request with this:
var req = http.request(options, function(res) { ... });
Then binds the error handler here:
req.on('error', function(e) { ... });
And then immediately before even waiting for any response to the request, before even a connection is being made, it calls .write() and .end() methods on the request object:
req.write('<SOMETHING>');
req.end();
Nothing here can possibly cause two requests being made at the same time. But even if the first (and only) request hasn't started yet you already call .write() and .end() methods so maybe there's your problem.
In addition to that you should expect having one request being started before the other one finishes if you are going to do few requests in parallel as you're saying you'd like to.
i have the same issue before, i fixed like this:
res.on('finish', function () {
console.log("res finished");
});
Look here nodejs.org event-finish
I am running this script in node:
var http = require('http');
var server = http.createServer(function (request, response) {
response.writeHead(200, { "Content-Type": "text/plain" });
response.write('Hello World\n');
response.end('Goodbye World', 'utf8', function() {console.log(response.body);
});
server.listen(8000);
console.log('running');
When I load the page (localhost:8000) in Chrome I see:
Hello World
Goodbye World
So far so good, but I'm trying to understand where in the response object the data ('Hello World/nGoodbyeWorld') is. That's why I have 'console.log(response.body)' as the callback in response.end() ( the node http documentation says that the callback will be executed when the response has finished streaming). However the console.log just gives 'undefined'. When I console.log the whole response object it console.logs the response object ok but I can't see any data or body in there even though it has 'hasBody:true'.
So the question is:
a) is there a response.body? I am thinking there has to be one otherwise nothing would show in the browser window.
b) if so how can i access it and why doesn't my way work?
The closest answer i could find was this one: Where is body in a nodejs http.get response? , but I tried adding
response.on('data', function(chunk) {
body += chunk;
});
response.on('end', function() {
console.log(body);
});
, as suggested there and it didn't work. Also people there are just answering HOW you can access the data, not WHY the response.body isn't easily accessible.
Thanks
There is no response body, the data you write to the response stream is just sent to the client as you write it (for the most part). It wouldn't make sense to keep in memory everything ever written to the response.
The same goes for requests. You have to buffer the incoming data yourself if you want that, it is not done behind the scenes, it is merely streamed in.
Code is listed below. The problem is that the console.log() is firing twice, indicating that rs.end is firing twice, even though I only registered it to fire once. If I comment out res.end() it only fires once, so I know the call to res.end is causing rs.end to fire as well, I just don't understand why.
I recognize that this could just be a misunderstanding of the event system or the server streaming objects, neither of which I've looked much into.
Where it gets a bit odd though, is that if I change that console.log to be res.write so that it's writing it to the browser, it only writes it to the browser once, even with res.end() being called.
Thanks in advance for any help you can offer!
require('http').createServer(function(req, res) {
var rs = require('fs').createReadStream('sample.txt');
//Set the end option to false to prevent res.end() being automatically called when rs ends.
rs.pipe(res, { end: false });
rs.once('end', function() {
console.log('Read stream completed');
res.end();
});
}).listen(8080);
Most likely you are seeing two separate http requests: the one you explicitly sent and the one sent automatically by the browser for /favicon.ico.
the browser with every response is looking for a favicon.ico , in this case because you didn't send a html with a <link rel="icon" href="favicon.ico" type="image/x-icon"/> send another request looking for that, if you are trying to avoid it you can do something like this:
var http = require('http');
var fs = require('fs');
http.createServer(function(req, res) {
var rs;
if(req.url !== "/favicon.ico") {
rs = fs.createReadStream('sample.txt');
//Set the end option to false to prevent res.end() being automatically called when rs ends.
rs.pipe(res, { end: false });
rs.once('end', function() {
console.log('Read stream completed');
res.end();
});
}
}).listen(3000);
If you look at the answer by Casey Chu (answered Nov30'10) in this question : How do you extract POST data in Node.js?
You will see that he is responding to 'data' events , to construct the body of the request. Reproducing code here:
var qs = require('querystring');
function (request, response) {
if (request.method == 'POST') {
var body = '';
request.on('data', function (data) {
body += data;
// Too much POST data, kill the connection!
if (body.length > 1e6)
request.connection.destroy();
});
request.on('end', function () {
var post = qs.parse(body);
// use post['blah'], etc.
});
}
}
Suppose I don't care about POST requests, and hence never check if a request is POST or create a 'data' event handler, is there a risk that someone can block my thread by sending a really large post request ? For example, instead of the above code, what if I just did:
function hearStory(request, response) {
response.writeHead(200, {"Content-Type": "text/plain"});
response.write("Cool story bro!");
response.end();
}
What happens to really large POST requests then ? Does the server just ignore the body ? Is there any risk to this approach ? Get requests including their headers must be less that 80kB, so it seems like a simple way to avoid flooding my server.
Hopefully these kinds of attacks can be detected and averted before it ever gets to your server via a firewall or something else. You shouldn't handle DOS attacks with the server itself. However, if they've gotten to your server with malicious intent, there needs to be a way to handle it. If you intend on handling POST requests, the code you're referring will help.
You could, if you just want to avoid POST requests all together and not listen for them, as is demonstrated by the second code snippet, do something like the following.
function denyPost(req, res) {
if (request.method == 'POST') {
console.log('POST denied...'); // this is optional.
request.connection.destroy(); // this kills the connection.
}
}
Of course, this wont work if you plan on handling post requests somehow. But again, DOS attacks need to be handled before they ever get to your server. If they've gotten there, they've already won.
I'm having trouble with something very basic. Going through node.js in Action (great book so far!) and I can't get this simple example to work. Perhaps it's because the stream api was updated after the book came out. I'm not sure. Anyway, here's the code:
var http = require('http');
var server = http.createServer(function (req, res) {
req.on('data', function (chunk) {
console.log("Chuck: ", chunk);
});
req.on('end', function () {
console.log("End of Request");
res.end('yay');
});
}).listen(3000);
The console.log('Chunk: ', chunk) never fires. It's almost as if the data events never fire, but according to the documentation the presence of the data handler should switch the readable stream (req) into flowing mode. Am I missing something?
Any help would rock!
The above code is current initally the request body is undefined you have to pass request data inorder to execute this line.
req.on('data', function (chunk) {
console.log("Chuck: ", chunk);
});
Use postman to send data in the request this line will be executed