Skip to content

Instantly share code, notes, and snippets.

@bnoordhuis
Created February 8, 2013 16:31
Show Gist options
  • Star 24 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save bnoordhuis/4740141 to your computer and use it in GitHub Desktop.
Save bnoordhuis/4740141 to your computer and use it in GitHub Desktop.
A node.js proxy that accepts HTTP and HTTPS traffic on the same port.
var fs = require('fs');
var net = require('net');
var http = require('http');
var https = require('https');
var httpAddress = '/path/to/http.sock';
var httpsAddress = '/path/to/https.sock';
fs.unlinkSync(httpAddress);
fs.unlinkSync(httpsAddress);
var httpsOptions = {
key: fs.readFileSync('/path/to/key.pem'),
cert: fs.readFileSync('/path/to/cert.pem')
};
net.createServer(tcpConnection).listen(8000);
http.createServer(httpConnection).listen(httpAddress);
https.createServer(httpsOptions, httpsConnection).listen(httpsAddress);
function tcpConnection(conn) {
conn.once('data', function(buf) {
// A TLS handshake record starts with byte 22.
var address = (buf[0] === 22) ? httpsAddress : httpAddress;
var proxy = net.createConnection(address, function() {
proxy.write(buf);
conn.pipe(proxy).pipe(conn);
});
});
}
function httpConnection(req, res) {
res.writeHead(200, { 'Content-Length': '4' });
res.end('HTTP');
}
function httpsConnection(req, res) {
res.writeHead(200, { 'Content-Length': '5' });
res.end('HTTPS');
}
@basarat
Copy link

basarat commented Jan 28, 2015

from: http://stackoverflow.com/a/23975955/390330

You don't need to listen on same port if you follow convention

By convention when you request http://127.0.0.1 your browser will try to connect to port 80. If you try to open https://127.0.0.1 your browser will try to connect to port 443. So to secure all traffic it is simply conventional to listen to port 80 on http with a redirect to https where we already have a listener for https for port 443. Here's the code:

var https = require('https');

var fs = require('fs');
var options = {
    key: fs.readFileSync('./key.pem'),
    cert: fs.readFileSync('./cert.pem')
};

https.createServer(options, function (req, res) {
    res.end('secure!');
}).listen(443);

// Redirect from http port 80 to https
var http = require('http');
http.createServer(function (req, res) {
    res.writeHead(301, { "Location": "https://" + req.headers['host'] + req.url });
    res.end();
}).listen(80);

Test with https:

$ curl https://127.0.0.1 -k
secure!

With http:

$ curl http://127.0.0.1 -i
HTTP/1.1 301 Moved Permanently
Location: https://127.0.0.1/
Date: Sun, 01 Jun 2014 06:15:16 GMT
Connection: keep-alive
Transfer-Encoding: chunked

@davidlondono
Copy link

It has a problem for multipart requests, the package is too large and some times it my not work

@DylanPiercey
Copy link

Does anyone know if any issues exist with this method?

@CatTail
Copy link

CatTail commented Jan 4, 2017

@davidlondono can you provide sample code to reproduce the problem?

@ildrm
Copy link

ildrm commented Apr 21, 2018

Thank you @basarat . but when you use http://IP:PORT , req.headers['host'] returns IP:PORT and you should split IP from that and attach :PORT to that. 😁

@ObscurusGrassator
Copy link

This is error generator.
Please add to code:
conn.on("error", err => console.error(err) );

The better code is in the second answer to:
https://stackoverflow.com/questions/22453782/nodejs-http-and-https-over-same-port

But it also returns the same error: write EPIPE (or read ECONNRESET)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment