ruby-oauth にブロックを渡せるようにする
Ruby には既に OAuth ライブラリ があるが,ブロックを渡せないのでちょっとずつ body を読み込みつつ何かする,というような処理ができない.
最終的には net/http を使っているので,適当にブロックを運ぶように書き換えて
consumer = OAuth::Consumer.new(consumer_key, consumer_secret, :site => 'http://twitter.com') access_token = OAuth::AccessToken.new(consumer, token, token_secret) access_token.get('http://chirpstream.twitter.com/2b/user.json?replies=all') do |res| if res.code == '200' res.read_body do |s| do_something s end end end
とも書けるようにした.
以下 0.4.2 に対する差分.
--- lib-orig/oauth/consumer.rb +++ lib/oauth/consumer.rb @@ -151,7 +151,7 @@ module OAuth # @consumer.request(:get, '/people', @token, { :scheme => :query_string }) # @consumer.request(:post, '/people', @token, {}, @person.to_xml, { 'Content-Type' => 'application/xml' }) # - def request(http_method, path, token = nil, request_options = {}, *arguments) + def request(http_method, path, token = nil, request_options = {}, *arguments, &block) if path !~ /^\// @http = create_http(path) _uri = URI.parse(path) @@ -160,7 +160,10 @@ module OAuth # override the request with your own, this is useful for file uploads which Net::HTTP does not do req = create_signed_request(http_method, path, token, request_options, *arguments) - return nil if block_given? and yield(req) == :done + if block_given? + http.request(req, &block) + return nil + end rsp = http.request(req) # check for an error reported by the Problem Reporting extension # (http://wiki.oauth.net/ProblemReporting) --- lib-orig/oauth/tokens/access_token.rb +++ lib/oauth/tokens/access_token.rb @@ -3,12 +3,16 @@ module OAuth class AccessToken < ConsumerToken # The less intrusive way. Otherwise, if we are to do it correctly inside consumer, # we need to restructure and touch more methods: request(), sign!(), etc. - def request(http_method, path, *arguments) + def request(http_method, path, *arguments, &block) request_uri = URI.parse(path) site_uri = consumer.uri is_service_uri_different = (request_uri.absolute? && request_uri != site_uri) consumer.uri(request_uri) if is_service_uri_different - @response = super(http_method, path, *arguments) + if block_given? + return super(http_method, path, *arguments, &block) + else + @response = super(http_method, path, *arguments) + end # NOTE: reset for wholesomeness? meaning that we admit only AccessToken service calls may use different URIs? # so reset in case consumer is still used for other token-management tasks subsequently? consumer.uri(site_uri) if is_service_uri_different @@ -20,8 +24,8 @@ module OAuth # @response = @token.get('/people') # @response = @token.get('/people', { 'Accept'=>'application/xml' }) # - def get(path, headers = {}) - request(:get, path, headers) + def get(path, headers = {}, &block) + request(:get, path, headers, &block) end # Make a regular HEAD request using AccessToken @@ -40,8 +44,8 @@ module OAuth # @response = @token.post('/people', nil, {'Accept' => 'application/xml' }) # @response = @token.post('/people', @person.to_xml, { 'Accept'=>'application/xml', 'Content-Type' => 'application/xml' }) # - def post(path, body = '', headers = {}) - request(:post, path, body, headers) + def post(path, body = '', headers = {}, &block) + request(:post, path, body, headers, &block) end # Make a regular PUT request using AccessToken @@ -52,8 +56,8 @@ module OAuth # @response = @token.put('/people/123', nil, { 'Accept' => 'application/xml' }) # @response = @token.put('/people/123', @person.to_xml, { 'Accept' => 'application/xml', 'Content-Type' => 'application/xml' }) # - def put(path, body = '', headers = {}) - request(:put, path, body, headers) + def put(path, body = '', headers = {}, &block) + request(:put, path, body, headers, &block) end # Make a regular DELETE request using AccessToken @@ -61,8 +65,8 @@ module OAuth # @response = @token.delete('/people/123') # @response = @token.delete('/people/123', { 'Accept' => 'application/xml' }) # - def delete(path, headers = {}) - request(:delete, path, headers) + def delete(path, headers = {}, &block) + request(:delete, path, headers, &block) end end end --- lib-orig/oauth/tokens/consumer_token.rb +++ lib/oauth/tokens/consumer_token.rb @@ -21,8 +21,12 @@ module OAuth # @token.request(:get, '/people') # @token.request(:post, '/people', @person.to_xml, { 'Content-Type' => 'application/xml' }) # - def request(http_method, path, *arguments) - @response = consumer.request(http_method, path, self, {}, *arguments) + def request(http_method, path, *arguments, &block) + if block_given? + consumer.request(http_method, path, self, {}, *arguments, &block) + else + @response = consumer.request(http_method, path, self, {}, *arguments) + end end # Sign a request generated elsewhere using Net:HTTP::Post.new or friends