_ もちろん apache 2.4、mod_lua が必要。さらに、mod_proxy と mod_proxy_http も。ProxyPass の設定は lua で置き替えるけど、よそにアクセスしにいく動作そのものは mod_proxy* がおこなうのでこいつらが不要になるわけではない。
なーんにも考えずに、うしろにただリクエストをまわすだけ。この程度なら素直に ProxyPass を使った方がずっとマシ。複雑な条件によってプロクシしたりしなかったりを制御しようとすると lua のうまみが出てくる。たとえば、上の例を-- httpd.conf LuaHookTranslateName /path/to/proxy.lua reverse_proxy -- proxy.lua backend = "http://127.0.0.1:8080" function reverse_proxy(r) r.handler = "proxy-server" r.proxyreq = apache2.PROXYREQ_REVERSE r.filename = "proxy:" .. backend .. r.uri return(apache2.OK) endのように修正すると、複数のバックエンドに対してリクエストをランダムに振り分けるようなことが mod_proxy_balancer なしで実現できる。もちろん、関数をてきとーに書き換えればランダム以外の方法で振り分けることもできる。backend = { "http://...", "http://...", ... } function backend_random(be) return(be[math.random(#be)]) end backend_selector = backend_random function reverse_proxy(r) r.handler = "proxy-server" r.proxyreq = apache2.PROXYREQ_REVERSE r.filename = "proxy:" .. backend_selector(backend) .. r.uri return(apache2.OK) end_ その他、以前 mod_lua をいじったときの記録。開発版の 2.3 で mod_lua をあそんでみた 例。2.4 で仕様が変わった DefaultType の挙動を mod_lua でエミュレートする 例。
_ ほんとはこんなことしてあそんでる余裕はないはずなんだが。こういうときほど現実から逃げたくなるのが世の常。だって叩いても叩いてもバグが減らないんだもん…。
_ mod_mime の AddType とか AddCharset とかでやっていることを mod_lua にやらせてみるテスト。AddHogehoge と DefaultHogehoge 系の機能はほぼ実装してるけど、RemoveHogehoge は不可。hoge.html.utf-8 みたいな二重拡張子は可。DefaultType は実は mod_mime ではなく core の機能のため実装していない( こちらをどうぞ)。
-- httpd.conf LuaHookTypeChecker /path/to/mod_mime.lua emulate_mod_mime # その他 mod_mime をロードしないようにして、かつ関連ディレクティブ全削除 -- mod_mime.lua mime_types = { -- AddType ["html"] = "text/html", ["htm"] = "text/html", ["shtml"] = "text/html", ["txt"] = "text/plain", ["jpg"] = "image/jpeg", ["gif"] = "image/gif", ["png"] = "image/png", default = "text/plain" -- DefaultType } charset = { -- AddCharset ["euc"] = "EUC-JP", ["jis"] = "ISO-2022-JP", ["sjis"] = "SHIT_JIS", ["utf-8"] = "UTF-8", ["iso8859-1"] = "ISO-8859-1", -- default = "iso-8859-1" -- AddDefaultCharset } language = { -- AddLanguage ["ja"] = "ja", ["en"] = "en", -- default = "en" -- DefaultLanguage } encoding = { -- AddEncoding ["gz"] = "x-gzip", ["tgz"] = "x-gzip", ["z"] = "x-compress", } handler = { -- AddHandler ["lua"] = "lua-script", ["cgi"] = "cgi-script", ["var"] = "type-map", ["asis"] = "send-as-is", } filter = { -- AddOutputFilter ["shtml"] = "INCLUDES", } function emulate_mod_mime(r) local lang = language.default local cs = charset.default for suffix in r.filename:lower():gmatch"%.([%w_-]+)" do if mime_types[suffix] then r.content_type = mime_types[suffix] elseif language[suffix] then lang = language[suffix] elseif charset[suffix] then cs = charset[suffix] elseif encoding[suffix] then r.headers_out["Content-Encoding"] = encoding[suffix] elseif handler[suffix] then r.handler = handler[suffix] end --[[ if filter[suffix] then r:add_output_filter(filter[suffix]) end ]] end if r.content_type and r.content_type:lower():sub(1,5) == "text/" then if lang then r.headers_out["Content-Language"] = lang end if cs and not r.content_type:lower():match"charset=" then r.content_type = r.content_type .. "; charset=" .. cs end end end_ ドキュメントには r:addoutputfilter() というメソッドがあるように書いてますが、嘘です。正しくは r:add_output_filter() で、だけど使ってもフィルタかからない上、たまにせぐふぉで死にます。なので上ではコメントアウトしてます。使いかた間違ってないよねぇ? ほかにもドキュメントの嘘はたくさんあって、
とか。まあ、そういうわけで mod_lua はまだまだ実用レベルにはほど遠いので、遊ぶにはいいけどマジメな用途に使おうなんて思ってはいけない。
- LuaMapHandler が使えない。 2.3 では使えていたんだが 2.4 のソースからは消えている。
- r:parsebody() が使えない。これは 2.3 のときから使えなかった。
- r:escape_url() とか r:construct_url() とかの undocumented なメソッドがいくつか。