module AkamaiRSpec::Matchers

Public Instance Methods

cache_headers() click to toggle source
# File lib/akamai_rspec/matchers/caching.rb, line 53
def cache_headers
  @responses.map {|response| response.headers[:x_cache] }
end
cache_server(header) click to toggle source
# File lib/akamai_rspec/matchers/caching.rb, line 61
def cache_server(header)
  header.split(" ")[2]
end
cache_servers() click to toggle source
# File lib/akamai_rspec/matchers/caching.rb, line 57
def cache_servers
  cache_headers.map &method(:cache_server)
end
cc_directives(origin_response, akamai_response) click to toggle source
# File lib/akamai_rspec/matchers/honour_origin_headers.rb, line 42
def cc_directives(origin_response, akamai_response)
  origin_cc, akamai_cc = clean_cc_directives(origin_response, akamai_response)
  check_cc(origin_cc, akamai_cc) unless (origin_cc & ['no-store', 'no-cache']).empty?
  return origin_cc, akamai_cc
end
check_and_clean_header(origin_cc, akamai_cc, expected) click to toggle source
# File lib/akamai_rspec/matchers/honour_origin_headers.rb, line 48
def check_and_clean_header(origin_cc, akamai_cc, expected)
  unless akamai_cc.include? expected
    fail "Akamai was expected to, but did not, add 'Cache-Control: #{expected}' as Origin sent 'no-store' or 'no-cache'"
  end
  akamai_cc.delete expected unless origin_cc.include? expected
  akamai_cc
end
check_cache_control(origin_response, akamai_response, headers) click to toggle source
# File lib/akamai_rspec/matchers/honour_origin_headers.rb, line 102
def check_cache_control(origin_response, akamai_response, headers)
  if [:both, :cache_control].include? headers
    origin_cc, akamai_cc = cc_directives(origin_response, akamai_response)
    origin_cc, akamai_cc = check_max_age(origin_cc, akamai_cc)
    validate_akamai_dropped(origin_cc, akamai_cc)
    validate_akamai_added(origin_cc, akamai_cc)
  end
end
check_cc(origin_cc, akamai_cc) click to toggle source
# File lib/akamai_rspec/matchers/honour_origin_headers.rb, line 56
def check_cc(origin_cc, akamai_cc)
  ['no-store', 'max-age=0'].each do |expected|
    akamai_cc = check_and_clean_header(origin_cc, akamai_cc, expected)
  end
  return origin_cc, akamai_cc
end
check_expires(origin_response, akamai_response, headers) click to toggle source
# File lib/akamai_rspec/matchers/honour_origin_headers.rb, line 111
def check_expires(origin_response, akamai_response, headers)
  if [:both, :expires].include? headers
    origin_expires, akamai_expires = expires(origin_response, akamai_response)

    fail "Origin sent 'Expires: #{
      origin_response.headers[:expires]
    }' but Akamai sent 'Expires: #{
      akamai_response.headers[:expires]
    }', varies by #{
      expires_diff origin_expires, akamai_expires
    } seconds" unless expires_match?(origin_expires, akamai_expires)

  end
end
check_max_age(origin_cc_directives, akamai_cc_directives) click to toggle source
# File lib/akamai_rspec/matchers/honour_origin_headers.rb, line 77
def check_max_age(origin_cc_directives, akamai_cc_directives)
  origin_max_age, origin_cc_directives = clean_max_age(origin_cc_directives)
  akamai_max_age, akamai_cc_directives = clean_max_age(akamai_cc_directives)
  fail "Akamai sent a max-age but Origin did not" if akamai_max_age && origin_max_age.nil?

  if (akamai_max_age && origin_max_age) && (akamai_max_age > origin_max_age)
    fail "Akamai sent a max-age greater than Origin's: #{akamai_max_age} > #{origin_max_age}"
  end
  return origin_cc_directives, akamai_cc_directives
end
clean_cc_directives(origin_response, akamai_response) click to toggle source
# File lib/akamai_rspec/matchers/honour_origin_headers.rb, line 34
def clean_cc_directives(origin_response, akamai_response)
  origin_cc_directives = origin_response.headers[:cache_control].split(/[, ]+/).to_set
  akamai_cc_directives = akamai_response.headers[:cache_control].split(/[, ]+/).to_set

  origin_cc_directives.delete 'must-revalidate' # as Akamai does no pass it on
  return origin_cc_directives, akamai_cc_directives
