class LinkScout::Runner

Constants

DEFAULT_OPTIONS

Public Class Methods

new(args) click to toggle source
# File lib/link_scout/runner.rb, line 9
def initialize(args)
  @args = args
end

Public Instance Methods

run() click to toggle source
# File lib/link_scout/runner.rb, line 13
def run
  case
  when single?(@args)
    @options = merge_defaults(@args[1])
    @options[:url] = @args[0]
    run_single
  when single_hash?(@args)
    @options = merge_defaults(@args[0])
    run_single
  when multiple_shared?(@args)
    @options = merge_defaults(@args[1])
    run_multiple_shared(@args[0])
  when multiple_individual?(@args)
    run_multiple(@args[0])
  else
    raise InvalidUsageError,  'Invalid usage of LinkScout::run. Please consult the README for help'
  end
end

Private Instance Methods

fetch(uri_str, limit=nil) click to toggle source

Fetches uri_str and tries limit times in case of redirections. @return response

# File lib/link_scout/runner.rb, line 42
def fetch(uri_str, limit=nil)
  # set starting limit if limit is not set
  limit ||= @options[:limit].to_i
  retry_count ||= 2

  # keeps track of previous url in case redirects are done
  @final_uri ||= nil

  raise RedirectLoopError, 'HTTP redirect too deep for ' + uri_str if limit == 0

  #uri_str = response['location']
  url = URI.parse(sanitize_uri(uri_str))
  req = Net::HTTP::Get.new(url, user_agent: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36')
  response = Net::HTTP.start(url.host, url.port, use_ssl: url.scheme == 'https', read_timeout: 30) { |http| http.request(req) }

  @final_uri = uri_str

  case response
  when Net::HTTPRedirection
    return response unless follow_redirects?
    fetch(response['location'], limit - 1)
  else
    response
  end

rescue Errno::ETIMEDOUT
  [response, true]
rescue Net::ReadTimeout => e
  retry_count -= 1
  p "Net::ReadTimeout - retry #{retry_count} fetch url " + uri_str and retry if retry_count > 0

  [response, true]
rescue NoMethodError => e
  [response, true]
rescue SocketError
  retry_count -= 1
  p "SocketError - retry #{retry_count} fetch url " + uri_str and retry if retry_count > 0

  [response, true]
rescue URI::InvalidURIError
  [response, true]
end
follow_redirects?() click to toggle source
# File lib/link_scout/runner.rb, line 115
def follow_redirects?
  @options[:follow] == true
end
merge_defaults(options) click to toggle source
# File lib/link_scout/runner.rb, line 34
def merge_defaults(options)
  return DEFAULT_OPTIONS unless options.is_a?(Hash)

  DEFAULT_OPTIONS.merge(options)
end
multiple_individual?(args) click to toggle source

Usage: LinkScout::run([url: url, url: url1], options)

# File lib/link_scout/runner.rb, line 164
def multiple_individual?(args)
  args[0].is_a?(Array) && args[0][0].is_a?(Hash)
end
multiple_shared?(args) click to toggle source

Usage: LinkScout::run([url, url1], options)

# File lib/link_scout/runner.rb, line 170
def multiple_shared?(args)
  args[0].is_a?(Array) && args[0].first.is_a?(String)
end
pattern_success?(response, type) click to toggle source

checks response body against given pattern options:

  • in any case its a success if the pattern type is not set

  • in case of :pattern its a success if the content does match

  • in case of :antipattern its a success if the content does NOT match.

@params response, type @return Bool

# File lib/link_scout/runner.rb, line 142
def pattern_success?(response, type)
  return true if @options[type].nil?
  success = @options[type].match?(response.body)

  return !success if type == :antipattern
  success
end
run_multiple(sets) click to toggle source
# File lib/link_scout/runner.rb, line 178
def run_multiple(sets)
  sets.map do |set|
    @options = merge_defaults(set)
    [set[:url], run_single]
  end
end
run_multiple_shared(urls) click to toggle source
# File lib/link_scout/runner.rb, line 185
def run_multiple_shared(urls)
  urls.map do |url|
    @options[:url] = url

    [url, run_single]
  end
end
run_single() click to toggle source
# File lib/link_scout/runner.rb, line 174
def run_single
  successfull_response?(*fetch(@options[:url]))
end
sanitize_uri(uri_str) click to toggle source
# File lib/link_scout/runner.rb, line 85
def sanitize_uri(uri_str)
  return scheme_and_domain(@final_uri) if ['/', '//'].include? uri_str
  return scheme_and_domain(@final_uri) + uri_str if uri_str.start_with?('/')
  return scheme_and_domain(@final_uri) + uri_str if uri_str.start_with?('?')

  uri_str
end
scheme_and_domain(uri_str) click to toggle source
# File lib/link_scout/runner.rb, line 93
def scheme_and_domain(uri_str)
  uri = URI.parse(uri_str)
  uri.path  = ''
  uri.query = nil

  # ensure that multiple relative redirects still know their domain
  if uri.to_s == ''
    return @last_scheme_and_domain
  end

  @last_scheme_and_domain = uri.to_s
end
single?(args) click to toggle source

Usage: LinkScout::run(url, options)

# File lib/link_scout/runner.rb, line 152
def single?(args)
  args[0].is_a?(String)
end
single_hash?(args) click to toggle source

Usage: LinkScout::run(url: url)

# File lib/link_scout/runner.rb, line 158
def single_hash?(args)
  args[0].is_a?(Hash) && !args[0][:url].nil?
end
status_code_success?(response) click to toggle source
# File lib/link_scout/runner.rb, line 119
def status_code_success?(response)
  [*@options[:success]].map(&:to_s).include?(response.code)
end
successfull_response?(response, invalid=false) click to toggle source
# File lib/link_scout/runner.rb, line 106
def successfull_response?(response, invalid=false)
  !invalid && \
  status_code_success?(response) && \
  pattern_success?(response, :pattern) && \
  pattern_success?(response, :antipattern) && \
  target_success? && \
  deeplink_success?
end
target_success?() click to toggle source
# File lib/link_scout/runner.rb, line 123
def target_success?
  return true if @options[:target].nil?
  @final_uri == @options[:target]
end