tips

WPの外部画像URLをhttps対応

SSL対応時にどうしても混在コンテンツを回避できない場合に

WP+SSL化で検索すると、自作ブログのSSL化ばかりが話題になりますが、
実際のクライアントワークでは、SSL対応時にどうしても混在コンテンツを回避できないケースがままあります。
SSLやめるのは本末転倒ですし、外部画像のURLを変えてもらうように言えず、コピペしがちなケースが多い現場に細かい注意点を引き継いでいただくのは至難の技です。

そこで、外部画像URLをphpでイメージプロキシして、ちょっと強引に表示を実現します。
例えば、googleのロゴを非SSLで読み込むと以下のようなURLになります。

<img src="http://www.google.com/images/branding/googlelogo/2x/googlelogo_color_272x92dp.png" />

これをフィルターを通すと、こう加工されて出力されます。

<img src="https://web.contempo.jp/imageproxy?src=www.google.com%2Fimages%2Fbranding%2Fgooglelogo%2F2x%2Fgooglelogo_color_272x92dp.png&_wpnonce=8b7048f424" />

‘wp’フックでimageproxyというurlを読み込んだ場合にphpで画像を取得して吐き出すようにしています。
プロキシということで、第三者に利用されないようにwp_Nonce でチェックする工程を入れています。HTTP_REFERERで判定する方がスッキリしたURLでいけますが、セキュリティの都合等もあるでしょうから、その辺はお好みで。
フック先は画像を貼り付けてそうなメインエディタ、コメント、ウィジェットの三つのテキストに引っ掛けてあります。

if ( $_SERVER['HTTPS'] == 'on' ){

add_filter( 'the_content', 'change_image_src_for_proxy', 99 );
add_filter( 'comment_text', 'change_image_src_for_proxy', 99 );
add_filter( 'widget_text', 'change_image_src_for_proxy', 99 );
function change_image_src_for_proxy( $content ){
preg_match_all('/<img[^>]*src=[\'"]http:\/\/(.*?)[\'"][^>]*>/i', $content, $matches, PREG_SET_ORDER);
foreach ($matches as $match):
$homeurl = str_replace( 'https://', '', home_url() );
if ( stripos( $match[2], $homeurl ) === 0 ){
$img = str_replace( 'http://', 'https://', $match[0] );
} else {
$img = str_replace( 'http://'.$match[1], wp_nonce_url( home_url('imageproxy').'?src='.$match[1], 'imageproxy' ), $match[0] );
}
$content = str_replace( $match[0], $img, $content );
endforeach;
return $content;
}

add_filter('wp', function () {
global $wp;

if ( $wp->request !== "imageproxy" || empty( $_GET['src'] ) ) return;
if ( !wp_verify_nonce( $_REQUEST['_wpnonce'], 'imageproxy' ) ) exit;
$context = stream_context_create( array( 'http' => array('ignore_errors' => true, 'timeout' => 5, ) ) );
$response = file_get_contents( 'http://'.$_GET['src'], false, $context);
if( $response ){
if ( preg_match( '/.*?\.(jpeg|jpg|gif|svg|png|bmp)/i', $_GET['src'], $ext ) ) {
$ext = 'Content-type: image/'.str_replace( 'jpg', 'jpeg', mb_strtolower($ext[1]) );
header( $ext );
}
echo $response;
}
exit;
});

}