Redirecionar para WWW NodeJS

A função de redirecionar para WWW é importante caso esteja usando um add-on como o cloudflare, por exemplo. Onde para obter os benefícios da CDN é necessário que seja usado o CNAME WWW.
Em PHP é bem documentado como poderia ser feito isso. Tanto no .htaccess quando no próprio código. Se for WordPress é mais fácil ainda, pois não é nem necessário editar nada manualmente.
Porém em NodeJS, a solução pode não parecer tão óbvia. Visto que é menos comum aplicações Node utilizando a Cloudflare.
Esse post será construído em cima do meu outro post sobre redirecionamento para HTTPS. Pois vários daqueles conceitos se aplicam para essa funcionalidade também.

Apenas redirecionar para WWW mantendo o protocolo

app.use((req, res, next) => {
    if (!req.hostname.startsWith("www."))
        res.redirect(`${req.headers["x-forwarded-proto"]}://www.${req.hostname}${req.url}`);
    else
        next();
});

Redirecionar para WWW e HTTPS em um único middleware

app.use((req, res, next) => {
    if (!req.hostname.startsWith("www.") || (req.headers["x-forwarded-proto"] || "").endsWith("http"))
        res.redirect(`https://${req.hostname.startsWith("www.") ? "" : "www."}${req.hostname}${req.url}`);
    else
        next();
});

Cuidado

Note que, ao contrário do exemplo dado no post sobre redirecionamento para HTTPS, esses middlewares não funcionam rodando localmente. Isso porque o req.hostname também funcionará localmente, e perguntar se ele inicia com www. sempre será falso. Ele então tentará redirecionar para https://www.localhost que não funcionará por três motivos. O primeiro é que não existe www para o localhost. O segundo é que ele não mantém a porta. Então não acessará pela 3000. O terceiro motivo é que se for usado o primeiro exemplo, que mantém o procolo, ele redirecionará para undefined://www.localhost. Pois o header x-forwarded-proto não é criado localmente.
Se um dos requisitos é que funcione localmente também, sem ser necessário identificar o ambiente e registrar a rota de acordo, veja os dois exemplos adaptados:

Exemplos acima porém funciona localmente também

Nesse caso, usamos o fato de que o header x-forwarded-proto só estar presente quando rodando na Umbler para a nossa vantagem. Pois exigindo que ele seja definido no If para dar continuidade as outras condições faz com que se ele não for definido, o redirecionamento nunca ocorrerá.

Apenas redirecionar para WWW mantendo o protocolo

app.use((req, res, next) => {
    if (req.headers["x-forwarded-proto"] != undefined && !req.hostname.startsWith("www."))
        res.redirect(`${req.headers["x-forwarded-proto"]}://www.${req.hostname}${req.url}`);
    else
        next();
});

Redirecionar para WWW e HTTPS em um único middleware

app.use((req, res, next) => {
    if (req.headers["x-forwarded-proto"] != undefined && (!req.hostname.startsWith("www.") || (req.headers["x-forwarded-proto"] || "").endsWith("http")))
        res.redirect(`https://${req.hostname.startsWith("www.") ? "" : "www."}${req.hostname}${req.url}`);
    else
        next();
});

Olá, acabei de mover meus sites para usar o cloudflare.

O que estou vendo é que o https://www.meusite.com.br funciona perfeitamente.

Porém o https://meusite.com.br não chega no servidor da umbler e morre no ERR_SSL_PROTOCOL_ERROR

E o http://meusite.com.br chega no servidor da Umbler. Porém… o https:// já o cached no browser e tal.

Acho que a pergunta principal é, qual seria a maneira de servir o site com https sem o www mesmo usando o cloudflare? Seria uma configuração especifica de certificado no lado do cloudflare, ou alguma configuração especifica de DNS no lado da Umbler/Route53?

Agradeço a ajuda.

1 curtida

Olá, @Felx! :smiley:

Eu testei de vários jeitos, e o melhor que eu encontrei até o momento é fazer com que todas as requisições, www ou não, passem pela cloudflare primeiro. Podendo assim reaproveitar o mesmo certificado!

Isso consiste em alterar os seus nameservers para a cloudflare e efetuar a configuração no painel deles, que seria criar o apontamento A como proxied apontando para o IP do seu servidor (mesmo que pinga o domínio temporário).

Assim, publicamente o IP será da cloudflare e irá a requisição para o servidor deles primeiro (onde o certificado é válido), então a requisição será repassada para nós

Vale notar que para isso funcionar, é preciso ter o modo de criptografia definido como Flexible:

1 curtida

Estou usando a configuração em “Conectar usando o DNS de terceiros”, a Umbler da 2 CNAME records especificas para o cloudflare.

identar texto pré-formatado por 4 espaços
resolve-to-cloudflare -> domain-name.com
www -> www.domain-name.com.cdn.cloudflare.net

SSL/TLS o Umbler configura para Flexible por padrão

Você pode ser um pouco mais especifico, pois sou meio disléxico, e não sou um mestre Jedi em DNS, uma lista de 1 para 1 me ajuda muito.

Pelo que entendi:

  • Remover a autoconfiguração da da Umbler com Cloudflare apontando o A proxied para o servidor da Umbler…

Só essa parte remover a integração da Umbler com a Cloudflare não ficou muito clara para mim.

Obrigado @ThFnsc vc me ajuda muito.

  • Desabilitei a integração automática da umbler com cloudflare
  • criei o website no cloudflare
  • movi minhas configurações de DNS do AWS Route53 para o Cloudflare
  • Apontei o A record na cloudflare para o IP da Umbler.

Funcionou como eu esperava. Até melhor do que eu esperava. Recomendo para quem estiver lendo esse tópico :+1:

Obrigado mais uma vez Thiago .

De nada, @Felx!
Fico feliz que funcionou :smiley: