Node simple http app respond 2 times - node.js

I trying to find my way into node.js transfering a local sports statistics application written in c#.
Writing the http server, i observe that every time i refresh (after the first time) the server to make a new request, i have 2 response.
I strip the code to eliminate every other possible cause and the "problem" still exists.
Code
var http = require("http");
var counter = 0;
var port = process.env.PORT || 3000;
var requestListener = function (req, res) {
counter += 1;
res.end("Hits: "+ counter);
};
var server = http.createServer(requestListener);
server.listen(port, function (err) {
console.log("server listen on port " + port);
});
Is this the normal behaviour or i missing something?

In a browser page, this is often caused by the browser requesting your page and then requesting some other resource from the same host (such as the favicon for the page). You can see exactly what is being requested to shine some light on what's happening by logging req.url:
var http = require("http");
var counter = 0;
var port = process.env.PORT || 3000;
var requestListener = function (req, res) {
// add logging for what url is being requested
console.log(req.url);
counter += 1;
res.end("Hits: "+ counter);
};
var server = http.createServer(requestListener);
server.listen(port, function (err) {
console.log("server listen on port " + port);
});
Is this the normal behaviour or i missing something?
This is normal and expected. If the extra request turns out to be a favicon request, then you can disable that as explained here: How to prevent favicon.ico requests?
Note: it is a bit unusual to have a web server that does not even look at the requesting URL and does the same thing no matter what path request was sent to it. If you were looking at the URL and branching your code based on the URL, you would likely be avoiding requests that you were not expecting.

Related

Request.headers missing or undefined

Hopefully somebody will find this a relatively simple answer, but it is beyond me at the moment. I have a Node.js/Express setup. I am simply trying to retrieve the client IP address upon each request to the site. My code is as follows:
const express = require('express');
const app = express();
const port = 3000;
...
// Start server...
var webServer = app.listen(process.env.PORT || port, function(request, response) {
console.log(" Received request for " + new Date());
var _FORWARD_IP = request.headers['x-forwarded-for'];
console.log('_FORWARD_IP (CLIENT IP ADDRESS): ' + _FORWARD_IP);
});
However this throws the following error:
"TypeError: Cannot read property 'headers' of undefined"
Therefore it seems there are no headers in the 'request' object within the 'app.listen' command. I am unsure how to resolve, this is the initial instance of dealing with something like this. If anybody knows an answer or a workaround it is greatly appreciated. I thank you in advance.
Regards
app.listen() just starts the server, telling it to listen for requests. There is no request at that point in your code.
This sounds like a job for some custom middleware
const port = process.env.PORT || 3000;
// Middleware
app.use((req, res, next) => {
const _FORWARD_IP = req.get('x-forwarded-for');
console.log('_FORWARD_IP (CLIENT IP ADDRESS):', _FORWARD_IP);
next();
});
app.listen(port, () => {
// This callback executes when the server is ready to accept connections
console.info(`Express server started on port ${port}`);
});

IP reported as null in Node.jsExpress...how is that possible?

I have a website with a Node.js/Express backend and I need to log the visitor's IP address. It seems this should be a fairly straightforward process, however I am having continuous difficulty with it. My code is similar:
const express = require('express');
const app = express();
var port = 443;
app.get('/', function (req, res) {
var site = req.hostname; //example returns "localhost" from "localhost:8080"
var splits = site.split("."); //"split" on "periods"
var subdomain = String(splits[1])
var _host = req.headers.host;
var _userIP = req.headers['x-forwarded-for'] || req.socket.remoteAddress || null;
console.log('_userIP is: ', _userIP); //returns 'null'
//...
});
//...
// Start server...
var webServer = app.listen(process.env.PORT || port, function(request, response) { console.log(" Received request for " + new Date()); } );
console.log('Listening on port ' + port);
//...
console.log("***CREATING WEBSOCKET SERVER");
var wsServer = new WebSocketServer({
httpServer: webServer,
// You should not use autoAcceptConnections for production
// applications, as it defeats all standard cross-origin protection
// facilities built into the protocol and the browser. You should
// *always* verify the connection's origin and decide whether or not
// to accept it.
autoAcceptConnections: false
});
For guidance I am using the following source for information: "https://stackoverflow.com/questions/8107856/how-to-determine-a-users-ip-address-in-node".
My console.log statement returns "null" as the value for the '_userIP' variable...why??? As I understand ANY connection made to the server should have some sort of IP address, correct? If that is the case then the 'null' as my 'fallback' variable definition should never be assigned, however it is...
Any advice is greatly appreciated.
BTW I have also attempted assigning the '_userIP' variable to "req.ip" as:
console.log('_userIP is: ', req.ip);
...without success. I believe it returned 'undefined' if I remember correctly.
I have also tried:
_userIP = req.header('x-forwarded-for') ||
req.connection.remoteAddress ||
req.socket.remoteAddress ||
req.connection.socket.remoteAddress;
This code throws an error, I believe because the 'req.connection.socket.remoteAddress' is deprecated...?
If it makes a difference I believe this code displays "::1" if it is run on localhost...which indicates it is functional. Why would the code fail to display a user IP address when executed on a 'real' server? Is it possible my server software (Plesk) may be somehow blocking the IP address?

