Faradayのmiddlewareの作り方

こんにちは、久保田です。 今回はRubyのHTTPクライアント、Faradayのmiddlewareの作り方をご紹介しようと思います。
RubyKaigi2016のToru KawamuraさんのWeb Clients for Ruby and What they should be in the future の発表に触発されました。

FaradayはRack同様、middlewareを作り独自の機能を追加することができます。
このmiddlewareの機能を作ることで、リクエスト、レスポンスの処理をFaradayの中に隠蔽することが可能になります。

middlewareの作り方

middlewareの作り方は、

  • Faraday::Middlewareを継承したクラスを実装
  • register_middlewareメソッドを使ってmiddlewareとしてクラスを登録する。

この2ステップで作ることができます。

そしてFaradayのインスタンスを作る時に宣言することで使用することができます。

Faraday::Middlewareを継承したクラスを実装

まず、リクエストをhookするためには、

class Foo < Faraday::Middleware
  def call(req_env)
    # リクエスト時に動く
  end
end

最低限これだけあればOKです。
callの引数にリクエスト時にFaradayが生成した変数のセットが入っており、それを書き換えることなどができます。

そして、レスポンスをhookするためには、

class Foo < Faraday::Middleware
  def call(req_env)
    # リクエスト時に動く
    ...

    @app.call(req_env).on_complete do |res_env|
      # レスポンスが返ってきたらコールバックされる
    end
  end
end

これでOKです。 @app.call(req_env).on_completeにブロックを渡すことで、レスポンスが返ってきた時にコールバックされるブロックを定義できます。
@appはFaradayが定義しています。

register_middlewareメソッドを使ってmiddlewareとしてクラスを登録する。

middlewareができたらmiddlewareとして、Faradayに登録します。

この時の登録の方法でmiddlewareをリクエスト時に使えるものにするか、レスポンスが返ってきた時に使えるものにするか、両方で使うかが決まります。
そしてmiddlewareの使用時に使うメソッドも変わってきます。
正しいものを選びましょう。

リクエスト時のみ

Faraday::Request.register_middleware(foo: Foo)

使用時

connection = Faraday.new('http://example.com') do |conn|
  conn.request :foo
end

レスポンス時のみ

Faraday::Response.register_middleware(foo: Foo)

使用時

connection = Faraday.new('http://example.com') do |conn|
  conn.response :foo
end

両方

Faraday::Middleware.register_middleware(foo: Foo)

使用時

connection = Faraday.new('http://example.com') do |conn|
  conn.use :foo
end

以上になります。 この機能を使って綺麗なAPI用のクライアントや、スクレイピングする機能を開発していきたいですね。

今回参考にしたのは、こちらのGemです。
https://github.com/lostisland/faraday_middleware