end
clean_max_age(cc_directives) click to toggle source
# File lib/akamai_rspec/matchers/honour_origin_headers.rb, line 71
def clean_max_age(cc_directives)
  max_age = max_age(cc_directives)
  cc_directives.delete max_age if max_age
  return max_age_to_num(max_age), cc_directives
end
expires(origin_response, akamai_response) click to toggle source
# File lib/akamai_rspec/matchers/honour_origin_headers.rb, line 135
def expires(origin_response, akamai_response)
  return origin_expires(origin_response), httpdate(akamai_response.headers[:expires])
end
expires_diff(origin, akamai) click to toggle source
# File lib/akamai_rspec/matchers/honour_origin_headers.rb, line 131
def expires_diff(origin, akamai)
  ((akamai || Time.now).to_i - (origin || Time.now).to_i).abs
end
expires_match?(origin, akamai) click to toggle source
# File lib/akamai_rspec/matchers/honour_origin_headers.rb, line 126
def expires_match?(origin, akamai)
  # Allow some clock skew
   expires_diff(origin, akamai) <= @max_clock_skew
end
fix_date_header(origin_response) click to toggle source
# File lib/akamai_rspec/matchers/honour_origin_headers.rb, line 25
def fix_date_header(origin_response)
  origin_response.headers[:date] ||= Time.now.httpdate
  origin_response
end
hit?(response) click to toggle source
# File lib/akamai_rspec/matchers/caching.rb, line 37
def hit?(response)
  response.headers[:x_cache] =~ /TCP(\w+)?_HIT/
end
httpdate(header) click to toggle source
# File lib/akamai_rspec/matchers/honour_origin_headers.rb, line 144
def httpdate(header)
  Time.httpdate(header) rescue nil
end
max_age(cc_directives) click to toggle source
# File lib/akamai_rspec/matchers/honour_origin_headers.rb, line 63
def max_age(cc_directives)
  cc_directives.detect { |d| d.start_with? 'max-age=' }
end
max_age_to_num(max_age) click to toggle source
# File lib/akamai_rspec/matchers/honour_origin_headers.rb, line 67
def max_age_to_num(max_age)
  max_age.split('=').last.to_i rescue nil
end
origin_expires(origin_response) click to toggle source
# File lib/akamai_rspec/matchers/honour_origin_headers.rb, line 139
def origin_expires(origin_response)
  expires = origin_response.headers[:expires]
  expires == '0' ? httpdate(origin_response.headers[:date]) : httpdate(expires)
end
origin_response(origin) click to toggle source
# File lib/akamai_rspec/matchers/honour_origin_headers.rb, line 30
def origin_response(origin)
  fix_date_header(RestClient::Request.execute(method: :get, url: origin, verify_ssl: false))
end
refresh_hit?(response) click to toggle source
# File lib/akamai_rspec/matchers/caching.rb, line 33
def refresh_hit?(response)
  response.headers[:x_cache] =~ /TCP_REFRESH/
end
suggest_allow_refresh?(allow_refresh) click to toggle source
# File lib/akamai_rspec/matchers/caching.rb, line 41
def suggest_allow_refresh?(allow_refresh)
  !allow_refresh &&
  !@responses.any?(&method(:hit?)) &&
  @responses.any?(&method(:refresh_hit?))
end
validate_akamai_added(origin_cc, akamai_cc) click to toggle source
# File lib/akamai_rspec/matchers/honour_origin_headers.rb, line 95
def validate_akamai_added(origin_cc, akamai_cc)
  added = akamai_cc - origin_cc
  unless added.empty?
    fail "Akamai unexpectedly added 'Cache-Control: #{added.to_a.join ','}'"
  end
end
validate_akamai_dropped(origin_cc, akamai_cc) click to toggle source
# File lib/akamai_rspec/matchers/honour_origin_headers.rb, line 88
def validate_akamai_dropped(origin_cc, akamai_cc)
  dropped = origin_cc - akamai_cc
  unless dropped.empty?
    fail "Origin sent 'Cache-Control: #{dropped.to_a.join ','}', but Akamai did not."
  end
end