Connecting Flash to Node via websockets - Crossdomain.xml issue

I am trying to set up a simple websocket server that communicates between a Flash AS3 client and a Node.js backend. The following code is when both the client and server are hosted locally. The code also functions properly when the swf is hosted locally connected to the server hosted on heroku. The socket only fails when both the swf and the server are hosted online.
Node.js Code (Server)
var WebSocketServer = require("ws").Server
var net = require('net');
var http = require("http")
var express = require("express")
var app = express()
var crossdomain = require('crossdomain')
var port = process.env.PORT || 5000;
app.use(express.static(__dirname + "/"))
var xml = crossdomain({ domain: '*' });
app.all('/crossdomain.xml', function (req, res, next) {
res.writeHead(200, { 'Content-Type': 'application/xml; charset=utf-8' });
res.write(xml);
//res.write(new Buffer([0x00]))
res.end();
});
var server1 = http.createServer(app)
server1.listen(port)
console.log("http server listening on " + port)
var wss = new WebSocketServer({server: server1})
wss.on("connection", function(ws) {
console.log("Connected");
ws.on("close", function() {
console.log("websocket connection close")
})
})
Crossdomain file - example.com/crossdomain.xml
<cross-domain-policy>
<allow-http-request-headers-from domain="*" headers="*"/>
<site-control permitted-cross-domain-policies="all"/>
<allow-access-from domain="*" secure="false"/>
</cross-domain-policy>
AS3 Code (Client) - I'm Using (https://github.com/theturtle32/AS3WebSocket)
import com.worlize.websocket.*;
Security.loadPolicyFile("http://example.com/crossdomain.xml");
var websocket:WebSocket = new WebSocket("ws://example.com", "*", "echo-protocol");
websocket.addEventListener(WebSocketEvent.OPEN, handleWebSocketOpen);
websocket.connect();
var con = false;
function handleWebSocketOpen(event:WebSocketEvent):void {
trace(event);
}
When the client is accessed from the server a request for the crossdomain.xml does occur and it gets returned successfully to the client, but at that point nothing happens anymore. I've been trying to solve this for ages with no luck. I did find that when you return the crossdomain file you need to end it with a 0x00 for it to be properly read, but I haven't found a way to make to that work. I've tried adding res.write(new Buffer([0x00])) to the response from the crossdomain request as well as several other modifications to no avail. These all seem to stop the xml file from being valid anyway.
I would greatly appreciate if anyone could help in getting this to work, I've been struggling with it for an extremely long time and can't quite seem to get this last step working.

Issues with Socket.IO with Chrome and Firefox

