CFでカスタムオリジンをApacheに向けている時のディレクトリ名スラッシュ補完時にオリジンのURLに転送されてしまう問題を解決してみた
長い...。つまり、オリジンサーバ
http://origin.example.com
に対して、CFのDistoributionを
http://cached.example.com
みたいに設定していたとして、
http://cached.example.com/sub
みたいなディレクトリ名に/を付けずにアクセスした際に、ブラウザのURLが
http://origin.example.com/sub/
となってしまう問題を解決する設定を考えてみました。
原因
まず、なぜ起こるのかを考えて見ましょう。
$ curl -v http://cached.example.com/sub * About to connect() to cached.example.com port 80 (#0) * Trying 216.137.53.30... connected * Connected to cached.example.com (216.137.53.30) port 80 (#0) > GET /sub HTTP/1.1 > User-Agent: curl/7.19.7 (i686-pc-linux-gnu) libcurl/7.19.7 NSS/3.12.6.2 zlib/1.2.3 libidn/1.18 libssh2/1.2.2 > Host: cached.example.com > Accept: */* > * HTTP 1.0, assume close after body < HTTP/1.0 301 Moved Permanently < Date: Wed, 25 Apr 2012 17:14:37 GMT < Server: Apache/2.2.22 (Amazon) < Location: http://origin.example.com/sub/ < Content-Length: 233 < Content-Type: text/html; charset=iso-8859-1 < Age: 825 < X-Cache: Hit from cloudfront < X-Amz-Cf-Id: LdWjKWqdaIuOwWgHQ86B8tvef8Vmofv-TqXtEaggtVRKPjcvzSyMWg==,qRrOXfbgF6Sic5Z27w99TKqTyFi24Ibq5Ptz2Uk1XYQjqHarGzapzQ== < Via: 1.0 afc2ff739d4cc96648fcd7eae0aa3c71.cloudfront.net (CloudFront) < Connection: close < <!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN"> <html><head> <title>301 Moved Permanently</title> </head><body> <h1>Moved Permanently</h1> <p>The document has moved <a href="http://origin.example.com/sub/">here</a>.</p> </body></html> * Closing connection #0
はい、思いっきり、"Location: http://origin.example.com/sub/" と言われています。CFは素直に受け取ったままブラウザに渡します。
ブラウザは言われたとおりに http://origin.example.com/sub/ に移動するので、
あー、オリジンサーバのURLが出ちゃってますね。
やってみる
RewriteEngine on RewriteCond %{HTTP_USER_AGENT} ^Amazon\ CloudFront$ RewriteRule ^/([^\.])+[^/]$ http://cached.example.com%{REQUEST_URI}/ [R=301]
- まずUAをチェックして、CFのクライアントである場合に
- パスの中にドットが含まれない(≒拡張子がないのでファイルではない可能性が高い)、かつ終わりがスラッシュ以外の文字である
場合にキャッシュ用URLの当該ディレクトリへ/付きでリダイレクトします。
$ curl -v http://cached.example.com/sub * About to connect() to cached.example.com port 80 (#0) * Trying 216.137.53.96... connected * Connected to cached.example.com (216.137.53.96) port 80 (#0) > GET /sub9 HTTP/1.1 > User-Agent: curl/7.19.7 (i686-pc-linux-gnu) libcurl/7.19.7 NSS/3.12.6.2 zlib/1.2.3 libidn/1.18 libssh2/1.2.2 > Host: cached.example.com > Accept: */* > * HTTP 1.0, assume close after body < HTTP/1.0 301 Moved Permanently < Date: Wed, 25 Apr 2012 17:37:11 GMT < Server: Apache/2.2.22 (Amazon) < Location: http://cached.example.com/sub/ < Content-Length: 233 < Content-Type: text/html; charset=iso-8859-1 < X-Cache: Miss from cloudfront < X-Amz-Cf-Id: 75yDzxwfUh5C7Q3ELXyqWfXrSSMaWSxufnJps3RZDjy5_fl7F2J8xw==,J7xP0VptHjSq3_GFYTIIZ29PyXrlqGOh_zlhKrbYDIl3ffAvvbZ14w==,UagMrvsy7JXwBR5vNXPcZkpMiH5Px6XjxEWqTejV23S7HZqe5qeHFg== < Via: 1.0 8362ec81036ea7c5f40b353d26ad89cb.cloudfront.net (CloudFront) < Connection: close < <!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN"> <html><head> <title>301 Moved Permanently</title> </head><body> <h1>Moved Permanently</h1> <p>The document has moved <a href="http://cached.example.com/sub/">here</a>.</p> </body></html> * Closing connection #0
お、今度はちゃんと "Location: http://cached.example.com/sub/" となっているので、大丈夫そうですね。
ブラウザで http://cached.example.com/sub にアクセスしてみます。
FQDNはcached.example.comのまま、subの後ろに/が付きました!
しかも、UAをちゃんとチェックしているため、オリジンにダイレクトにブラウザでアクセスした場合には、
と、ちゃんとオリジン側のディレクトリ名に/を付けたURLに移動します。
コンテンツ制作時やアップロード確認時などにキャッシュURLへ飛ばされたりしません。
これって
CDPの種になりませんかね?(チラッ
Smart Custom Originパターンとか?