Whenever I make http requests to a server using node.js, the console.logs inside the http request function output twice. I set up a sever with the following code, and used localhost:8888 on firefox to make a request (localhost:8888):
var http = require('http');
var url = require('url');
function onRequest(request, response) {
var pathname = url.parse(request.url, true).pathname;
console.log("Your url pathname is " + pathname);
response.write("Did you get your response?");
}
var new_server = http.createServer(onRequest).listen(8888);
The console prints:
Your url pathname is /
Your url pathname is /favicon.ico
My questions are:
Why is the request sent twice?
Why is the pathname favicon.ico on the second request despite the fact that I did not specify anything after the socket number in the request url?
Is there any way you can fix these two issues?
Thank you.
Obviously the request isn't sent twice, it's two requests.
It's the browser asking for the favicon. That's a thing browsers do.
Related
I'm trying to write a simple Node.js http server which stops and exits its process when a given url is accessed: in this case, /stop. This is my program so far:
var http = require('http');
var server = http.createServer(function(request,response) {
response.end(function(){
if (request.url === '/stop') server.close();
});
});
server.listen(12345);
What I expect to happen is that the callback is called when the response finishes sending, and the server closes if the URL is /stop. However, all this ends up doing is it shows a blank page (which I expected) and does nothing else.
On the other hand, this program almost works if I omit response.end():
var http = require('http');
var server = http.createServer(function(request,response) {
if (request.url === '/stop') server.close();
});
server.listen(12345);
It does manage to stop the server, but not until I terminate the GET request by closing the browser window.
How can I get the server to stop when I GET a certain URL without having to close the browser window? (It would be nice if I could send a "Server stopped" message to the browser, too.)
NOTE: I know that I don't actually have the code to differentiate between GET and POST requests, but I would like to be able to handle both, and I'm assuming the answer isn't different depending upon the type of request.
I'm trying to parse the url in node js. Getting null values from this code. It is receiving value for the path. But not for the host or protocol.,
var http = require('http');
var url = require('url');
http.createServer ( function (req,res){
var pathname = url.parse(req.url).pathname;
var protocol = url.parse(req.url).protocol;
var host = url.parse(req.url).host;
console.log("request for " + pathname + " recived.");
console.log("request for " + protocol + " recived.");
console.log("request for " + host + " recived.");
res.writeHead(200,{'Content-Type' : 'text/plain'});
res.write('Hello Client');
res.end();
}).listen(41742);
console.log('Server Running at port 41742');
console.log('Process IS :',process.pid);
The HTTP protocol doesn't communicate the combined URL in one value for Node to parse out.
A request to http://yourdomain.com/home, for example, arrives as:
GET /home HTTP/1.1
Host yourdomain.com
# ... (additional headers)
So, the pieces won't all be in the same place.
The path and query-string you can get from the req.url, as you were doing – it'll hold "/home" for the above example.
var pathname = url.parse(req.url).pathname;
The host you can get from the req.headers, though a value wasn't always required for it.
var hostname = req.headers.host || 'your-domain.com';
For the protocol, there isn't a standard placement for this value.
You can use the advice given in "How to know if a request is http or https in node.js" to determine between http and https.
var protocol = req.connection.encrypted ? 'https' : 'http';
Or, though it isn't standard, many clients/browsers will provide it with the X-Forwarded-Proto header.
req.url only contains the path not the entire url.
Rest are in request headers.
For Host: console.log(req.headers["host"]);
For Protocol: console.log(req.headers["x-forwarded-proto"]);
you can view this source code:
https://github.com/expressjs/express/blob/master/lib/request.js
In browser javascript is pathetically broken in that the only way to make requests is using script tags and jsonp. To make this useful, I'm trying to make a nodejs server that, given a callback name and address, loads the page at the address and pads it in a call to callback and serves the result. However, I know next to nothing about nodejs. If the server's response is loaded from a script tag it would result in actually loading a web page. Currently, I'm writing the request as localhost:8000/callback/address so a script tag might be <script src="localhost:8000/alert/https://www.google.com" type="text/javascript"></script>. Here is my code for the server:
var http = require("http");
var request = require("request");
var server = http.createServer(function(req, res){
req.on("end", function(){
console.log("alive");
var url = req.url;
var i = url.indexOf("/", 1);
request(url.substring(i + 1), function(err, ret, body){
res.writeHead(200);
res.write(url.substring(1, i) + "(\"" + body + "\");");
res.end();
});
});
});
server.listen(8000);
Why does this stay loading for a very long time but never actually load? By using console.log() it seems as if the req.on("end") callback is never even called.
If you don't care about any request data, you could just add req.resume(); after you add your end event handler.
The reason it's getting "stuck" is that since node v0.10, streams start out in a paused state, so you need to unpause them by reading from them in some way. req.resume(); accomplishes this. Once there is nothing left in the request stream (which there could be nothing), the end event will be emitted.
I am building an Express app which on certain requests has to make its own HTTP calls. I could use Superagent, request or node's own http.request.
Thing is, I need to log all of those server originating requests and their respective responses. Calling log.info before each and every of those seems silly.
How can you add a pre-filter for all outgoing HTTP calls, and ideally access both req and res?
NOTE: I am not interested in logging requests coming in to the server I am building, only in the requests that the server itself kicks off. Think of my server as a client to another black box server.
What you can do is patch http and https and proxy the request method. This way you can have a global handler that will catch the req & res objects.
var http = require('http');
var https = require('https');
var patch = function(object) {
var original = object.request;
// We proxy the request method
object.request = function(options, callback) {
// And we also proxy the callback to get res
var newCallback = function() {
var res = arguments[0];
// You can log res here
console.log("RES",res.statusCode);
callback.apply(this,arguments);
}
var req = original(options, newCallback);
// You can log your req object here.
console.log(req.method,req.path);
return req;
}
}
patch(http);
patch(https);
http.get("http://www.google.com/index.html", function(res) {
console.log("Got response");
}).on('error', function(e) {
console.log("Got error: " + e.message);
});
Edit: This might work if you use the request npm package as well, as it might just rely on the built-in node.js http.request method anyways.
What server are you going to use for you app?
I would definally bring up such functionality on to server level. Take a look how heroku router is doing it. You can track all of needed information using some of their addons: papertrail, or newrelic ( or use them separately for you app ).
https://papertrailapp.com/
http://newrelic.com/
I like out-of-box solutions in this case, no need extend your app logic for logging such information.
If you want to have your own solution, you can setup nginx to monitor request/response info.
http://nginx.com/resources/admin-guide/logging-and-monitoring/
I'm trying to do a simple conection (request - response) from the javascript code on a web to a server in Node.js.
I have tried to make the request as follows:
var request = new XMLHttpRequest();
request.open('GET', 'http://localhost:4444/', false);
request.send();
if (request.status === 200) {
console.log(request.responseText);
}
Running this code I got an error in FireBug
I have continued searching and I found that this method is only to make GET requests on the same domain. To make cross domain requests we must use other strategies.
I found a jQuery method, and it seems that i'm on the right way:
$.get(
'http://localhost:4444/',
function(data) {
alert("sucess");
//Do anything with "data"
}
);
In this case I get the same response without the error.
It seems it works but the "alert" message is never shown! What happens? What am I doing wrong?
The Node.js server code is:
var http = require("http");
http.createServer(function(request, response) {
response.writeHead(200, {"Content-Type": "text/html"});
response.write("Response");
response.end();
}).listen(4444);
So you're running into cross domain issues. You have a few options:
1) since you're using node, use socket.io . It's cross domain compliant.
On the client:
<script src="Full path to were socket IO is held on your server//socket.io.js"></script>
<script>
var socket = io.connect();
socket.on('some_callback', function(data){
// receive data
});
socket.emit('some_other_callback', {'data': value}); //send data
</script>
Server:
var io = require('socket.io').listen(server);
// define interactions with client
io.sockets.on('connection', function(socket){
//send data to client
socket.emit('some_callback', {'data': value});
//recieve client data
socket.on('some_other_callback', function(data){
//do something
});
});
2) Since you just want to use GET you can use JSONP
$.getJSON('url_to_your_domain.com/?callback=?&other_data=something,
function(data){
//do something
}
);
Here we pass your normal GET params as well as callback=?. You will return the following from your server:
require('url');
var r = url.parse(req.url,true);
r.query.callback + '(' + some JSON + ')'
3) If you don't care about all browser compatibility you can use CORS:
You can see a much better example than I would be able to write Here
Cross domain ajax requires special support from your server.
Either CORS: http://en.wikipedia.org/wiki/Cross-origin_resource_sharing
Which not all browsers support yet. It involves special headers in both the request and response that tell the browser that one domain is allowed to communicate with the other, and for what data.
Or JSONP: http://en.wikipedia.org/wiki/JSONP
WHich will work anywhere, but has some implementation limitations. It involves the server wrapping the response in a javascript function callback that will execute and pass in that data you want.
Either way, the server needs to be setup for each of these approaches.
I think your problem is Same Origin Policy. Your browser must get webpage from node.js instance.
Otherwise, you must use something like CORS. There also good question on SO: Ways to circumvent the same-origin policy.