酔人日月抄

東京下町に暮らす写真とPENTAXとスキーと時代小説とお酒とプジョーを愛するある男の日常

はてなブログのSSL化に備えて混在コンテンツ対応をユーザースクリプトで効率化する

 このエントリーは99%が自分用のメモ書き、残り1%は「はてなブログ」を使用しているブロガーさんにとって「もしかしたら役立つかも知れない」というだけの内容です。

 Googleが半ば強引に推し進めているWEBサイトのSSL化(https化)推奨の波に飲まれて、私が使用している「はてなブログ」においても、SSL化が進みつつあります。しかし、従来SSLなど気にしないで作ってきたこのブログをSSL化するにはいろいろハードルがあるらしく、サービス提供側の「はてな」も苦労しているようですし、ユーザーである私の方でもSSL化に向けていろいろと対応しなくてはなりません。

 最も大きい問題が「混在コンテンツ」の解消で、中でも手間がかかりそうなのがブログに貼り付けた写真です。SSL化されたサイトでは、SSL化されていないリンクからのimgタグによる画像貼り付けは禁止されており、そのままでは正常に表示されなくなってしまいます。

 同様にiframeで貼られたコンテンツや、外部javascriptなどもhttps化された参照元からしか許可されないので、これらについても対応が必要です。

f:id:hisway306:20180314212506p:plain
 特に古い記事において対応が必要になるのですが、タグの書き換えなどは一つ一つ手動でやっていくのはあまりにも大変なので、ユーザースクリプトで自動化を進めつつ、混在コンテンツ解消のための対応方法などをまとめてみました。

 かなり長くてごちゃごちゃになったので目次置いておきます。

はてなブログのSSL化進行中

 Gppgleが非SSLサイトの検索順位を落としたり、Chromeによる非SSLサイト接続時の"Not Secure"警告表示を強めていくなかで、「はてなブログ」もとうとう重い腰を上げてブログサービス全体のSSL対応を始めた、と公表されたのが昨年の9月のことでした。

 当初発表よりスケジュールは遅れ気味ですが、第一段階はすでに完了し、現在は第二段階が提供され始めたところです。このブログは独自ドメインを使用しているので、第三段階での対応となる予定です。いつ頃か分かりませんが多分あと半年くらいはかかりそうな気配です。

 そしてこの記事にも書いてありますが、ユーザーはただ待っていれば良いのではなく、自分のブログをSSL化するならば「混在コンテンツ」回避への対応を自分自身で行わなくてはなりません。SSL化された際に「混在コンテンツ」として問題になるのはhttpで配信されるスクリプトとimgタグで貼られた画像、iframeで読み込まれる外部リソースなどです。

 混在コンテンツに関しては、さらにこんなQ&Aページも公開されました。上記記事よりも細かいことが具体的に書かれています。

このブログでやらなくてはならないこと

 ということで、以上の情報を参考にしつつ、具体的にこのブログの状況に落とし込んでみると、私がやらなくてはならないことは以下のようになります。

  1. Flickrから貼った写真のうちimgタグの参照先がhttpリンクになってるコードをhttpsに書き換える
  2. Amazonの商品紹介リンクなどで使っているiframeタグの参照先がhttpのままになっているコードをhttpsに書き換える
  3. 外部サーバーから読み込んでいるスクリプトのうち、httpを参照しているものをhttpsへ変更する

 という3点に絞られます。細かいことを言えば、ごく一部の記事ではFlikcr以外の画像も貼ってあるし、各記事のアイキャッチ画像なども見直しが必要かも知れませんが、それは比較的マイナーな問題なので後回しにしても良いでしょう。

 ということで、今回は特に要修正箇所が圧倒的に多い1.と2.の課題について対処方法を検討していくことにします。

1. Flickr画像のimgタグ書き換え

 私の場合、ブログに貼り付けている写真のほとんどはFlickrに置いてあります。Flickr自身がSSL化を果たしたのは2014年初頭のこと。それ以降に作成した記事の写真リンクはすべてhttpsになっているのでそのままで問題ありませんが、それ以前の記事に貼った写真はhttpのままになっています。

 幸いなことにFlickrではSSL化された後も、個別写真へのURLは変更がないままSSL化されています。ですのでhttpで貼られた昔の画像リンクも、再度FlickrからURL取得&張り直しを行う必要はなくて、すでに貼り付け済みのimgタグのプロトコル指定部分に"s"を足してやるだけで済みます。

例えば、

 <img src="http://hogehoge.flickr.com/pompom.jpg">

というリンクは、

 <img src="https://hogehoge.flickr.com/pompom.jpg">

こう書き換えればOK。あるいは、

 <img src="//hogehoge.flickr.com/pompom.jpg">

というように、プロトコル指定を省略してしまうのもアリです。

 これはRelative Referenceという方法で、呼び出し元のプロトコルに従ってリンク先を呼び出すという動作をします。つまりhttpサイトからはhttpで、httpsサイトからはhttpsで参照先にアクセスしますので、参照先が両プロトコルに対応していれば問題ありません。そしてFlickrは実際にどちらからのアクセスも受け付けます。

 このブログではほぼ全ての記事に写真が貼ってあり、しかもそのほとんどがFlickrに置いてあるので、2014年以前の記事全てを書き換えるとしたら1000記事ほどが対象になります。しかも一記事当たり複数の写真が貼ってあることがほとんど。やることは単純だけど量が膨大でちょっと現実的ではありません。

タグ書き換えはユーザースクリプトで自動化する

 そこで、できるだけ省力化するために、要修正箇所を見つけて書き換えを行う作業を自動化することにしました。基本的な考え方は、2年半前にFlickrが埋め込みコードにお節介なタグを追加したときに、その余計なタグを消す作業を自動化した際ににとった方法と同じです。

 その顚末をまとめたのが↑この記事。ブラウザでブログ編集画面を開いたときにだけ走るスクリプトを作成しました。

 上記記事ではFirefox用としては定番だったGrasemonkeyというユーザースクリプト用のアドオンを使いましたが、最近はマルチブラウザ対応なTampermonkeyというアドオンのほうが人気があるようです。これはFirefoxだけでなく、ChromeやSafariやOperaやMicrosoft Edgeなどでも使えるそうです。

 以下はFirefox版のTampermonkeyを使った場合の例となります。他のブラウザでは細かいUIなどが異なっているかもしれませんが、重要な部分は同じはずです。

f:id:hisway306:20180314224047j:plain
 Tampermonkeyをインストールすると、ブラウザのアドレスバー右にTampermonkeyのアイコンが現れます。これをクリックするとこのようなメニューが開くので、まずはダッシュボードをクリックしてみます。

f:id:hisway306:20180314214434j:plain
 するとこのような画面になります。最初はユーザースクリプトは何もありませんので、矢印で示した「+」マークのタブをクリックすると...

f:id:hisway306:20180314214429j:plain
 このような新規スクリプトのエディターが開きます。ヘッダー類はデフォルトで用意されているもので、下の方にある「// Your code here...」の部分に、実際にやりたいことをjavascriptで記述していきます。

f:id:hisway306:20180314214430j:plain
 今回は「はてなブログ」の編集画面を開いた時に、既に書いた記事内容の中からimgタグのリンクがhttpで記述されている部分を見つけ、それをhttpsに書き換えるか、またはhttpを削除してRelative Reference形式にする、という作業を行うだけなので、こんな感じのシンプルなコードでできそうです。

f:id:hisway306:20180314214431j:plain
 書き終えたらTampermonkey 内のファイルメニューから保存をします。

f:id:hisway306:20180314214432j:plain
 ということで、ダッシュボードの戻ってみるとこうなりました。なお、このスクリーンショットでは2つのユーザースクリプトがありますが、今回作成したのは二つ目の方です。一つ目は上記で紹介したFlickrのembedコードから余分なコードを削除するため2年半前に作ったスクリプトです。

ユーザースクリプトの内容

 さて、スクリーンショットでちょっとだけお見せしましたが、以下に私がやっつけで作ったhttps化書き換えスクリプトのコードを貼っておきます。

/// ==UserScript==
// @name         Modify img tag link to Relative Reference on Hatena Blog Editor
// @namespace    http://blog.hisway306.jp/
// @version      0.1
// @description  To modify http link of img tag to Relative Reference on Hatena Blog Editor
// @author       hisway306
// @match        http://blog.hatena.ne.jp/hisway306/history.hatenablog.jp/edit*
// @grant        none
// ==/UserScript==

