はじめに
mod_mruby
を動かせる環境が作れたのでユーザーエージェントを判断してアクセス先を振り分けてみる
参考
- Apacheのmod_rewriteをmod_mrubyによって無くす事ができるか
- Apacheによるバーチャルホスト構築レシピ mod_mruby編
- mruby から正規表現が消え、正規表現がやってきた。
- masamitsu-murase / mruby-hs-regexp
SmartPhone とそれ以外のアクセスを分けたい
mod_rewrite を使う場合
以前に取り上げたが mod_rewrite を使って SmartPhone からのアクセスとそれ以外のアクセスを分ける場合には以下のように書ける。
SetEnvIf User-Agent "iPhone" UA=smartphone-apple SetEnvIf User-Agent "iPod" UA=smartphone-apple SetEnvIf User-Agent "iPad" UA=smartphone-apple SetEnvIf User-Agent "Android" UA=smartphone-google RewriteCond %{ENV:UA} ^smartphone-apple$ RewriteRule ^/(path/to)(.*$) http://iPhoneのあれや/これや/$2 [R,L] RewriteCond %{ENV:UA} ^smartphone-google$ RewriteRule ^/(path/to)(.*$) http://Androidのあれや/これや/$2 [R,L] RewriteCond %{ENV:UA} !^smartphone*$ RewriteRule ^/(path/to)(.*$) http://それ以外のあれや/これや/$2 [R,L]
その他にも書き方があるが SetEnvIf
を使うのが最近の個人的な好み(他の書き方と差異があるのかは未検証)。ユーザーエージェントを判断してグルーピングして RewriteCond
とマッチさせて RewriteRule
で振り分けるって感じかな。
mod_mruby での実装
ここからが本題。mod_mruby
でユーザーエージェントを判断してリライトする場合には以下のように書いてみた。上記の内容を完全に実現するには引き続き調べなければいけないけどとりあえず。
# hi = Apache::Request.new.headers_in agent = hi["User-Agent"] # def go_redirect(redirect_path) r = Apache::Request.new() s = Apache::Server.new() r.filename = s.document_root + redirect_path Apache.return(Apache::OK) end # if agent.include?("Mac") then go_redirect("/iphone.html") elsif agent.include?("Android") then go_redirect("/android.html") else Apache.return(Apache::DECLINED) end
ユーザーエージェントは Apache::Request.new.headers_in
にハッシュで格納されているのでキー(User-Agent
)を指定して取り出すことが出来た。但し、ここからがちょっと悩んだ...
if /iPhone|iPad|iPod/ =~ agent redirect_path = "/iphone.html" r.filename = s.document_root + redirect_path
上記のように取得したユーザーエージェントが格納されている変数内に iPhone
と iPad
さらに iPhone
の何れかが含まれている場合にはという書き方が出来れば嬉しかったのだが、今回は下記のようなエラーが出てしまい動かすことが出来なかった。
[Fri Feb 28 20:34:04 2014] [error] mod_mruby ERROR ap_mrb_raise_error: mrb_run failed: [TYPE: FILE] [CACHED: DISABLE] mruby raise: /etc/apache2/rewrite.rb:5: '%s' is an invalid regular expression because %s. (ArgumentError)
mod_mruby
をコンパイルする際の build_config.rb
内に以下のように mruby-hs-regexp という正規表現を扱う為の mrbgems
も一緒にビルドされるように書かれているようなので動作するはずなのだが...
conf.gem :git => 'git://github.com/masamitsu-murase/mruby-hs-regexp.git'
上記についてはインストール時の自分の手違いである可能性も高い為、もう少し調べて issue で質問出来たらと考えている。
とりあえずデモ
mruby を実行するタイミングを指定
/etc/apache2/mods-enables/
以下に mruby.conf
というファイル名で mruby
を実行するタイミング(Hook Function
)を定義する。
mrubyTranslateNameMiddle /etc/apache2/hooks/rewrite.rb
振り分けの mruby スクリプトを設置
上記で指定したパス(/etc/apache2/hooks/rewrite.rb
)にスクリプトを設置する。設置したら念の為 apache
を再起動する。再起動後、スクリプトの修正を行った場合には再起動は不要なようだ。
テスト用の HTML ファイルの設置
ドキュメントルート以下に以下のようなファイルを設置する。
# tree /var/www /var/www |-- android.html # ユーザーエージェントが Android の場合に表示される HTML |-- index.html # ユーザーエージェントが iPhone 等場合に表示される HTML `-- iphone.html # 上記以外のユーザーエージェントの場合 0 directories, 3 files
各 HTML
ファイルには以下のようにユーザーエージェントを表示する Javascript
も埋め込んでおく。
<SCRIPT Language="JavaScript"> <!-- document.write(navigator.userAgent); // --> </SCRIPT>
iPhone のユーザーエージェントでアクセスしてみる
iPhone
以外にも iPod
や iPad
もアクセスされることを想定してユーザーエージェントを判断する文字列として「Mac
」を指定。*1
Android のユーザーエージェントでアクセスしてみる
上記以外のユーザーエージェントでアクセスしてみる
現時点で条件の指定に正規表現を利用出来ないのがちょっと辛いが上記のように振り分けを行うことが出来た。
最後に
mod_mruby
を使ってお手軽もユーザーエージェントを判断して振り分けの設定を行うことが出来た- 振り分けの条件が複雑になるにつれて通常の
mod_rewrite
よりも可読性が良くなるのが個人的にはお気に入り - 但し、検証した環境では正規表現での条件判定が出来なかったので引き続き調査したい
- これらの環境がとりあえず試せるであろう Dockerfile も作ってアップした
*1:MacBook Pro とかはどうすんねん...ということがあるので引き続き検討...