var http = require('http');
var fs = require('fs');
var path = process.argv[2];
var str="";
function onRequest(request, response) {
str += "";
console.log("Request received" + path);
fs.readdir(path, function(err, items) {
str += items;
});
response.writeHead(200, {"Context-Type": "text/plain"});
response.write(new Buffer(str).toString());
response.end();
}
http.createServer(onRequest).listen(8000);
The above snippet creates a http server which gets a directory path from the user as argument. Make a http request to get the list of files available in the directory and send them back as a response.
The response is written to the page only on the second request. The page is shown empty on the first request.
Could anyone help. Thanks in advance!!
Javascript is non blocking, so
response.writeHead(200, {"Context-Type": "text/plain"});
response.write(new Buffer(str).toString());
response.end();
will be executed before
str += items;
With
fs.readdir(path, function(err, items) {
// Handle error
str += items;
response.writeHead(200, {"Context-Type": "text/plain"});
response.write(new Buffer(str).toString());
response.end();
});
it will send the response after readdir.
And in Javascript the program will not be started for every new Request (like in PHP). So your global variable will be shared between all requests. If you don't want that put the var str=""; in onRequest.
If you have multiple routes you also want to look into something like express, because the http module doesn't include routing.
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
My source code:
var http = require("http");
var count=1;
http.createServer(function(request, response) {
response.writeHead(200, {"Content-Type": "text/plain"});
response.write("Hi, you are number "+count+" visitors");
response.end();
count++;
}).listen(8888);
I got 1,3,5,7,..... in each visit. Why to increment the count by 2?
The request to favicon.ico is triggering an extra request (I confirmed this by logging the details for each request and then making a normal request with Chrome).
You will need to look explicitly for the type of request (url, method, etc) you're wanting to match.
Also, keep in mind, if your server dies, which it probably will at some stage, your count will be reset. If you don't want that, you should persist it somewhere less volatile, such as a database.
If your server is just a simple counter and knowing that the request to favicon.ico is triggering an extra request, then you can simple count every request as a half so it will result in exact number of visits.
counter = counter + 0.5;
You could ignore the request for the favicon.ico:
var server = http.createServer(function (req, res) {
if(req.url === '/favicon.ico'){
console.log('favicon');
return;
}
userCount++;
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.write('Hello!\n');
res.write('We have had ' + userCount + ' visits!\n');
res.end();
});
I am new to node.js and json and am having trouble returning the JSON object to the client html page that's using $.getjson.
In the example below when i point the same code at the api.twitter.... url I can query and return the value. But when I point this to my own node.js back end that's spitting out the same JSON the alert('inside callback: ' + data[0].is_translator); does not pop up. What am I doing wrong here? I would really appreciate some help here.
This is script code in my test.html that's calling $.getJSON.
<script>
//var url = "http://localhost:5000/searchPlaces?callback=?";
function abc(result) {
//var url = "http://localhost:5000/random"
var url = "http://api.twitter.com/1/statuses/21947795900469248/retweeted_by.json?callback=?";
alert('before $.getjson');
$.getJSON(url, function(data) {
alert('hello');
alert('inside callback: ' + data[0].is_translator);
abc(result.data);
})
}
abc();
</script>
This is the code from my node.js backend:
var http = require("http");
var url = require("url");
var port = process.env.PORT || 8888
function start(route, handle){
function onRequest(request, response) {
var postData = "";
var pathname = url.parse(request.url).pathname;
console.log("Request received for:" + pathname + " receieved.");
response.writeHead(200, {"Content-Type": "application/json"});
var otherObject = {"is_translator":false,"id":644233,"followers_count":77};
response.write(
JSON.stringify({
anObject: otherObject
})
);
response.end();
// route(handle, pathname, response, request);
}
http.createServer(onRequest).listen(port);
console.log("Server had started. Port:" + port);
}
exports.start = start;
Callback for $.getJSON() is called only if the JSON is valid. The url for your twitter api http://api.twitter.com/1/statuses/21947795900469248/retweeted_by.json?callback=? gives a JSON with the following error on JSONlint.org
Parse error on line 1:
([ { "is
^
Expecting '{', '['
You should maybe $.get() the url and then validate JSON yourself before using it.
I wish to create a first node js app. For this I need to pull the public twitter tweet and output tweet as a request response. I searched a lot but I got code that written in older node version code(ie createServer, addListener something like this). How we write code for request a twitter call and output the json as response in node version 0.6.18?
Following is the older code I tried
var http = require("http");
var events = require("events");
var port = 8001;
var twitterClient = http.createClient(80, 'api.twitter.com');
var tweetEmitter = new events.EventEmitter();
var request = twitterClient.request("GET", "/1/statuses/public_timeline.json", {"host": "api.twitter.com"});
function getTweats() {
request.addListener("response", function (response) {
var body = "";
response.addListener("data", function (data) {
body += data;
});
response.addListener("end", function (end) {
var tweets = JSON.parse(body);
if (tweets.length > 0) {
tweetEmitter.emit("tweets", tweets);
console.log(tweets, 'tweets loaded');
}
});
});
request.end();
}
setInterval(getTweats(), 1000);
http.createServer(function (request, response) {
var uri = url.parse(request.url).pathname;
console.log(uri);
if (uri === '/stream') {
var cb = function (tweets) {
console.log('tweet'); // never happens!
response.writeHead(200, {"Content-Type": "text/plain"});
response.write(JSON.stringify(tweets));
response.end();
clearTimeout(timeout);
};
tweetEmitter.addListener("tweets", cb);
// timeout to kill requests that take longer than 10 secs
var timeout = setTimeout(function () {
response.writeHead(200, {"Content-Type": "text/plain"});
response.write(JSON.stringify([]));
response.end();
tweetEmitter.removeListener("tweets", cb);
}, 10000);
} else {
loadStaticFile(uri, response);
}
}).listen(port);
console.log("Server running at http://localhost:" + port + "/");
And got error
$ node tweet.js
Server running at http://localhost:8001/
timers.js:223
callback.apply(timer, args);
^
TypeError: Cannot call method 'apply' of undefined
at Timer.ontimeout (timers.js:223:14)
Your error is a common one. Instead of:
setInterval(getTweats(), 1000);
you need
setInterval(getTweats, 1000);
This is because you want setInterval to call the getTweats function itself.
Your code has getTweats() with parentheses instead. This calls getTweats first, and gives the result to setInterval. Since this result is undefined (your function doesn't return anything), node cannot call it.
In my node.js server listener callback(http.createServer(cb(response, request)), I write those code:
if(request.url == "/upload") {
request.addListener("end", function(){
console.log("UPLOAD");
var form = new formidable.IncomingForm();
form.parse(request, function(err, fields, files) {
response.writeHead(200, {"Content-Type" : "text/html"});
response.write('received files: ');
response.end();
});
});
}
And there is a file uploading form in my index. The problem is, the console outputs UPLOAD, but the response never ends. The browser waits until timeout. If I write these:
if(request.url == "/upload") {
var form = new formidable.IncomingForm();
form.parse(request, function(err, fields, files) {
response.writeHead(200, {"Content-Type" : "text/html"});
response.write('received files: ');
response.end();
});
}
Everything works well. I know that listener is unnecessary, but why doesn't it work?
Well that listener gets fired when all the data events has been emitted, it is late for formidable to start listening to events. What formidable does is that it is starts listening on events, when everything completed it calls the callback. In this case, after the end event emitted there wouldn't be any data to be emitted and formidable waits to receive something but nothing it gets.