Redirecionamento HTTPS em aplicações NodeJS

É super importante que você use o seu site por HTTPS atualmente. E dada a facilidade que é usar o certificado grátis do Let’s Encrypt, não há mais desculpas!

Porém, o redirecionamento de requisições inseguras HTTP para HTTPS devem ser feitas manualmente pela sua aplicação. E se você já fez isso em casa ou em um servidor que não passa por load balancers, o processo é um pouco diferente.

Como é feito originalmente no Express:

app.use((req, res, next) => { //Cria um middleware onde todas as requests passam por ele
    if (req.secure) //Se a requisição feita é segura (é HTTPS)
        next(); //Não precisa redirecionar, passa para os próximos middlewares que servirão com o conteúdo desejado
    else //Se a requisição não for segura (é HTTP)
        res.redirect(`https://${req.hostname}${req.url}`); //Redireciona a requisição para o mesmo host e url mas com HTTPS e termina a request
});

Porque isso não funciona na Umbler?

Segundo a documentação do express, req.secure é equivalente a executar req.protocol === 'https' mas isso na Umbler sempre será falso. Porque?
Na Umbler, a sua aplicação não é exposta diretamente à internet. Ela passa por outros servidores de proxy, load balancing etc dentro do nosso datacenter. Por isso, requisições HTTPS são descriptografadas antes de chegarem na sua aplicação e quando chegam sempre são HTTP.

Então como eu vou saber se a requisição original foi em HTTP ou HTTPS?

Esse não é um problema novo, e já existe uma solução que é amplamente aceita, que é incluir o header
X-Forwarded-Proto na requisição que contém o protocolo original que o cliente se comunicou com o servidor de load balancing. Logo, é necessário checar esse header ao invés do protocolo.

Como deve ser feito:

app.use((req, res, next) => { //Cria um middleware onde todas as requests passam por ele
    if (req.headers["x-forwarded-proto"] == "http") //Checa se o protocolo informado nos headers é HTTP
        res.redirect(`https://${req.hostname}${req.url}`); //Redireciona pra HTTPS
    else //Se a requisição já é HTTPS
        next(); //Não precisa redirecionar, passa para os próximos middlewares que servirão com o conteúdo desejado
});

Problemas comuns:

HTTPS funciona, mas ele ainda não está redirecionando automaticamente

Normalmente o problema é causado pelo middleware que serve a sua página vir antes do middleware que faz o redirecionamento, por exemplo:

var express = require("express");
var app = express();

app.get("/", (req, res) => {
    res.send("Hello world!");
});

/*O middleware mencionado acima para o redirecionamento*/

app.listen(process.env.PORT || 3000, () => console.log("Servidor escutando"));

O que acontece nesse caso é o seguinte: o middleware app.get("/"[...] foi declarado antes que o que redireciona, e quando o usuário acessa o site, cai nesse middleware > envia o conteúdo que o cliente pediu > termina ali. O middleware que detecta e redireciona nunca é chamado. Por isso, é ideal que ele seja o primeiro middleware a ser definido após o instanciamento do express var app = express();

Está redirecionando, mas quando tenta acessar com HTTPS dá erro de certificado

Nesse caso, pode ser que você não tenha ativado o SSL ou não foi ativado corretamente. Nessa caso, recomendamos que você dê uma olhada no nosso artigo sobre SSL. E se mesmo assim o problema persistir, nos chamar no suporte :wink:

Deseja redirecionar para WWW também?

1 Curtida