さくらサーバ+SSL(https)で別ページからアンカーリンクが使えない

WordPress上で、別ページへアンカーリンク(ページの途中へリンク)をしたいのに、ページ遷移した後、一瞬アンカー位置へ移動したと思ったらページトップへ戻されてしまう、という症状。

この症状が確認できたのは、さくらインターネットのレンタルサーバだけで、他のサーバではこの症状は今のところ確認できない。また、同じさくらサーバを使っていても、この症状が出ないサイトもある。

ネットで解決法を探しても、ずばりこれ!といった解決法が無く、途方に暮れていました。

とりあえず、妥協案ということで解決できたので、今後のためにもメモメモ。

この症状が出るのは、

  • さくらサーバ
  • https(SSL)使用
  • 別ページへのアンカーリンク

という条件。ここでひっかかってくるのが、SSLとアンカーリンク。さくらサーバの仕様を確認すると、以下の記述があります。

「さくらのレンタルサーバ」にて提供しているウェブサーバ(Apache)は、80番ポートを使用するものと、443番ポートを使用するものとの2種類に分けられます。
一般的に、80番ポートは「http://」、443番ポートは「https://」という形式でアクセスされ、「https://」についてはプロクシとして動作します。
そのため、同じディレクトリへのアクセスであっても、その際に呼び出されるウェブサーバが異なると、CGIプログラムやウェブサーバが.htaccessなどのファイルを読み込む際、挙動に違いが生じます。

つまり、さくらサーバでは、サーバ側で自動的にhttpからhttpsへリダイレクトをかけているということになります。



そこで、PHP側でリクエスト情報やサーバ情報などを表示させてみたところ、アンカーをつけてリクエストしているのに、表示されたページではアンカーだけがそっくり消えていることがわかりました。

例えば「https://○○○/edit.php#form」というリンクを貼っておいても、実際にedit.phpへ遷移したときには「#form」という部分がリクエストから消えてしまっている、ということです。ただし、ブラウザのURL欄には「#form」という部分が表示されたままで。

これを、さくらサーバの仕様のとおりに、大ざっぱに処理の順番で書いていくと、

  1. サーバ側へ「https://○○○/edit.php#form」がリクエストされる
  2. サーバ側は、まず80番ポートで「https://○○○/edit.php#form」を受け取る
  3. リクエストがhttpsなので、443番ポート用のサーバに転送される
  4. 443番ポート用のサーバが、転送されてきたリクエストのページをX-SAKURA-FORWARDED-FORに設定されているIP宛に返す
  5. クライアント側に、httpsでページが表示される

という流れになり、おそらく3番目の「443番ポート用サーバに転送」するときに、アンカーが消えてしまっているようです。

ただ、ブラウザをよーく見ていると、一瞬だけスクロールバーの位置がアンカーのある位置に移動しているので、リクエストが443番ポート用のサーバに渡る前に、一瞬だけ80番ポートのサーバからレスポンスは返ってきているような気がする。


この症状は、さくらサーバ+Wordpressで必ず出るものではないようで、この症状が出たサイトとは別に管理しているサイトでは再現しませんでした。もちろん、さくらサーバ以外のサーバでWordpressを使っているサイトでも再現せず。

ということで、おそらくさくらサーバ+Wordpress+なにか、が原因で起きる症状なのかもしれません。とりあえず、jQueryのanimate()(スムーズスクロール等に使う関数)は関係ありませんでした。



ゆっくりと時間をかけて調べている余裕はないので、とりあえず解決法。

アンカーは消えてしまうけど、クエリ文字列はそのまま転送されるようなので、アンカーをクエリ文字列で渡せばOK。簡単な話、「#」を「?」にするだけです。もしくは、「anchor=○○○」のようにしてもいいですね。

クエリ文字列で渡された文字列を使って、PHPやjQueryでアンカー位置まで移動する処理をページロード後に行えば、擬似的にアンカーリンクが完成します。その辺の処理は難しくないので省略。


ちょっと面倒なやり方ですが、この方法を使えばサーバを引っ越した後でも問題なく使えますので、お試しあれ。


初稿:2019年1月18日