Another update:
The problem occurs when running on localhost as well. Since I figured out the problem comes from the proxy server, here's its code :
var serverBouncer = bouncy(function(req, res, bounce) {
var path = req.url;
var url = req.headers.host;
if (typeof url !== "string")
return;
var urlArray = url.split('.');
var bouncePort = port;
if (!isNaN(urlArray[0]))
bouncePort = parseInt(urlArray[0]);
else if (String(urlArray[0]).toLowerCase() === "www" && !isNaN(urlArray[1]))
bouncePort = parseInt(urlArray[1]);
bounce(bouncePort);
});
serverBouncer.listen(80);
Update:
I found where the problem came from!!! But I still need to find the solution... There seems to be issues with using newer versions of Socket.io (>= 1.0) with a proxy server (bouncy, in my case).
I recently updated Socket.IO from v0.9.16 to v1.4.5, as well as adding Express to the mix. However, now I cannot open multiple (number seems to vary) tabs in Chrome and Firefox without experiencing strange issues (Edge is the only one to work well). It either hangs, or partially loads html and other resources before it hangs.
After waiting, I often get the error :
Failed to load resource: the server responded with a status of 400 (Bad Request)
When I close one of the tab that's been hanging, it unblocks the other tabs that were also hanging.
The issues were not present before going through with the changes listed above.
I've been doing research for 2 full days and just now decided to post this, as I know it's very vague and I'm probably not providing enough information. As much as I'd like to, it would take a very long time to remember and list everything I tried during that time.
Using Windows 10 with Chrome v51.0.2704.103, Firefox v43.0.1. The server (CentOS) is using node v6.2.2 with mainly the following modules :
express#4.14.0
npm#3.9.5
socket.io#1.4.5
Here's some relevant server code :
var port = 8502;
var socketio = require('socket.io');
var express = require("express");
var http = require('http');
var app = express();
var server = http.createServer(app);
var io = socketio.listen(server);
server.listen(port);
app.get('/', function(req, res, next) {
//Returning index.html
});
io.on("connection", function(socket) {
//Some events...
});
Here's a bit of the client code :
var client = io.connect();
client.on('connect', function() {
//Some events
})
your binding before the server is listening, try something like this
var app = express();
server = app.listen(PORT, function () {
console.log('Example app listening on port ' + PORT + '!');
});
io.listen(server);
I managed to replace the bouncy module with nginx. See my other question for the solution.
nginx : redirect to port according to domain prefix (dynamically)

Intercept HTTP responses on an HTTPS server in Node.JS and Express

I'm just starting with node.js and express and I'm doing a simple HTTPS server. I've been working with nginx for some time and when I make an HTTP request to an HTTPS endpoint I get a "400 Bad Request" error. However, when using node.js the request never finishes.
How can I intercept an HTTP request in Express to be able to generate the "400 Bad Request" response?
This is my code:
var express = require('express');
var https = require('https');
var fs = require('fs');
var port = process.env.PORT || 8080;
var tls_options = {
key: fs.readFileSync('certs/server.key'),
cert: fs.readFileSync('certs/server.crt'),
ca: fs.readFileSync('certs/ca.crt'),
requestCert: true,
};
var app = express();
var router = express.Router();
router.get('/', function(req, res) {
res.json({ message: 'Checkpoint!!' });
});
app.use('/', router);
var secureServer = https.createServer(tls_options, app);
secureServer.listen(port);
console.log('Listening on port ' + port);
Until now the only thing I've been able to use is getting a 'connection' event every time a request arrives to the server:
secureServer.on('connection', function (stream) {
console.log('someone connected!');
});
Done. In fact, an HTTP request to an HTTPS socket ends after the default 120secs TLS handsahke timeout. This way I can end the request without waiting. I include the solution I used just for future references if anything needs the same functionality.
var secureServer = https.createServer(options, app);
secureServer.on('connection', function(socket) {
socket.on('data', function(data) {
var first_line = data.toString().split('\r\n')[0];
var pattern = /\bhttp\/1\.[01]$\b/i;
if (pattern.test(first_line)) {
var headers = {};
headers['Date'] = new Date().toUTCString();
headers['Connection'] = 'close';
var headers_string = '';
for (var name in headers) {
headers_string = headers_string + '\r\n' + name + ': ' + headers[name];
}
socket.end('HTTP/1.1 400 Bad Request' + headers_string);
}
});
There isn't a way of starting both HTTP and HTTPS servers on the same port. What most people do is either:
Start two servers (one HTTP and one HTTPS) on different ports, and redirect the HTTP traffic to HTTPS. Using Express it would mean the additional code:
// create two ports, one for HTTP and one for HTTPS
var port = process.env.PORT || 8080;
var httpsPort = 8081;
// redirect all HTTP requests to HTTPS
app.use(function(req, res, next) {
var hostname;
if (!req.secure) {
hostname = req.get("host").split(":")[0];
return res.redirect(["https://", hostname, ":", httpsPort, req.url].join(""));
}
next();
});
app.listen(port); // listen on HTTP
https.createServer(tls_options, app).listen(httpsPort); // listen on HTTPS
Or they use nginx or apache to handle outside connections (both HTTP and HTTPS) and redirect traffic to the Node server (which can then just run on HTTP).

Resources