diff --git a/lib/itamae/resource/http_request.rb b/lib/itamae/resource/http_request.rb index dfe88759..236849ee 100644 --- a/lib/itamae/resource/http_request.rb +++ b/lib/itamae/resource/http_request.rb @@ -1,27 +1,45 @@ require 'itamae' require 'uri' -require 'net/http' +require 'net/https' module Itamae module Resource class HttpRequest < File - UrlNotFoundError = Class.new(StandardError) + RedirectLimitExceeded = Class.new(StandardError) define_attribute :action, default: :get define_attribute :headers, type: Hash, default: {} define_attribute :message, type: String, default: "" + define_attribute :redirect_limit, type: Integer, default: 10 define_attribute :url, type: String, required: true def pre_action uri = URI.parse(attributes.url) - http = Net::HTTP.new(uri.host, uri.port) - http.use_ssl = true if uri.scheme == "https" - - case attributes.action - when :delete, :get, :options - response = http.method(attributes.action).call(uri.request_uri, attributes.headers) - when :post, :put - response = http.method(attributes.action).call(uri.request_uri, attributes.message, attributes.headers) + response = nil + redirects_followed = 0 + + loop do + http = Net::HTTP.new(uri.host, uri.port) + http.use_ssl = true if uri.scheme == "https" + + case attributes.action + when :delete, :get, :options + response = http.method(attributes.action).call(uri.request_uri, attributes.headers) + when :post, :put + response = http.method(attributes.action).call(uri.request_uri, attributes.message, attributes.headers) + end + + if response.kind_of?(Net::HTTPRedirection) + if redirects_followed < attributes.redirect_limit + uri = URI.parse(response["location"]) + redirects_followed += 1 + Itamae.logger.debug "Following redirect #{redirects_followed}/#{attributes.redirect_limit}" + else + raise RedirectLimitExceeded + end + else + break + end end attributes.content = response.body diff --git a/spec/integration/default_spec.rb b/spec/integration/default_spec.rb index 83673fe3..800fe229 100644 --- a/spec/integration/default_spec.rb +++ b/spec/integration/default_spec.rb @@ -101,6 +101,11 @@ its(:content) { should match(/"User-Agent": "Itamae"/) } end +describe file('/tmp/http_request_redirect.html') do + it { should be_file } + its(:content) { should match(/"from": "itamae"/) } +end + describe file('/tmp/notifies') do it { should be_file } its(:content) { should eq("2431") } diff --git a/spec/integration/recipes/default.rb b/spec/integration/recipes/default.rb index a8660318..432ad7cc 100644 --- a/spec/integration/recipes/default.rb +++ b/spec/integration/recipes/default.rb @@ -186,6 +186,11 @@ url "https://httpbin.org/get" end +http_request "/tmp/http_request_redirect.html" do + redirect_limit 1 + url "https://httpbin.org/redirect-to?url=https%3A%2F%2Fhttpbin.org%2Fget%3Ffrom%3Ditamae" +end + ###### service "cron" do