概要
Djangoアプリを使用していたらMixed Content
というエラーになりました。
少しイレギュラーな原因でしたが、備忘も兼ねて紹介します。
Mixed Contentエラー
ブラウザのコンソールに表示されたエラーは以下です。
Mixed Content: The page at 'https://xxxxx' was loaded over HTTPS, but requested an insecure stylesheet 'http://xxxxx.css'. This request has been blocked; the content must be served over HTTPS.
該当と思われるDjangoのHTMLテンプレートを確認すると以下でした。
<img class="icon" src="{{ request.scheme }}://{{ request.META.HTTP_HOST }}/xxx/images/{{ tag.image_name }}">
上記は、現在のリクエストのスキームとホスト名に基づいて、画像の完全なURLを動的に生成するコードです。
・{{ request.scheme }}
:現在のリクエストのスキーム(httpまたはhttps)を取得
・{{ request.META.HTTP_HOST }}
:現在のリクエストのホスト名を取得
・/xxx/images/
:画像ファイルが配置されているディレクトリのパス
・{{ tag.image_name }}
:tagオブジェクトのimage_name属性を取得
この方法で動的にURLを生成していたのが原因でした。
このアプリはAWSのロードバランサーにより、アプリケーション側がHTTPで返したものをHTTPSに変換するルールが設けられていました。ただ、Djangoアプリケーション自体はHTTPでリクエストを処理しているため、request.scheme
がhttp
のままになります。
その結果、HTML内で生成される静的ファイルのリンクがhttp
になり、ブラウザ上でMixed Contentエラーが発生していたのです。
ブラウザ上ではHTTPSなのに、Djangoアプリとしては静的ファイルをHTTPで生成しているので、「Mixed Content」となったということですね。
解決方法
Djangoアプリではstatic
テンプレートタグの方がメジャーでしょう。
実際私も今までstatic
テンプレートタグを利用していましたし、これが一般的に推奨されていると思います。
Djangoのドキュメントもこちらですね。
{% static %} テンプレートタグは、静的ファイルの完全 URL を生成します。