I was wondering how can I create a https server in node listening on Port 443 in a way that when I type :
https://my.ip.address:443 it should work.
https://my.ip.address it should work.
my.ip.address (without the https://) it should work and redirect me to https)
my.ip.address:443 it should work and redirect me to https
So far I was only able to make the first and second url work.
So my question is how can I make it also work for the other two possibilities (the final two). Thanks
If you type my.ip.address into a browser's address bar then it will request http://my.ip.address:80. To get that to work with your SSL version you need to:
Listen for HTTP (not HTTPS) on port 80
Issue a 301 HTTP Redirect to the SSL site
If you type my.ip.address:443 into a browser, then it will request http://my.ip.address:443. This will try to make an HTTP request without setting up SSL first and get an error. There is nothing you can do about that.
You can make redirects from http to https.
Via nginx
https://github.com/vodolaz095/hunt/blob/master/examples/serverConfigsExamples/nginx.conf#L22-L39
server {
listen 80;
server_name example.org;
rewrite ^ https://$host$request_uri? permanent;
}
Via expressjs middleware
https://github.com/vodolaz095/hunt/blob/master/examples/index.js#L133-L139
something like this:
app.use(function (request, response, next) {
if (request.protocol === 'http') {
response.redirect('https://yourhostname.com' + request.originalUrl);
} else {
next();
}
});
Related
I have a simple node http server set up currently, I'm trying to build the server so that it only accepts post requests from certain domains. I'm trying to get the domain of the server that made a post request to my node server but can't quite figure it out.
In my test environment, I am making the post request from localhost:3000 to my node server which is running on localhost:9220. I have been examining the req object but can't seem to find localhost:3000 mentioned anywhere in it.
http.createServer(function (req, res) {
if(req.method == 'POST')
{
// Here is where I want to find the domain of the server
// making the request
{
}).listen(9220);
It's probably simple but I am having trouble
thanks for the help!
There is no way to do this reliably.
If you make a cross-origin Ajax request, a browser will add an Origin header to it. If you submit a form, a browser might add a Referer header to it.
I was needed to redirect http to https and found this code:
app.enable('trust proxy');
app.use((req, res, next) => {
if (req.secure) {
next();
} else {
res.redirect('https://' + req.headers.host + req.url);
}
});
I'm using heroku to host my project, I noticed that heroku as default issued *.herokuapp.com cert, so I can use http and https as well.
When looked at req.secure within app.use callback, without app.enable('trust proxy'), req.secure is always false, when I add app.enable('trust proxy') it's false for about 2 times and after the https redirection it's switches to true.
app.enable('trust proxy'), the docs:
Indicates the app is behind a front-facing proxy, and to use the
X-Forwarded-* headers to determine the connection and the IP address
of the client.
My question:
Why would my server be behind a proxy?(is it relates to the issued *.herokuapp.com cert?), if someone could explain how all fits together, I mean, why my server is behind a proxy? and why without app.enable express won't identify(or accept) secure connection?
If your not running behind a proxy, it's not required. Eg, if your running multiple websites on a server, chances are your using a Proxy.
X-Forwarded-For header attributes get added when doing this so that your proxy can see what the original url was, proxying in the end will be going to localhost you see. The reason why it's needed is that X-Forwared-For can be faked, there is nothing stopping the client adding these too, not just a proxy. So trust-proxy should only be enabled on the receiving end, that would be behind your firewall. Because you have control, you can trust this.
So in a nutshell, if your website is running behind a proxy, you can enable it. If you website is running direct on port 80, you don't want to trust it. As the sender could pretend to be coming from localhost etc.
Answers to this question explain how to route sub domains in Node.js with Express.
I want to know how to do it without Express.
Here's my server module, which returns a server object:
module.exports.serve = function(port) {
var server = https.createServer(options, function(req, res) {
// Parse & process URL
var reqInfo = url.parse(req.url, true, true),
path = reqInfo.pathname;
debug.log("Client [" + req.connection.remoteAddress +
"]requesting resource: " + path);
// Quickly handle preloaded requests
if (preloaded[path])
preloadReqHandler(req, res, preloaded[path], path);
// Handle general requests
else generalReqHandler(req, res, reqInfo);
}).listen(port);
return server;
};
No need to go into detail with the modules that handle the requests, I'm just interested in how to detect www.example.com and route it to example.com or vice-versa, via my server.
Just to add as much detail as possible, my goal here is to route all traffic from http://www.example.com and http://example.com and https://www.example.com and send it all to https://example.com. To do that, I think I just need to learn how to route the www sub domain, and then listen on both the http and https ports for that routing.
Since HTTP 1.1, user agents send the Host request header which specifies the domain. So you can get the domain (including the port if specified) from req.headers['host'] and apply your custom domain routing logic.
If you're talking with a HTTP 1.0 or older user agent, then just reply with "505 HTTP Version Not Supported" or serve some default content.
Trying to get Adobe's Socket object up and running. I have this code:
var reply = "";
var conn = new Socket;
// access Adobe’s home page
if (conn.open("www.adobe.com:80"))
{
// send a HTTP GET request
conn.write ("GET /index.html HTTP/1.0\n\n");
// and read the server’s reply
reply = conn.read(999999);
conn.close();
alert(reply.toString());
}
else
{
alert(conn.error);
}
And it doesn't work. conn.error is fired, so I know the problem is with conn.open. This is the error message I get:
Tried a bunch of other sites too; nothing worked. But if I switch www.adobe.com:80 to localhost:8080, everything works as expected.
EDIT
I've definitely narrowed it down to being a proxy problem. But I don't know what to do about it, if I have to fix in my script or if I have to talk to IT to see about allowing proxy connections.
Here's where I'm at with my code:
if (conn.open("proxyserver.com:port"))
{
conn.write ("CONNECT www.adobe.com:443 HTTP/1.0\n\n");
reply = conn.read(999999);
alert(reply.toString());
}
This gets me the following:
But I'm not able to do anything beyond that. I can only do port 443 (https, I think); port 80 doesn't work on any site. I think this is more of a proxy problem than a script problem. When I do port 443 and get a connection, though, I don't know how to do anything with that connection. I tried sending a GET request afterwards and it returned blank.
Make sure your firewall isn't blocking access to your proxy server - the particular port may need to be opened, too.
Or, maybe the proxy is not set up to use port 80? If port 443 is used, isn't that SSL; do you need a certificate? It looks like your proxy only accepts SSL connections.
Maybe try with an ipaddress instead of a domain name: 192.150.14.12:80 is the one the adobe pdf provides.
I'm running a node.js express 3 server with no proxies and using SSL.
I'm trying to figure out how to force all connections to go through https.
Google searching shows me this:
https://groups.google.com/forum/#!topic/express-js/Bm6yozgoDSY
There's currently no way to force https redirects, though that seems
like a bit of a strange work-around. We have an https-only app and we
just have a simple ~4 line node http server that redirects, nothing
fancy
Which is what I need, but he doesn't say what those 4 lines are.
How do we do this? Thanks.
I don't really understand the point in starting two servers when only one can do the job perfectly. For example, by adding a simple middleware in your server file:
app.use(function(req, res, next) {
if(!req.secure) {
return res.redirect(['https://', req.get('Host'), req.url].join(''));
}
next();
});
This will redirect any non-secure request to the corresponding HTTPS page. For example, http://example.com/ to https://example.com/ and http://example.com/foo?bar=woo to https://example.com/foo?bar=woo. This is definitely the behavior I would expect. Maybe you should filter this by host, so it redirects only on domains for which you own and installed a proper certificate.
If your app is running behind another server like Nginx, you may want to add the configuration parameter app.set('trust proxy', true). Or, even better, make Nginx do the redirect itself, which will be more efficient than any Node.js app.
Edit: According to my benchmarks, join is a little faster than + for concatenating strings. Nothing dramatic, but every win is a win...
You should create a second server listening on 80 and redirect with a 301 header to your https server:
var express = require('express');
var app = express();
app.get('/', function(req, res, next){
res.redirect('https://' + app.address().address)
});
app.listen(80);
I had a similar problem and the redirect solution is not suitable for me because essentially I want to get rid of the browser's insecure warning,
So instead of redirect every message, I did:
app1 = new express()
app1.get('/', function(req, res) {
res.sendFile(path.join(__dirname + '/redirect.html'));
});
app1.listen(80, function(){'redirect server running on 80 port'})
and in the redirect.html is just a redirecting html file:
<meta http-equiv="refresh" content="0; URL='https://my-site.com'" />
Of course, this won't work for complicated cases when you want to redirect all routings, but for me, I only want to redirect my homepage to my https homepage and get rid of the browser's insecure warning. Hope this help somebody!