コージィコーンモテル

読書とRPGを趣味とするエンジニアのblog

Curb使ってみる

とあるStack Overflowの質問でCurbというgemを使っていたので解決できるかなーと思ってインストールしてみた。

Curbって?

libcurlのrubyバインディングです。

cURLを使ったことがあれば、それと同じ機能をrubyスクリプトから呼び出すためのものと考えて大丈夫。 使ったことがない人は、万能なデータ転送ツールなのでいじっておくべきかも。

OSXなら初期装備だし、Linuxも、メジャーなディストリビューションで、ミニマル設定とかでなければ入ってると思います。 なくても、おそらく全てのパッケージマネージャでらくらくインストールできるはず。

試してみましょう。

curl www.example.com

HTMLがズラ〜と出力されたら成功です。

詳しい使い方を説明してると夜が明けてしまうので、日本語ドキュメントを見てください。 多分なんでもできます。驚くほど高機能です。

環境つくる

既存環境を汚したくないので、ローカルでやります。適当にディレクトリを作って、Bundlerを設定します。

mkdir curb_test
cd curb_test
bundle init

これでGemfileが作成されるので、今回使うgemを記入します

# A sample Gemfile
source "https://rubygems.org"

gem "curb"
gem "sinatra"

書いたらローカル環境にgemをインストールします。

bundle install --path=vendor/bundle

これで準備はOK。

サーバつくる

Curbを試すため、Sinatraを使ってAPIサーバとも呼べなさそうなものを作ってみます。

質問では、CookieSESSIONIDなる文字列を格納しつつユーザ名とパスワードをPOSTしてログインという感じだったので、一応偽ユーザ&パスワードチェックを入れてます。Cookieはめんどいので単にコンソールに出力して確認できるだけにしました。本当に役に立たないですがあくまでCurbが主役なので。

# server.rb
require 'sinatra'
require 'json'

post '/' do
  content_type:json

  # just show cookies on console
  p request.cookies

  # fake username&pass check
  if params['user'] != 'user' || params['pass'] != 'pass'
    return {"status":"failed"}.to_json
  end

  {"data":[{"value":2.74}],"status":"success"}.to_json
end

それぞれの行が何をしてるか、一目瞭然なのがrubyのいいところ

bundle exec ruby server.rb

書けたらこれでサーバが立ち上がります。デフォルトではlocalhostの4567番ポートにあがるはず。

cURLでテスト

クライアントを書く前に、cURLを使ってコマンドラインからテストしてみましょう

curl -X POST -d "user=user&pass=pass" -b "SESSIONID=123" localhost:4567

"status":"success"を含むJSONが返ってくれば成功。"failed"ならユーザ名かパスワードが間違ってます。 また、サーバ側で{"SESSIONID"=>"123"}と表示されるはずです。

クライアント作る

いよいよCurbを使います。上記のコマンドを同じことをやってから、結果をパースするクライアントを書いてみます。

# client.rb
require 'curb'
require 'json'

url = 'localhost:4567'
params = {'user':'user','pass':'pass'}
cookie = 'SESSIONID=123'

# generate http request
post = Curl.post(url,params) do |curl|
  curl.cookies = cookie
end

# parse response
res = JSON.parse(post.body_str)

puts res["status"] if res["status"]

gem名はCurbですがモジュール名は普通にCurlなので注意。

Curl.postにURLとパラメータを渡してます。その他の設定はブロックにまとめて渡します。結果はCurl::Easyインスタンスで返ってきますが、基本的にはbody_strメソッドを知ってればレスポンスを受け取れるのでOK。他のメソッドドキュメントを読みましょう。

"success"が出力されれば成功。簡単ですね。

所感

Curbを初めて使ってみました。扱ったのはかなりプリミティブな例でしたが、とても書きやすい(気がする)。

で、これをCurbでやる必要はあるのか?という問いに対しては、ピュアなrubyで書かれているNet::HTTPよりも、Curbの方が速いんですくらいしかまだ言えません。同じlibcurlを使用しているTyphoeusとの違いは?とか聞かれると、ちょっと厳しい。これはいろいろいじってみないとわからないですね。

結論