FuzzyTemper
FuzzyTemper

Reputation: 783

NestJS redirect HTTP to HTTPS / force SSL

Building a NestJS Application I want to route ALL incoming traffic through https without inconvenience for the user.

So far there are two ways I know, both doesn't fit my requirements.

  1. Set up two servers for http and https and than redirect traffic per route/api endpoint, which is really not DRY and cannot be best practice. Doc redirect

  2. By only creating the https server, the user would always be forced to type the https address manually what I don't want. Doc https

Ideally I would assume a solution where https is checked and forced the very first moment some one is hitting the server by just typing example.com. I think this would best be done in main.ts of my NestJS application.

Upvotes: 5

Views: 6105

Answers (3)

MegaSpaceHamlet
MegaSpaceHamlet

Reputation: 371

Heroku Users

npm install express-sslify --save

Then, in your main.ts file:

import enforce from 'express-sslify';

async bootstrap() {
    // create your app

    // Must be the FIRST middleware applied
    // Must add in the 'trustProtoHeader' option
    // (I only add this for production, but you can do whatever suits you)
    if (process.env.NODE_ENV === 'production') {
        app.use(enforce.HTTPS({ trustProtoHeader: true });
    }

    // other stuff
}

If your NestJS application is hosted on Heroku, you cannot have 2 servers running on an HTTP and HTTPS port. You also cannot simply redirect to https, because Heorku sends the data from their outward-facing load balancers internally over HTTP traffic, and the app will redirect infinitely.

See Heroku Docs and express-sslify docs, especially the section there regarding Heroku.

Upvotes: 2

R. V.
R. V.

Reputation: 836

For my use case, I see no reason to bloat the server with reverse proxy layer while node http servers are fully featured. Since question is related to NestJS, here I present simple native solution, using Nest middleware. Of course, u will have to also follow the NestJS documentation on hosting two servers, which is again fairly simple.

import { HttpStatus, Injectable, NestMiddleware } from '@nestjs/common';
import { Request, Response } from "express";

@Injectable()
export class HttpsRedirectMiddleware implements NestMiddleware
{
    use(req: Request, res: Response, next: () => void)
    {
        if (!req.secure)
        {
            const httpsUrl = `https://${req.hostname}${req.originalUrl}`;
            res.redirect(HttpStatus.PERMANENT_REDIRECT, httpsUrl);
        }
        else
        {
            next();
        }
    }
}

We simply ask on request object whether conneciton is secure, if not, we incite browser to permanently redirect to same url, but this time prefixed with https://. The middleware class above is then to be registered for all routes within configure() method of AppModule.

configure(consumer: MiddlewareConsumer)
{
    consumer.apply(HttpsRedirectMiddleware).forRoutes("*");
}

Upvotes: 8

Przemyslaw Jan Beigert
Przemyslaw Jan Beigert

Reputation: 2486

For production release you will probably use nginx. Nginx will be listen on port 80 and redirect to nestJS port. Advantage of this solution is easy redirecting to https. In you config you can put something like this

server {
       listen         80;
       server_name    example1.com example2.com;
       return         301 https://$host$request_uri;
}

server {
       listen         443 ssl;
       server_name    example1.com example2.com;
       ...
}

So each http request will be redirect to https. And your application don't have to care about http request because each of them will be redirect before.

Upvotes: 7

Related Questions