Stop 16 · Security Across the StackTopics · 7/7

HTTPS Everywhere

Part of the Full Stack Developer Roadmap

In short

Your React app is on HTTPS, your API is on plain HTTP, and suddenly every fetch fails in production. One weak link breaks the whole chain, so both ends need HTTPS.

Serving both your frontend and backend exclusively over HTTPS in production — mixed content (an HTTPS page calling an HTTP API) is blocked by browsers and a common full-stack deployment mistake.

The purple blob carries a locked cash box to an armoured van while an open rickshaw waits unused.

Think of it like this

The cash van, every single leg

A bank moves cash in a locked armoured van. If one leg of the trip uses an open cycle-rickshaw, the locks on the other legs don't help. Browser to frontend, frontend to API, API to database: every leg needs its own lock.

Watch it happen

One page load, three locked legs

Browser
Frontend host
API
Database

GET http://shop.in

1/6Someone types the address without https. The request goes out in plain text.

The big ideas

What you need to know

Mixed content gets blocked

An HTTPS page that calls an http:// API or loads an http:// script is blocked by the browser. Check your API base URL env variable first.

Redirect, then remember

Redirect HTTP to HTTPS with a 301, then send Strict-Transport-Security so browsers skip plain HTTP on later visits.

Secure cookies need HTTPS

Cookies marked Secure are only sent over HTTPS. Auth that works on localhost can silently break on a half-HTTPS deploy.

Inside the cloud counts too

Use TLS from your API to the database and other services. 'It's a private network' is not a lock.

See it in code

Walk through the code

ts
1import express from "express";2import helmet from "helmet";3 4const app = express();5app.set("trust proxy", 1); // TLS ends at the load balancer in front of us6 7app.use((req, res, next) => {8  if (req.secure) return next();9  res.redirect(301, `https://${req.headers.host}${req.originalUrl}`);10});11 12app.use(helmet.strictTransportSecurity({ maxAge: 31536000, includeSubDomains: true }));13 14// Frontend .env.production15// NEXT_PUBLIC_API_URL=https://api.shop.in

1/4Without this, req.secure is always false behind a proxy and you get an endless redirect loop.

Behind a load balancer, trust proxy lets Express read the original protocol. Then redirect plain HTTP and tell browsers to stick to HTTPS for a year.

Save yourself the pain

Common mistakes

Oops

Testing only on localhost, where mixed content and Secure cookies behave differently, then shipping.

Do this instead

Test on a real HTTPS preview deploy. Open the console and look for mixed content warnings before going live.

Oops

Turning on HSTS with includeSubDomains before every subdomain supports HTTPS.

Do this instead

Start with a short max-age, check every subdomain works on HTTPS, then raise it to a year.

Your mission

Hunt the plain HTTP leg

~25 min

Quick check

Your site is on https://app.in and calls fetch("http://api.app.in/me"). What happens in a modern browser?

Go deeper

  1. 1Confirm both your deployed frontend and backend serve HTTPS with valid certificates.
  2. 2Check your frontend's API base URL uses `https://`, not `http://`, in production.
  3. 3Understand why browsers block 'mixed content' requests from an HTTPS page to an HTTP endpoint.

More topics at this stop

Stuck on this topic? Ask an Insider

Get 1:1 guidance from people who've walked this exact path — on the InsideEdge app.

Download
InsideEdge