HTTP to HTTPS Redirection with Laravel Vapor
Tags: laravel, aws, https, vapor
Published: 2021-10-03 11:10:37

One of the limitations of Laravel Vapor is the inability to serve HTTPS. This isn't because of Vapor though, it comes from the Api Gateways from AWS that Vapor is built on. The problem with that is that when browser try to reach your domain via HTTP, nothing happens and they get an error screen, this is annoying for users that simply type your domain name in the url bar on IOS Safari for example as it won't try to contact the HTTPS port and just fail.

After two days of fighting with Cloudfront and Vapor, I finally got it working! With one caveat: If I change the domains associated to my Vapor environment in vapor.yml, I will experience a small downtime.

Important thing to note, this cannot work with the default SESSION_DRIVER which is the cookie driver as the headers become too large. 

I'm using dynamodb as driver. Also, I'm using Api Gateway V2 and Route 53 as DNS so Vapor handles my DNS records ! If Vapor doesn't handle your DNS records you might be able to bypass some of this by changing the DNS records yourself to point at your Cloudfront distribution. In my case it would make my deployments fail.

*Try this on a staging environment and test everything out carefully before trying it on production. Try to log in etc to make sure sessions work as well!*

For the example, well say that we have a site that is currently deployed on `example.com` and `www.example.com`.


# Creating the Cloudfront distribution


The idea is pretty simple, we'll put a Cloudfront distribution in front of our Api Gateway to act as a reverse proxy and redirect port 80 to port 443 when applicable.

Create a new Cloudfront distribution and use a subdomain of your choice as the origin url, that will be the new url of our Api Gateway that we will setup later on. Let's use `gateway.example.com` !

Give it a name of your liking then scroll down to the **User** section and select **"Redirect HTTP to HTTPS"** as **User protocol policy** and **"GET, HEAD, OPTIONS, PUT, POST, PATCH, DELETE"** as **Allowed HTTP methods**.

Regarding the Cache settings, select the **"Legacy cache settings"** and select **"All"** for **Headers**, **Request query** and **Cookies**.

In the **Settings** section, select the pricing category that makes the most sense to you, I'm using "Only Northern America and Europe" but it depends where your users are.

As "Alternative Domain Names", make sure to add `www.example.com` and `example.com`. Then, right under that, create an SSL certificate for those. I just used a wildcard certificate (*.example.com, example.com). You might need to add gateway.example.com in there but I don't think so !

Once you're done, click the create button and you're good to go !


# Updating vapor.yml


The domains section of your vapor.yml should look a little bit like this by now :

```
domain:
  - www.example.com
  - example.com
```

Change it to this :
```
domain: gateway.example.com
```

And, once you're ready, deploy your application but BE AWARE that your application won't be reachable until you complete the next step (pretty fast).


# Creating the Custom Domains on the Api Gateway


Go to your **Api Gateway** settings on AWS, in the Custom Domains section. Your `www.example.com` and `example.com` domains should have disappeared (deleted by Vapor) after the deployment. You simply need to recreate them both (don't forget to attach the **certificate**, you normally created one already via Vapor beforehand when attaching your custom domain for the first time).

Then, for both of those custom domain, setup the **API Mappings** to be the same as the ones created by Vapor on `gateway.example.com`. Select the right API Endpoint and Step (there is only one most of the time) then click save ! 

Do that for both domains and, after a few seconds, your app should now be accessible and redirect HTTP to HTTPS successfully :)


## Conclusion


I'm by no means an AWS expert so there might be ways to do this in a safer or more optimized way, if that's the case don't hesitate to comment down below.

As I said above, if you change the domains in your vapor.yml, you will need to re-do the last step so keep that in mind. I will personnaly work on creating an after-deploy script for Vapor that will ensure those Custom Domains exist and re-create them if they don't !