mrubyも少しずつ知られてきていて、WindowsやLinux、MacOSX等マルチプラットフォームで色々遊んでいる人が多いことでしょう。そうなってくると、しばらく弄ってみた後はやっぱりマルチプラットフォームで同じようにHTTPで通信してみたいと思いませんか?
例えば、
- mrubyでHTTPのGETとかPOSTとかしてみたり
- mrubyを組み込んだデバイスからTwitterに呟いてみたり
- 各種デバイスからZabbixをつついてみたり
- エアコンを監視してるRaspberry PiからGrowthForecastにデータを送ってグラフ化してみたり
- 組み込みデバイスや低レイヤーなソフトウェアからfluentdにデータを送って解析してみたり
ということで、今回はそういうことをするためにはmruby側でどういう準備をして、どう実装すればいいかの導入部分を説明したいと思います。
HTTP関連のmrbgemsを導入
mrubyは基本的に全ての機能をスタティックにリンクするので、まずは以下のようなHTTPで色々遊ぶためのmrbgemsをリンクする設定をbuild_config.rbに書きましょう。
[program lang=’ruby’ escaped=’true’]
MRuby::Build.new do ¦conf¦ toolchain :gcc conf.gembox 'default' conf.gem :git => 'https://github.com/iij/mruby-pack.git' conf.gem :git => 'https://github.com/iij/mruby-digest.git' conf.gem :git => 'https://github.com/mattn/mruby-json.git' conf.gem :git => 'https://github.com/mattn/mruby-uv.git' conf.gem :git => 'https://github.com/mattn/mruby-http.git' conf.gem :git => 'https://github.com/matsumoto-r/mruby-simplehttp.git' conf.gem :git => 'https://github.com/matsumoto-r/mruby-httprequest.git' conf.gem :git => 'https://github.com/matsumoto-r/mruby-oauth.git' conf.gem :git => 'https://github.com/matsumoto-r/mruby-sleep.git' conf.gem :git => 'https://github.com/matsumoto-r/mruby-zabbix.git' conf.gem :git => 'https://github.com/matsumoto-r/mruby-growthforecast.git' conf.gem :git => 'https://github.com/y-ken/fluent-logger-mruby' end
[/program]
続いて、マルチプラットフォームでのTCP通信の核となるlibuvが必要になりますので、これをgithubからダウンロードして最新のものをビルドしておきましょう。最近のgithubのlibuvはconfigureスクリプトも用意されてきているので、./configure make make installで基本的にOKなはずです。
そして、上記のようにlibuvをインストール後、build_config.rbにmrbgemの設定を記述した状態で、rakeあるいはmakeすればビルドが完了するはずです。
HTTP通信を色々してみる
では早速、rakeによって生成されたバイナリbin/mrubyを使って、HTTP通信してみましょう。上記のmrbgemを組み込んだmrubyバイナリやlibmruby.aをリンクさせたバイナリは、以下のようなRubyコードを実行することができます。
例えば、任意のURLに対して、普通にGETしたりPOSTするには以下のように書きましょう。
- GETする場合
[program lang=’ruby’ escaped=’true’]
h = HttpRequest.new() p h.get("https://blog.matsumoto-r.jp/")
[/program]
これでHTTPのGETができてしまいます。
[program lang=’bash’ escaped=’true’]
./bin/mruby get.rb
[/program]
で実行してやると良いでしょう。以下、同様に./bin/mrubyで実行できます。
- POSTする場合
[program lang=’ruby’ escaped=’true’]
h = HttpRequest.new() h.post("http://127.0.0.1:5125/http/master/access", { :number => 7, :color => "#333399", :mode => "count", },{ 'User-Agent' => "mruby-growthforecast", })
[/program]
とかしてやれば、HTTPのPOSTができます。
Twitterに呟いたりTL眺めたりしてみる
次にTwitterに呟いてみたいときは、以下のように書くと良いでしょう。
[program lang=’ruby’ escaped=’true’]
CONSUMER_KEY = '' CONSUMER_SECRET = '' ACCESS_TOKEN = '' ACCESS_TOKEN_SECRET = '' API_URL = 'http://api.twitter.com/1.1/statuses/update.json' tweet = "happy new year from mruby-oauth" ex_headers = {'Content-Type' => 'application/x-www-form-urlencoded'} twitter = OAuth.new(CONSUMER_KEY, CONSUMER_SECRET, ACCESS_TOKEN, ACCESS_TOKEN_SECRET) response = twitter.post(API_URL, {:status => tweet}, ex_headers) if response.code.to_i == 200 puts "tweet success: #{tweet}" else puts "tweet failed: #{tweet}: bellow response" p response end
[/program]
これて、ツイートできるはずです。
単純にストリームAPIを使わずにタイムラインをmrubyで眺める場合など、以下のように書くと良いでしょう。
[program lang=’actionscript3′ escaped=’true’]
CONSUMER_KEY = "" CONSUMER_SECRET = "" ACCESS_TOKEN = "" ACCESS_TOKEN_SECRET = "" GET_API_URL = 'http://api.twitter.com/1.1/statuses/home_timeline.json?count=' tweet_num = 10 interval = 60 twitter = OAuth.new(CONSUMER_KEY, CONSUMER_SECRET, ACCESS_TOKEN, ACCESS_TOKEN_SECRET) new_id = 0 old_id = 0 while response = twitter.get(GET_API_URL + tweet_num.to_s) if response.code.to_i == 200 data = JSON::parse(response.body) if old_id == 0 ¦¦ old_id != data[0]["id"].to_i new_id = data[0]["id"].to_i data.reverse.each do ¦d¦ if old_id < d["id"].to_i puts "[¥e[33m#{d["created_at"]}¥e[m] ¥e[36m#{d["user"]["screen_name"]}¥e[m: #{d["text"]}" end end old_id = new_id end else p response raise "Request failed: " + response.code.to_s end sleep interval end
[/program]
これを./bin/mruby timeline.rbとかして実行すると、タイムラインが表示されます。
ZabbixのAPIをつついてみる
ZabbixのAPIのをつつきたい場合は、以下のように書くと良いでしょう。
[program lang=’ruby’ escaped=’true’]
config = { :url => "http://127.0.0.1/zabbix/api_jsonrpc.php", :ua => "mruby-zabbix", :user => "api-admin", :pass => "api-admin", } z = Zabbix::Client.new(config) data = { :method => "get", :object => "host", :params => { :output => "extend", :filter => { :host => "example.com", }, }, } puts "request: #{JSON::stringify(data)}" puts "response: #{z.post(data)["body"]}"
[/program]
paramsシンボルにAPIの仕様にのっとったJSONをハッシュ形式で与えてやれば、Zabbixにmrubyを組み込んだ各種デバイスから指示が出せます。
GrowthForecastにデータを送ってみる
エアコンを監視していたり、様々なセンサーデータをRaspberry Piで集めていて、C/C++アプリからグラフ化したいデータをGrowthForecastに送りたい場合は、以下のように書くと良いでしょう。
[program lang=’ruby’ escaped=’true’]
g = GrowthForecast::Client.new("127.0.0.1", 5125) config = { :service => "apache", :section => "scoreboard", :graph => "worker", } data = { :number => 7, :color => "#333399", :mode => "count", } p g.post(config, data)
[/program]
これで、エアコンを監視しているRaspberry Piから、GrowthForecastにデータを送って良い感じに宅内情報をグラフ化する事ができます。
Fluentdにデータを送ってみる
組み込みデバイスにmrubyを組み込んでいたり、低レイヤーなアプリから定期的にログを直接fluentdに投げたい場合は、以下のように書くと良いでしょう。
[program lang=’ruby’ escaped=’true’]
log = Fluent::Logger.new(nil, :host=>'127.0.0.1', :port=>8888) log.post('myapp.access', {"agent"=>"foo"})
[/program]
これで簡単にmrubyを組み込んだデバイスや低レイヤーなソフトウェアの内部情報をfluentdに投げて解析する事ができます。
C/C++アプリへの組み込み方
基本はここに書かれているような感じです。これを参考にすると良いでしょう。分からない事があったら、Twitterでmrubyというキーワードを入れて質問すると、誰かが反応してくれると思います。
基本は、
- rakeで生成されたbuild/host/lib/libmruby.aをCアプリにリンクさせる
- リンクさせる際にはbuild/host/lib/libmruby.flags.makから必要なincludeファイルやライブラリを得る
です。libmruby.flags.makから得たcflagsとldflagsとlibsをgccのオプションに渡して、libmruby.aをリンクさせる、という手順です。
例えばmod_mrubyでは以下のようなMakefileを使って、動的に読み込むようにしています。
[program lang=’bash’ escaped=’true’]
# suport mrbgems MRUBY_MAK_FILE := $(MRUBY_ROOT)/build/host/lib/libmruby.flags.mak ifeq ($(wildcard $(MRUBY_MAK_FILE)),) MRUBY_CFLAGS = MRUBY_LDFLAGS = MRUBY_LIBS = else include $(MRUBY_MAK_FILE) endif APXS_LDFLAGS=-Wl,-lcrypto,-lm, CFLAGS=$(INC) LDFLAGS=$(MRUBY_LDFLAGS) LIBS=$(LIB) $(MRUBY_LIBS)
[/program]
これによって生成されたC/C++アプリから上記のRubyコードにデータをC側から渡しつつ実行することで、C/C++アプリから簡単にmruby経由でのHTTP通信が可能になります。
最後に
どうでしょう。このように、mrubyをちょっと弄ってみたら、HTTP通信をしたくなるのはエンジニアの性だと思いますので、上記のサンプルを参考に色々とC/C++アプリやデバイス等から簡単にHTTP通信を楽しんでみて下さい。最近はmrubyで色々なデバイスを動かしている事例を見かけますので、そこからHTTP通信でデータを送受信したりすると面白い事が沢山できるかもしれませんね!
何か良い感じのmrbgemができる事を楽しみにしています。