http_caller.rb revision 61ca03fc1ce689310740e8ae71fdaa533d2ba1bc
02c335c23bf5fa225a467c19f2c063fb0dc7b8c3Timo Sirainenmodule UriFetcher
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen include Errors
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen DEFAULT_REDIRECTS = 10
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen class HTTPCaller
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen include UriFetcher::Errors
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen attr_accessor :uri, :data, :redirect_limit
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen attr_accessor :previous_response, :current_response
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen attr_accessor :content_test_block, :write_file, :file_type
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen def initialize(uri, data: {}, redirect_limit: DEFAULT_REDIRECTS)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen self.uri = uri
f16c114c20bbd7d292d93415d1e56c8dd6abd3e7Timo Sirainen self.data = data
f16c114c20bbd7d292d93415d1e56c8dd6abd3e7Timo Sirainen self.redirect_limit = redirect_limit
f16c114c20bbd7d292d93415d1e56c8dd6abd3e7Timo Sirainen end
f16c114c20bbd7d292d93415d1e56c8dd6abd3e7Timo Sirainen
f16c114c20bbd7d292d93415d1e56c8dd6abd3e7Timo Sirainen # Currently only File and Tempfile are
f16c114c20bbd7d292d93415d1e56c8dd6abd3e7Timo Sirainen # allowed for file_type.
f16c114c20bbd7d292d93415d1e56c8dd6abd3e7Timo Sirainen def call(write_file: nil, file_type: File)
f16c114c20bbd7d292d93415d1e56c8dd6abd3e7Timo Sirainen self.write_file = write_file
f16c114c20bbd7d292d93415d1e56c8dd6abd3e7Timo Sirainen self.file_type = file_type
f16c114c20bbd7d292d93415d1e56c8dd6abd3e7Timo Sirainen fetch
f16c114c20bbd7d292d93415d1e56c8dd6abd3e7Timo Sirainen end
f16c114c20bbd7d292d93415d1e56c8dd6abd3e7Timo Sirainen
f16c114c20bbd7d292d93415d1e56c8dd6abd3e7Timo Sirainen def fetch
f16c114c20bbd7d292d93415d1e56c8dd6abd3e7Timo Sirainen check_redirections_count
f16c114c20bbd7d292d93415d1e56c8dd6abd3e7Timo Sirainen result = nil
f16c114c20bbd7d292d93415d1e56c8dd6abd3e7Timo Sirainen make_http_request(URI(uri)) { |r| result = handle_response(r) }
f16c114c20bbd7d292d93415d1e56c8dd6abd3e7Timo Sirainen result
f16c114c20bbd7d292d93415d1e56c8dd6abd3e7Timo Sirainen end
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen def has_actual_content_through(&block)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen self.content_test_block = block
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen end
16f816d3f3c32ae3351834253f52ddd0212bcbf3Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen protected
98c1cf256927e254f0c092acd2ddcd7ea50bd009Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen def make_http_request(uri, &block)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen raise NotImplementedError
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen end
84e1634acc701d14e358e27f1beff5ad74f5004aTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen private
98c1cf256927e254f0c092acd2ddcd7ea50bd009Timo Sirainen def check_redirections_count
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if redirect_limit == 0
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen raise TooManyRedirectionsError.new(last_response: previous_response)
022412398e56a8f31ef111cfd7271498d64af9a9Timo Sirainen end
1a073dd6184645b026583274e05afba10dcc20bbTimo Sirainen end
98c1cf256927e254f0c092acd2ddcd7ea50bd009Timo Sirainen
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen def handle_response(response)
9aa52288a4b53186d81b0ec9afa7d9e0a8ee8753Timo Sirainen self.current_response = response
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if has_actual_content?(response)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen provide_result(response)
e06c0b65c16ccce69bbee009ead14d7d3d17a256Timo Sirainen elsif is_redirection?(response)
e05ea8311ae16687295048e88ca205dfe29fbcbfTimo Sirainen response.read_body
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen recall
8fcff4c5b52f24d9c681805fdf06b486f1d0fcbeTimo Sirainen else
98c1cf256927e254f0c092acd2ddcd7ea50bd009Timo Sirainen response.read_body
98c1cf256927e254f0c092acd2ddcd7ea50bd009Timo Sirainen msg = <<-MSG
f7d43647acc6dc80064c8c4cacf5bf86f754c530Timo SirainenCan't follow the response from #{uri} anymore.
98c1cf256927e254f0c092acd2ddcd7ea50bd009Timo Sirainen MSG
98c1cf256927e254f0c092acd2ddcd7ea50bd009Timo Sirainen raise UnfollowableResponseError.new(msg, last_response: response)
98c1cf256927e254f0c092acd2ddcd7ea50bd009Timo Sirainen end
98c1cf256927e254f0c092acd2ddcd7ea50bd009Timo Sirainen end
98c1cf256927e254f0c092acd2ddcd7ea50bd009Timo Sirainen
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen def recall
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen self.redirect_limit -= 1
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen self.previous_response = current_response
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen call(write_file: write_file, file_type: file_type)
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen end
b6d817f0effeff645aadc01fd468a7d4084ba1f2Timo Sirainen
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen def is_redirection?(response)
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen response['location'] && !response['location'].empty?
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen end
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen def has_actual_content?(response)
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen if self.content_test_block
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen content_test_block.call(response)
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen else
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen response.is_a?(Net::HTTPSuccess) &&
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen response.content_type != 'text/html'
ca98892a6b8a30ffc1fe26fcf02c7d59e3204e7eTimo Sirainen end
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen end
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen def provide_io
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen if write_file
02b79f9c2636da1829eee5b92753602bba8b67edTimo Sirainen if file_type == File
02b79f9c2636da1829eee5b92753602bba8b67edTimo Sirainen file_type.new(write_file, 'w+')
02b79f9c2636da1829eee5b92753602bba8b67edTimo Sirainen elsif file_type == Tempfile
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen file_type.new('uri-fetcher')
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen end
1d2b188f0eedc3cab6e27ceac5425a037f38042eTimo Sirainen else
02b79f9c2636da1829eee5b92753602bba8b67edTimo Sirainen ''
02b79f9c2636da1829eee5b92753602bba8b67edTimo Sirainen end
02b79f9c2636da1829eee5b92753602bba8b67edTimo Sirainen end
02b79f9c2636da1829eee5b92753602bba8b67edTimo Sirainen
02b79f9c2636da1829eee5b92753602bba8b67edTimo Sirainen def provide_result(response)
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen io = provide_io
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen response.read_body { |chunk| io << chunk }
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen io.rewind if io.respond_to?(:rewind)
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen io
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen end
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen def data_json
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen (data || {}).to_json
a2637488c8d514ec1ac3914811deee814f9761b3Timo Sirainen end
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen end
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainenend
299183fbb6ec5d0828a0880da372540421ac4665Timo Sirainen