Mixed content: my app works on http and breaks the moment I add httpsSolved

Help & QuestionsDawson3 replies

Jump to the accepted answer

DawsonMember#1

I have an application that works fine over plain HTTP. I put a certificate in front of it, and now parts of the page are blocked and a fetch from the browser fails.

The console says "mixed content" and refuses to load something. The page itself is served over HTTPS, so I do not understand what is being mixed.

3 replies

HermanMember#2

Accepted answer

"Mixed content" means exactly what it says: an HTTPS page is not allowed to load an HTTP resource. The browser blocks it, and it does not matter that the resource is on your own server.

The list of things to check, in the order they usually turn up:

1. An absolute http:// URL in the page. Grep the built HTML and the JavaScript bundles for http:// and for a site URL stored in a config that was written before the certificate existed. This is the most common cause by a wide margin.

2. The API base URL. If the frontend calls an API at http://api.example.com, the whole app is broken over HTTPS even though the page loads. The symptom you describe — the page loads, a fetch fails — is almost always this.

3. A redirect. A resource that is requested over HTTPS and redirects to HTTP is also blocked, and the message in the console shows the redirect target.

4. A websocket. ws:// is blocked from an HTTPS page; it has to be wss://. A websocket that works over HTTP and silently never connects over HTTPS is the same bug in a different place.

5. A third-party resource. A script, a font or an image loaded over HTTP from somewhere else is blocked, and it is the one you will not find by grepping your own code.

The fix for all five is the same in principle: make every URL scheme-relative or HTTPS, and put the scheme in one place rather than in the code. An application that can be told "the public URL is https://..." does not have this bug; an application with http:// written into a template has it in every environment.

IvanMember#3

In reply to Herman (#2)

The "one place" point is the one that matters. We moved the public URL into a single runtime config value that the templates and the bundles read, and the class of bug disappeared.

Before that, every deployment to a new domain was a search and replace, and every one of those was a chance to miss a URL.

DawsonAuthorMember#4

In reply to Ivan (#3)

It was the API base URL, exactly as you said, and it was in a config file that was correct for the old environment.

The scheme-relative suggestion is what I am taking from this: one place, and the scheme comes from the deployment rather than from the code. Accepted, thank you.