lib/spaceship/client.rb in spaceship-0.20.0 vs lib/spaceship/client.rb in spaceship-0.21.0
- old
+ new
@@ -37,10 +37,13 @@
class UnexpectedResponse < StandardError; end
# Raised when 302 is received from portal request
class AppleTimeoutError < StandardError; end
+ # Raised when 401 is received from portal request
+ class UnauthorizedAccessError < StandardError; end
+
# Authenticates with Apple's web services. This method has to be called once
# to generate a valid session. The session will automatically be used from then
# on.
#
# This method will automatically use the username from the Appfile (if available)
@@ -64,12 +67,18 @@
def self.hostname
raise "You must implemented self.hostname"
end
def initialize
+ options = {
+ request: {
+ timeout: 300,
+ open_timeout: 300
+ }
+ }
@cookie = HTTP::CookieJar.new
- @client = Faraday.new(self.class.hostname) do |c|
+ @client = Faraday.new(self.class.hostname, options) do |c|
c.response :json, content_type: /\bjson$/
c.response :xml, content_type: /\bxml$/
c.response :plist, content_type: /\bplist$/
c.use :cookie_jar, jar: @cookie
c.adapter Faraday.default_adapter
@@ -166,13 +175,13 @@
if user.to_s.strip.empty? or password.to_s.strip.empty?
raise NoUserCredentialsError.new, "No login data provided"
end
self.user = user
-
+ @password = password
begin
- send_login_request(user, password) # different in subclasses
+ do_login(user, password)
rescue InvalidUserCredentialsError => ex
raise ex unless keychain_entry
if keychain_entry.invalid_credentials
login(user)
@@ -180,24 +189,40 @@
puts "Please run this tool again to apply the new password"
end
end
end
- def with_retry(tries = 5, &block)
- return block.call
- rescue Faraday::Error::TimeoutError, AppleTimeoutError => ex # New Faraday version: Faraday::TimeoutError => ex
+ def with_retry(tries = 5, &_block)
+ return yield
+ rescue Faraday::Error::ConnectionFailed, Faraday::Error::TimeoutError, AppleTimeoutError => ex # New Faraday version: Faraday::TimeoutError => ex
unless (tries -= 1).zero?
logger.warn("Timeout received: '#{ex.message}'. Retrying after 3 seconds (remaining: #{tries})...")
- sleep 3
+ sleep 3 unless defined? SpecHelper
retry
end
-
raise ex # re-raise the exception
+ rescue UnauthorizedAccessError => ex
+ if @loggedin
+ msg = "Auth error received: '#{ex.message}'. Login in again then retrying after 3 seconds (remaining: #{tries})..."
+ puts msg if $verbose
+ logger.warn msg
+ do_login(self.user, @password)
+ sleep 3 unless defined? SpecHelper
+ retry
+ end
+ raise ex # re-raise the exception
end
private
+ def do_login(user, password)
+ @loggedin = false
+ ret = send_login_request(user, password) # different in subclasses
+ @loggedin = true
+ ret
+ end
+
# Is called from `parse_response` to store the latest csrf_token (if available)
def store_csrf_tokens(response)
if response and response.headers
tokens = response.headers.select { |k, v| %w(csrf csrf_ts).include?(k) }
if tokens and !tokens.empty?
@@ -236,21 +261,28 @@
params_to_log.delete(:accountPassword) # Dev Portal
params_to_log.delete(:theAccountPW) # iTC
params_to_log = params_to_log.collect do |key, value|
"{#{key}: #{value}}"
end
- logger.info("#{method.upcase}: #{url} #{params_to_log.join(', ')}")
+ logger.info(">> #{method.upcase}: #{url} #{params_to_log.join(', ')}")
end
def log_response(method, url, response)
- logger.debug("#{method.upcase}: #{url}: #{response.body}")
+ logger.debug("<< #{method.upcase}: #{url}: #{response.body}")
end
# Actually sends the request to the remote server
# Automatically retries the request up to 3 times if something goes wrong
def send_request(method, url_or_path, params, headers, &block)
with_retry do
response = @client.send(method, url_or_path, params, headers, &block)
+ resp_hash = response.to_hash
+ if resp_hash[:status] == 401
+ msg = "Auth lost"
+ logger.warn msg
+ raise UnauthorizedAccessError.new, "Unauthorized Access"
+ end
+
if response.body.to_s.include?("<title>302 Found</title>")
raise AppleTimeoutError.new, "Apple 302 detected"
end
return response
end