简体   繁体   中英

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).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM