CloudFrontでドメインルートをS3にして、サブディレクトリをWordPressにした場合の注意点と解決策

2015.11.02

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

CloudFrontでドメインルートをS3にして、サブディレクトリをWordPressにした場合の注意点と解決策

ハロウィンは家にこもってゆるゆりを見ていました森永です。

今回はタイトルをどうしようかすごく迷いましたが、困っている方がいらっしゃると思うのでド直球なタイトルにしてみました。

問題の構成

今回の問題の前提は以下の通りです。

  • CDNにCloudFrontを使用してリバースプロキシとしている
  • ドメインルートexample.comはS3に向ける
  • example.com/blog/*はWordPressを構築したEC2に向ける(ELBを挟んだ場合も同様)
    • WordPress側でblogというスラッグを作成している

S3+WordPress

CloudFrontの設定はこんな感じです。
S3とEC2(もしくはELB)をOrigin登録して、Behaviorで振り分けます。

AWS_CloudFront_Management_Console

想定としては、コーポレートブログをS3に置いていて、後になってブログを開設したくなったのでWordPressを使おう!といったものが考えられます。
結構ありそうな状況ですよね。

問題点

見る側からすると問題はありません。(もし何かあればコメントで教えて下さい。)
記事を編集する側がある操作をした際に大きな問題が発生します。

それは、未公開の記事をプレビューしたい時です。
こいつの原因は明確です。プレビューのURLにサブディレクトリが含まれないからです。

example.comの例で行くと、WordPressの公開記事はhttp://example.com/blog/hogehogeといったURLとなります。
これだとCloudFrontでちゃんとWordPress側に振り分けられます。

ところが、未公開記事をプレビューするとhttp://example.com/?p=番号&preview=trueというURLになってしまいます。
/blogどこ行った!!

こいつの厄介なところは、ドメインルートのあとにすぐクエリストリングが来ている点です。
CloudFrontではクエリストリングによるBehavior設定は出来ないので、preview=trueなどで振り分けられないのです。

解決策

サブディレクトリではなくサブドメインにしましょう!!!!

と言いたいのですが、そうも行かないこともありますよね。。。
出来るのであればサブドメイン形式blog.example.comをオススメします。

気を取り直して、サブディレクトリ形式での解決方法。
プレビューのURLが問題になっているので、プレビューのURLを書き換えちゃいましょう!

簡単に言うなと思われるかもしれませんが、WordPressにはfunction.phpというファイルがあり、そこにコードを書けばWordPressの機能をHookできるのです。
こいつを使う方針で行きます。
(.htaccessでRewriteする手も考えたのですが、最初にS3に見に行ってしまうのでそもそものURLを変えないと無理でした…)

以下のコードをwp-content/themes/function.phpに追記します。

/*プレビューのURL修正*/
function my_update_post_link($link) {
        $post_type_rewrite = get_post_type_object(get_post_type())->rewrite;

        $link = preg_replace('/\?/', $post_type_rewrite['slug'].'/?', $link);
        return $link;
}
add_filter('preview_post_link', 'my_update_post_link');

function my_post_updated_messages($messages){
        $post_type_rewrite = get_post_type_object(get_post_type())->rewrite;

        $messages['post'][8] = preg_replace('/\?/', $post_type_rewrite['slug'].'/?', $messages['post'][8]);
        $messages['post'][9] = preg_replace('/\?/', $post_type_rewrite['slug'].'/?', $messages['post'][9]);
        $messages['post'][10] = preg_replace('/\?/', $post_type_rewrite['slug'].'/?', $messages['post'][10]);
        return $messages;
}
add_filter('post_updated_messages', 'my_post_updated_messages');

上記でやっていることを簡単に言うと、プレビューのURLの?スラッグ/?に書き換えているだけです。
今回はblogというスラッグを作成しているので、?blog/?に書き換えられて見事CloudFrontで振り分けできるURLとなるわけです。

最後に

結構前にやったときに起きた問題だったんですが、最近になって同僚に質問されたので備忘としてまとめてみました。
こういうTips結構重要なんですよね…(再現しても次やった時忘れている問題)

他に今回の構成で問題になるところがあればコメント頂けると幸いです。