(function() {
    'use strict';
  var e = document.getElementById('body');
  var text = document.getElementById('body').value;
  var textA = text.replace(/img src\=\"http\:/g,'img src\=\"');
  e.value = textA;
}) ();

 ヘッダー部のコメント行は単なるコメントではなく実は重要なタグになっています。特に「@match」の行はこのスクリプトを実行するURLを指定するフィールドです。この例ではこの私のブログの編集画面のURLを指定しています。移植する場合はこの部分をご自分のアカウント、ブログの編集画面URLに書き換える必要があります。

 また「@name」の行はTampermonkey上からユーザースクリプトを識別するための名前として使われます。それ以外は適当でも良いのではないかと思っています。

 そしてスクリプトの本体はfunction()以下、"var e =”で始まってる行から"e.value ="までの4行だけです。ざっくり内容を説明すると...

  • まず1行目(var e...の部分)は、はてなブログの編集画面の入力フィールドであるテキストボックスからエレメント名を取得します。
  • 2行目でエレメントの中にあるテキスト(=本文)を取得します。
  • 3行目では取得した本文の中から「img src=http:"」という文字列を探し出し「img src="」に置き換えます。
  • その結果を最後にtextboxに書き戻します。

 見て分かるとおり、この例ではhttpをhttpsに置き換えるのではなく、Relative Reference形式に変換しています。httpsと明示したい場合は3行目をそのように書けばOKです。

 なお置換元に":"を含めるところは結構重要です。そうしないと"httpss”とか"//s"みたいな異常が起きる可能性がありますので、テストは十分に行ってください。

Flickr以外のimgタグにも全てに働くので注意!

 なお、このスクリプトはそのimgタグがFlickrを呼んでいるものかどうかに関わらず、httpで書かれたimgタグ全てを書き換えてしまいます。ですから、写真以外にimgタグが使われている場合は注意が必要です。

 しかし逆に言えば、ブログがSSL化された際にhttpで指定されたimgタグは中身がなんであれ動作しないので、そのまま残しておく意味はありません。なので、現状httpとなっているimgタグは、とりあえず全てRelative Referenceに書き換え、SSL化した際にもしFlickr以外から読み込んでいる画像で、そのホストがSSL配信出来すに表示されない場合があるなら、それはその時個別に対応を考えた方が良いと思います。

実行結果

 さて、一応実行結果を示しておきます。

 Tampermonkeyはアドオンとしてブラウザ起動時に同時にロードされています。12インチMacbook 2015でも特に動作が重くなるとか不安定になるみたいな弊害は体感しません。

f:id:hisway306:20180314224047j:plainf:id:hisway306:20180314225818j:plain
指定URLにアクセスしたときだけスクリプトが実行される
 左のGoogleのように関係ないサイトを開いているときは、今回作成したユーザースクリプトは実行されず、右のように「@match」で指定したブログの編集画面を開いたときだけ実行され、その状態はアドレスバー右端のアイコンで認識できるようになっています。

 そして、このスクリプトを用いて、FlickrがSSL化される前の2013年12月に書いた記事を編集モードで開いてみました。

f:id:hisway306:20180314214427j:plain
 まずはこちらがスクリプトを実行する前のをオリジナル。赤線を引いた部分で分かるとおり、imgタグはhttpリンクで写真データを呼び出しています。

f:id:hisway306:20180314214433j:plain
 こちらはスクリプト実行後。赤線部分で示したとおりimgタグのhttpが削除されRelative Reference形式に書き換わりました。

 便宜上Before / Afterを示しましたが、スクリプトは設定した編集画面を開いた瞬間に自動的に動作するので、開いたと思ったら既にAfterの状態になっているはずです。確認ダイアログなどは表示されず問答無用で動作しますので、注意が必要です。

 なお上記例で示した約4年前の記事がこちら。ページソースを見て頂けると分かりますが、imgタグはRelative Referenceとなっていて、画像もちゃんと表示されているはずです。

 現在はまだこのブログは非SSLですので、ブラウザ自体はhttpで呼び出していますが、SSL化した暁には混在コンテンツエラーになることなく、自動的にhttpsで画像が読み込まれるはずです。

2. アマゾン商品紹介リンクなどiframeタグ内を書き換える

 Flickr画像と同様にiframeタグ内のリンクがhttpで参照されている場合、やはり混在コンテンツ問題が起きるはずです。主にiframeを使っているのはAmazonの商品紹介リンク、Googleマップ、Youtubeあたりとなります。

 今回のSSL化騒動の発端となっているGoogleのサービスはさすがにかなり早い段階でhttps化されていますが、Amazonの対応はFlickrよりも遅く、比較的最近の記事(2016年頃半ば)でもhttpになっていたりします。

f:id:hisway306:20180315201122p:plain
 ちなみにiframeで貼られたAmazon商品紹介リンクというのは↑こんなやつです。はてなブログのサイドバーから貼ったものは該当しません(そちらはそちらで再更新などの作業が必要になる可能性あり)、

<iframe src="http://rcm-fe.amazon-adsystem.com/e/cm?t=hogehoge&o=9&p=8&l=as1&asins=B00FYHFLR6&ref=tf_til&fc1=000000&IS2=1&lt1=_blank&m=amazon&lc1=0000FF&bc1=000000&bg1=FFFFFF&f=ifr" style="width:120px;height:240px;" scrolling="no" marginwidth="0" marginheight="0" frameborder="0"></iframe>

 Amazon商品紹介リンクのコードは具体的にこんな感じです。imgタグ同様に"src=..."で参照先のURLが書かれていますが、これを上記Flickrの場合と同様にRelative Referenceに書き換えてしまいましょう。

やはりTampermonkeyでユーザースクリプト!

 その手段はやはりFlickrの場合と同様でユーザースクリプトを書きます。新たにもう一つユーザースクリプトを作っても良いのですが、今回は先ほどFlickr用に作成したスクリプトにもう一行追加することで、対応しようと思います。

 手順と考え方はimgタグの場合と同じなので色々省略して、完成品はこんな感じになりました。

/// ==UserScript==
// @name         Modify img tag link to Relative Reference on Hatena Blog Editor
// @namespace    http://blog.hisway306.jp/
// @version      0.1
// @description  To modify http link of img&iframe tag to Relative Reference on Hatena Blog Editor
// @author       hisway306
// @match        http://blog.hatena.ne.jp/hisway306/blog.hisway306.jp/edit*
// @grant        none
// ==/UserScript==

(function() {
    'use strict';
  var e = document.getElementById('body');
  var text = document.getElementById('body').value;
  var textA = text.replace(/img src\=\"http\:/g,'img src\=\"');
  var textB = textA.replace(/iframe src\=\"http\:/g,'iframe src\=\"');
  e.value = textB;
}) ();

 imgタグを置換する作業のあとに、同じようにiframeタグを置換する処理を一行追加しました(下から3行目)。imgタグを書き換えた後のtextAに対してiframeをさらに書き換え、その結果であるtextBを編集画面に書き戻しています。

結果はSSL化されてから要確認

 さて、これで大丈夫なはずですが、色々調べてみるとAmazon商品紹介のリンクは、iframeタグからhttpsで呼び出しても、それに付いてくる画像ファイルがhttpのままだったりする場合もあるようで、その場合はやはり正常に動作しなくなります。

 そうなったら新しくコードを取得し直して(現在取得できるコードは全てRelative Reference形式になっている)貼り直すか、あるいは商品リンク自体を消してしまうか考えたいと思います。

 Flickr画像と違ってAmazon商品紹介はなくても記事内容に影響はほとんどありませんから...。

1800近い記事の確認と更新が必要...

 ということで、以上が本ブログがSSL化されるまでにやらなくてはならない主な作業です。これ以外にフォトライフから貼った画像、編集サイドバーから貼ったAmazon商品リンク、主にSNSボタンで使用しているスクリプトなど、細かい見直し点もあります。

 いずれにしろ全部で1800近い記事があって、恐らくここ1年分くらいの記事はほぼ問題ないと思うのですが、それ以前の記事はひとつひとつ確認と更新が必要になりそうです。

 いくらかスクリプトで自動化したとは言え、編集画面を開いて更新ボタンを押す必要があるのでかなり手間と時間がかかるのは間違いありません。生真面目に全記事をひとつひとつやるよりは、ある程度のエラーが残留することは覚悟の上で、アクセス数の多い記事から順に処置していくのが効率よさそうです。

 独自ドメインブログのSSL化開始まではまだ数ヶ月かかりそうですが、後で慌てないようにコツコツと準備しておこうと思います。