ホームページ制作(技術情報)不安定と言われているWordPressのコンテンツ埋め込み(oEmbed)についてのメモ12月16日にWordPress5がリリースされ、新エディタ「Gutenberg」となりましたが、まだ未成熟な部分もあって嫌だ、または、いままでのエディタ感覚のまま使い方をしたいなど色々な理由で、Classicエディタ「TinyMCE」を継続して利用しておられる方も多いと思います。下記、Classicエディタ「TinyMCE」利用を前提としてのメモになります。(「おーえんぶど」と読むそうです)に対応していれば、埋め込み用のコードが差し込まれます。これが差し込まれない場合もあって、また、TinyMCE上では差し込まれてないけど、公開ページでは差し込まれてたり、ネットで言われているとおり不安定な動きを確認しつつ、筆者も放置していました。この度、この奇っ怪な動きを調べる機会があったので、そのメモをご紹介します。自分のホームページから、同じWebサーバに共存するバーチャルドメインのホームページへのoEmbedが動作しない原因のひとつ。WordPressで構築したホームページをインターネット上に公開する場合、上記のようなネットワーク構成のパターンがあると思います。インターネット層(external-zone)とWebサーバ層の(internal-zone)の間に、ファイアウォールを挟み、internal-zoneのWebサーバにはIPv4のプライベートIPアドレスを割り振るパターンです。このパターンでは、external-zoneからinternal-zoneに流れるIPv4のIPパケットはファイアウォールでNAT変換しています。internal-zoneのWebサーバからexternal-zoneのグローバルIPアドレスが付与されているインターフェースにアクセスに対応できないファイアウォールが存在します。これは、internal-zoneからexternal-zoneにバインドされたパケットはNAT変換対象外としているファイアウォールの仕様によるものですが、その場合、自分のWebサーバから自分のWebサーバのexternal-zoneのグローバルIPアドレスには、アクセスできないという状況になってしまいます。これによって、oEmbedの埋め込み用のコード取得に失敗し、結果、埋め込みされない結果になってしまいます。通常、このパターンのネットワーク構成では、内部DNSやHOSTSファイルなどを利用して、自分のWebサーバから自分のWebサーバにアクセスする際の名前解決はプライベートIPアドレスで行えるようにしますが、それでも、結果、oEmbedの埋め込み用のコード取得に失敗し、結果、埋め込みされない結果になってしまいます。その理由は、oEmbedの埋め込み用のコード取得は、wp-includes/class-wp-embed.php内のshortcodeメソッドで、wp_oembed_get関数で取得しています。このwp_oembed_get関数がHTTP通信でHTMLを取得する際に「reject_unsafe_urls」が真(true)とされ、オブジェクトWP_Httpのrequestメソッドで取得しています。「reject_unsafe_urls」が真(true)の場合、wp_http_validate_url関数にてURLを厳密にチェックしているのですが、そのチェックの一つに、バリデイト対象のURL内のホスト名を名前引きして、それが、プライベートIPアドレスだったらNGとしています。false;}}}幸いにも、上記のとおり、「http_request_host_is_external」というフィルターがあるので、$hostが自分のホームページのWebサーバに共存するホームページURLだったら真(true)を返してあげればこのケースの現象は直りますが、重要なセキュリティの要のフィルターのひとつなので、注意が必要です。自分のホームページで、自分のホームページへのoEmbedの場合は、wp_oembed_get関数から呼び出しているWP_oEmbedのget_htmlメソッドで、HTTP通信せずに、「pre_oembed_result」フィルターにapply_filtersされているwp_filter_pre_oembed_result関数で、url_to_postid関数などを使って、埋め込みコードを取得しています。アクセス制御・BASIC認証などoEmbedが動作しないの原因のひとつに、「原因その1:自分のネットワーク構成」でも触れましたが、HTTP通信で埋め込むコードを取得しにいってるので、その先がアクセス制御やBASIC認証などの制限でHTTPアクセスができない状況である場合は、埋め込みできないということになります。ポイントは、手持ちのブラウザから対象先のURLにHTTP通信できるかということではなく、Webサーバから対象先のURLにHTTP通信できるかというところです。SSL/TLSSSL/TLSが原因で、oEmbedが動作したりしなかったりするケースがあります。これは、Classicエディタ「TinyMCE」側でURLを検知し、それをJavaScriptから/wp-admin/admin-ajax.phpに、oEmbedの埋め込むコードを取得する命令を伝えているのですが、その命令をadmin-ajax.phpで受け取って、/wp-admin/includes/ajax-actions.phpのwp_ajax_parse_embed関数が動いています。そのwp_ajax_parse_embed内に下記のコードがあります。);}ここでの注釈(コメント)のとおり、こちらがSSL/TLSなのに、いまから埋め込もうとしているiframeのコードが非SSL/TLSだった場合、埋め込みをブロックします。当たり前のことですが、確かに、SSL/TLSなページ内で非SSL/TLSの部品は表示できませんからね。まとめますとこのパターンでoEmbedが動作しないケースは下記のような感じになると思います。(このケースの場合は、管理画面のTinyMCEではoEmbedは動作しませんが、一般公開のページでは動作します)。自分のホームページが完全SSL/TLS化しているけど、oEmbedの先が非SSL/TLSのケース。以上ですが、不安定と言われているWordPressのコンテンツ埋め込み(oEmbed)。キャッシュについてoEmbedはHTTP通信で埋め込むコードを取得していますが、ボトルネックが激しいので、WordPressでは、その記事毎にpost_meta形式でキャッシュ保存しています。具体的には、/wp-includes/class-wp-embed.phpのWP_Embedオブジェクトのshortcodeメソッドです。{上記のように、このキャッシュのTTLは「DAY_IN_SECONDS」つまり1日ですので、開発中に誤ったoEmbedの埋め込みコードを取得した場合、1日はキャッシュが効いて変わりません。このキャッシュを削除するには、下記のようなSQL文で強制的に削除することもできます。'_oembed_%';wp_の部分はPrefixですので、WPインストールの際に指定したものをご利用ください。SQL文の操作になりますので、WordPressが壊れないように、事前にバックアップや入念にチェックした上で行うようにしてください。update後vsftpdにログインできなくなった沖縄を拠点とし、お客様のご予算と目的に応じたホームページ制作(WordPress)・ラジオCM/番組制作など、各種メディアでの情報配信のお手伝いをしております。お見積りのご依頼はもちろん、事前のご相談も承ります。ご気軽にご連絡ください。