akamai_rspec 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/lib/akamai_rspec/akamai_headers.rb +7 -0
- data/lib/akamai_rspec/matchers/caching.rb +54 -0
- data/lib/akamai_rspec/matchers/honour_origin_headers.rb +124 -0
- data/lib/akamai_rspec/matchers/matchers.rb +40 -0
- data/lib/akamai_rspec/matchers/non_akamai.rb +67 -0
- data/lib/akamai_rspec/matchers/redirects.rb +28 -0
- data/lib/akamai_rspec/request.rb +89 -0
- data/lib/akamai_rspec.rb +3 -0
- metadata +92 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA1:
|
|
3
|
+
metadata.gz: 06d8b35c313b71c7d4d8723af6c0f6fac7884ec6
|
|
4
|
+
data.tar.gz: acddb3b50759171eb123010e287a1cf842cc1bb8
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: e9c998292a3c9b68c4e125b43e318b062019903408159916cdc994fc63bf7b58e432190b7ab7dda0f3c3f1d66ef073c8d4c298a87c3749536b2b78a9cfc559d0
|
|
7
|
+
data.tar.gz: 57043ea5fa5f880a19bd2d964adcbb4970adc28b7bbe9812157186c32e76e6f0fe840703c0b4670743c5c4fbed1548e62150a2a7183ccc029c307b1a0f118357
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
module AkamaiHeaders
|
|
2
|
+
def akamai_debug_headers
|
|
3
|
+
{
|
|
4
|
+
pragma: 'akamai-x-cache-on, akamai-x-cache-remote-on, akamai-x-check-cacheable, akamai-x-get-cache-key, akamai-x-get-extracted-values, akamai-x-get-nonces, akamai-x-get-ssl-client-session-id, akamai-x-get-true-cache-key, akamai-x-serial-no'
|
|
5
|
+
}
|
|
6
|
+
end
|
|
7
|
+
end
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
require 'rspec'
|
|
2
|
+
require 'securerandom'
|
|
3
|
+
|
|
4
|
+
RSpec::Matchers.define :be_cacheable do
|
|
5
|
+
match do |url|
|
|
6
|
+
response = RestClient::Request.responsify url
|
|
7
|
+
x_check_cacheable(response, 'YES')
|
|
8
|
+
response.code == 200
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
module RSpec::Matchers
|
|
13
|
+
alias_method :be_cachable, :be_cacheable
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
RSpec::Matchers.define :have_no_cache_set do
|
|
17
|
+
match do |url|
|
|
18
|
+
response = RestClient::Request.responsify url
|
|
19
|
+
cache_control = response.headers[:cache_control]
|
|
20
|
+
fail('Cache-Control has been set') unless cache_control == 'no-cache'
|
|
21
|
+
true
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
RSpec::Matchers.define :not_be_cached do
|
|
26
|
+
match do |url|
|
|
27
|
+
response = RestClient::Request.responsify url
|
|
28
|
+
x_check_cacheable(response, 'NO')
|
|
29
|
+
response = RestClient::Request.responsify response.args[:url] # again to prevent spurious cache miss
|
|
30
|
+
|
|
31
|
+
not_cached = response.headers[:x_cache] =~ /TCP(\w+)?_MISS/
|
|
32
|
+
unless not_cached
|
|
33
|
+
fail("x_cache header does not indicate an origin hit: '#{response.headers[:x_cache]}'")
|
|
34
|
+
end
|
|
35
|
+
response.code == 200 && not_cached
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
RSpec::Matchers.define :be_tier_distributed do
|
|
40
|
+
match do |url|
|
|
41
|
+
response = RestClient::Request.request_cache_miss(url)
|
|
42
|
+
tiered = !response.headers[:x_cache_remote].nil?
|
|
43
|
+
fail('No X-Cache-Remote header in response') unless tiered
|
|
44
|
+
response.code == 200 && tiered
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def x_check_cacheable(response, should_be_cacheable)
|
|
49
|
+
x_check_cacheable = response.headers[:x_check_cacheable]
|
|
50
|
+
fail('No X-Check-Cacheable header?') if x_check_cacheable.nil?
|
|
51
|
+
unless (x_check_cacheable == should_be_cacheable)
|
|
52
|
+
fail("X-Check-Cacheable header is: #{x_check_cacheable} expected #{should_be_cacheable}")
|
|
53
|
+
end
|
|
54
|
+
end
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
require 'rspec'
|
|
2
|
+
require 'set'
|
|
3
|
+
require 'time'
|
|
4
|
+
require 'uri'
|
|
5
|
+
|
|
6
|
+
RSpec::Matchers.define :honour_origin_cache_headers do |origin, headers|
|
|
7
|
+
header_options = [:cache_control, :expires, :both]
|
|
8
|
+
headers ||= :both
|
|
9
|
+
fail("Headers must be one of: #{header_options}") unless header_options.include? headers
|
|
10
|
+
|
|
11
|
+
match do |url|
|
|
12
|
+
akamai_response = RestClient::Request.responsify url
|
|
13
|
+
origin_response = origin_response(origin)
|
|
14
|
+
check_cache_control(origin_response, akamai_response, headers)
|
|
15
|
+
check_expires(origin_response, akamai_response, headers)
|
|
16
|
+
true
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def fix_date_header(origin_response)
|
|
21
|
+
origin_response.headers[:date] = Time.now.httpdate unless origin_response.headers[:date]
|
|
22
|
+
origin_response
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def origin_response(origin)
|
|
26
|
+
fix_date_header(RestClient::Request.execute(method: :get, url: origin, verify_ssl: false))
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def clean_cc_directives(origin_response, akamai_response)
|
|
30
|
+
origin_cc_directives = origin_response.headers[:cache_control].split(/[, ]+/).to_set
|
|
31
|
+
akamai_cc_directives = akamai_response.headers[:cache_control].split(/[, ]+/).to_set
|
|
32
|
+
|
|
33
|
+
origin_cc_directives.delete 'must-revalidate' # as Akamai does no pass it on
|
|
34
|
+
return origin_cc_directives, akamai_cc_directives
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def cc_directives(origin_response, akamai_response)
|
|
38
|
+
origin_cc, akamai_cc = clean_cc_directives(origin_response, akamai_response)
|
|
39
|
+
check_cc(origin_cc, akamai_cc) unless (origin_cc & ['no-store', 'no-cache']).empty?
|
|
40
|
+
return origin_cc, akamai_cc
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def check_and_clean_header(origin_cc, akamai_cc, expected)
|
|
44
|
+
unless akamai_cc.include? expected
|
|
45
|
+
fail "Akamai was expected to, but did not, add 'Cache-Control: #{expected}' as Origin sent 'no-store' or 'no-cache'"
|
|
46
|
+
end
|
|
47
|
+
akamai_cc.delete expected unless origin_cc.include? expected
|
|
48
|
+
akamai_cc
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def check_cc(origin_cc, akamai_cc)
|
|
52
|
+
['no-store', 'max-age=0'].each do |expected|
|
|
53
|
+
akamai_cc = check_and_clean_header(origin_cc, akamai_cc, expected)
|
|
54
|
+
end
|
|
55
|
+
return origin_cc, akamai_cc
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def max_age(cc_directives)
|
|
59
|
+
cc_directives.detect { |d| d.start_with? 'max-age=' }
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def max_age_to_num(max_age)
|
|
63
|
+
max_age.split('=').last.to_i
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def clean_max_age(cc_directives)
|
|
67
|
+
max_age = max_age(cc_directives)
|
|
68
|
+
cc_directives.delete max_age if max_age
|
|
69
|
+
return max_age_to_num(max_age), cc_directives
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def check_max_age(origin_cc_directives, akamai_cc_directives)
|
|
73
|
+
origin_max_age, origin_cc_directives = clean_max_age(origin_cc_directives)
|
|
74
|
+
akamai_max_age, akamai_cc_directives = clean_max_age(akamai_cc_directives)
|
|
75
|
+
if akamai_max_age > origin_max_age
|
|
76
|
+
fail "Akamai sent a max-age greater than Origin's: #{akamai_max_age} > #{origin_max_age}"
|
|
77
|
+
end
|
|
78
|
+
return origin_cc_directives, akamai_cc_directives
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def validate_akamai_dropped(origin_cc, akamai_cc)
|
|
82
|
+
dropped = origin_cc - akamai_cc
|
|
83
|
+
unless dropped.empty?
|
|
84
|
+
fail "Origin sent 'Cache-Control: #{dropped.to_a.join ','}', but Akamai did not."
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def validate_akamai_added(origin_cc, akamai_cc)
|
|
89
|
+
added = akamai_cc - origin_cc
|
|
90
|
+
unless added.empty?
|
|
91
|
+
fail "Akamai unexpectedly added 'Cache-Control: #{added.to_a.join ','}'"
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def check_cache_control(origin_response, akamai_response, headers)
|
|
96
|
+
if [:both, :cache_control].include? headers
|
|
97
|
+
origin_cc, akamai_cc = cc_directives(origin_response, akamai_response)
|
|
98
|
+
origin_cc, akamai_cc = check_max_age(origin_cc, akamai_cc)
|
|
99
|
+
validate_akamai_dropped(origin_cc, akamai_cc)
|
|
100
|
+
validate_akamai_added(origin_cc, akamai_cc)
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def check_expires(origin_response, akamai_response, headers)
|
|
105
|
+
if [:both, :expires].include? headers
|
|
106
|
+
origin_expires, akamai_expires = expires(origin_response, akamai_response)
|
|
107
|
+
validate_expires(origin_expires, akamai_expires)
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def validate_expires(origin, akamai)
|
|
112
|
+
unless akamai.to_i == origin.to_i
|
|
113
|
+
fail "Origin sent 'Expires: #{origin}' but Akamai sent 'Expires: #{akamai}'"
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def expires(origin_response, akamai_response)
|
|
118
|
+
return origin_expires(origin_response), Time.httpdate(akamai_response.headers[:expires])
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def origin_expires(origin_response)
|
|
122
|
+
expires = origin_response.headers[:expires]
|
|
123
|
+
expires == '0' ? Time.httpdate(origin_response.headers[:date]) : Time.httpdate(expires)
|
|
124
|
+
end
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
require 'securerandom'
|
|
2
|
+
require 'rspec'
|
|
3
|
+
require_relative 'redirects'
|
|
4
|
+
require_relative 'caching'
|
|
5
|
+
require_relative 'non_akamai'
|
|
6
|
+
require_relative 'honour_origin_headers'
|
|
7
|
+
include AkamaiHeaders
|
|
8
|
+
|
|
9
|
+
RSpec::Matchers.define :x_cache_key_contains do |contents|
|
|
10
|
+
match do |url|
|
|
11
|
+
response = RestClient::Request.responsify url
|
|
12
|
+
fail 'No X-Cache-Key header' if response.headers[:x_cache_key].nil?
|
|
13
|
+
unless response.headers[:x_cache_key].include?(contents)
|
|
14
|
+
fail("x_cache_key has value '#{response.headers[:x_cache_key]}' which doesn't include '#{contents}'")
|
|
15
|
+
end
|
|
16
|
+
response.code == 200 && response.headers[:x_cache_key].include?(contents)
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
module RSpec::Matchers
|
|
21
|
+
alias_method :be_served_from_origin, :x_cache_key_contains
|
|
22
|
+
alias_method :have_cp_code, :x_cache_key_contains
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
RSpec::Matchers.define :be_forwarded_to_index do |channel|
|
|
26
|
+
match do |url|
|
|
27
|
+
response = RestClient.get(url, akamai_debug_headers)
|
|
28
|
+
|
|
29
|
+
session_info = response.raw_headers['x-akamai-session-info']
|
|
30
|
+
if session_info.nil?
|
|
31
|
+
fail("x-akamai-session-info not found in the headers '#{response.raw_headers}'")
|
|
32
|
+
end
|
|
33
|
+
outcome_attribute = session_info.find { |header| header.include? 'AKA_PM_FWD_URL' }
|
|
34
|
+
if outcome_attribute.nil?
|
|
35
|
+
fail("AKA_PM_FWD_URL not found in the x-akamai-session-info header '#{session_info}'")
|
|
36
|
+
end
|
|
37
|
+
outcome_url = outcome_attribute.split('value=')[1]
|
|
38
|
+
response.code == 200 && outcome_url == "#{channel}"
|
|
39
|
+
end
|
|
40
|
+
end
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
require 'rspec'
|
|
2
|
+
require 'socket'
|
|
3
|
+
require 'openssl'
|
|
4
|
+
|
|
5
|
+
def check_ssl_serial(addr, port, url, serial)
|
|
6
|
+
cert_serial = ssl_cert(addr, port, url).serial.to_s(16).upcase
|
|
7
|
+
fail("Incorrect S/N of: #{cert_serial}") unless cert_serial == serial.upcase
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def ssl_cert(addr, port, url)
|
|
11
|
+
ssl_client = ssl_client_for_verify_cert(TCPSocket.new(addr, port), addr, url)
|
|
12
|
+
# We get this after the request as we have layer 7 routing in Akamai
|
|
13
|
+
cert = OpenSSL::X509::Certificate.new(ssl_client.peer_cert)
|
|
14
|
+
ssl_client.sysclose
|
|
15
|
+
cert
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def dummy_request(url, addr)
|
|
19
|
+
"GET #{url} HTTP/1.1\r\n" \
|
|
20
|
+
'User-Agent: Akamai-Regression-Framework\r\n' \
|
|
21
|
+
"Host: #{addr}\r\n" \
|
|
22
|
+
'Accept: */*\r\n'
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def ssl_client_for_verify_cert(tcp_client, addr, url)
|
|
26
|
+
ssl_client = OpenSSL::SSL::SSLSocket.new(tcp_client)
|
|
27
|
+
ssl_client.sync_close = true
|
|
28
|
+
ssl_client.connect
|
|
29
|
+
ssl_client.puts(dummy_request(url, addr))
|
|
30
|
+
ssl_client
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
RSpec::Matchers.define :be_successful do
|
|
34
|
+
match do |url|
|
|
35
|
+
response = RestClient::Request.responsify url
|
|
36
|
+
fail('Response was not successful') unless response.code == 200
|
|
37
|
+
true
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
RSpec::Matchers.define :be_verifiably_secure do (verify = OpenSSL::SSL::VERIFY_PEER)
|
|
42
|
+
match do |url|
|
|
43
|
+
begin
|
|
44
|
+
RestClient::Request.execute(method: :get, url: url, verify_ssl: verify)
|
|
45
|
+
true
|
|
46
|
+
rescue => e
|
|
47
|
+
raise("#{url} could not be verified as secure, :sad_panda: #{e.message}")
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
RSpec::Matchers.define :be_gzipped do
|
|
53
|
+
match do |response_or_url|
|
|
54
|
+
response = RestClient::Request.responsify response_or_url
|
|
55
|
+
response.headers[:content_encoding] == 'gzip'
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
RSpec::Matchers.define :have_cookie do |cookie|
|
|
60
|
+
match do |response_or_url|
|
|
61
|
+
response = RestClient::Request.responsify response_or_url
|
|
62
|
+
unless response.cookies[cookie]
|
|
63
|
+
fail("Cookie #{cookie} not in #{response.cookies}")
|
|
64
|
+
end
|
|
65
|
+
response.cookies[cookie]
|
|
66
|
+
end
|
|
67
|
+
end
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
require 'rspec'
|
|
2
|
+
|
|
3
|
+
RSpec::Matchers.define :be_permanently_redirected_to do |expected_location|
|
|
4
|
+
match do |url|
|
|
5
|
+
redirect(url, expected_location, 301)
|
|
6
|
+
end
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
RSpec::Matchers.define :be_temporarily_redirected_to do |expected_location|
|
|
10
|
+
match do |url|
|
|
11
|
+
redirect(url, expected_location, 302)
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
RSpec::Matchers.define :be_temporarily_redirected_with_trailing_slash do
|
|
16
|
+
match do |url|
|
|
17
|
+
redirect(url, url + '/', 302)
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def redirect(url, expected_location, expected_response_code)
|
|
22
|
+
response = RestClient.get(url) { |response, _, _| response }
|
|
23
|
+
fail "response was #{response.code}" unless response.code == expected_response_code
|
|
24
|
+
unless response.headers[:location] == expected_location
|
|
25
|
+
fail "redirect location was #{response.headers[:location]} (expected #{expected_location})"
|
|
26
|
+
end
|
|
27
|
+
true
|
|
28
|
+
end
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
require 'rest-client'
|
|
2
|
+
require 'akamai_rspec'
|
|
3
|
+
|
|
4
|
+
module RestClient
|
|
5
|
+
class Request
|
|
6
|
+
@@akamai_network = 'prod'
|
|
7
|
+
@@akamai_stg_domain = 'overwrite me'
|
|
8
|
+
@@akamai_prod_domain = 'overwrite me'
|
|
9
|
+
|
|
10
|
+
def self.domain
|
|
11
|
+
env = @@akamai_network
|
|
12
|
+
case env.downcase
|
|
13
|
+
when 'staging'
|
|
14
|
+
@@akamai_stg_domain
|
|
15
|
+
else
|
|
16
|
+
@@akamai_prod_domain
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def self.akamai_network(env)
|
|
21
|
+
@@akamai_network = env
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def self.stg_domain(domain)
|
|
25
|
+
@@akamai_stg_domain = domain
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def self.prod_domain(domain)
|
|
29
|
+
@@akamai_prod_domain = domain
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def self.http_url(url)
|
|
33
|
+
url = "/#{url}" unless url.start_with?('/')
|
|
34
|
+
"http://#{domain}#{url}"
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def self.https_url(url)
|
|
38
|
+
url = "/#{url}" unless url.start_with?('/')
|
|
39
|
+
"https://#{domain}#{url}"
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# Define the Host header and join the Akamai headers
|
|
43
|
+
def self.options
|
|
44
|
+
akamai_debug_headers
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# Make requests to the right network
|
|
48
|
+
def self.http_get(url, options, cookies = {})
|
|
49
|
+
do_get(url, options, cookies, false)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def self.https_get(url, options, cookies = {})
|
|
53
|
+
do_get(url, options, cookies, true)
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def self.do_get(url, options, cookies = {}, is_secure)
|
|
57
|
+
if is_secure
|
|
58
|
+
base_url = https_url(url)
|
|
59
|
+
else
|
|
60
|
+
base_url = http_url(url)
|
|
61
|
+
end
|
|
62
|
+
headers = options.merge(akamai_debug_headers).merge(cookies)
|
|
63
|
+
do_get_no_ssl(base_url, headers) { |response, _, _| response }
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def self.do_get_no_ssl(url, additional_headers = {}, &block)
|
|
67
|
+
headers = (options[:headers] || {}).merge(additional_headers)
|
|
68
|
+
RestClient::Request.execute(options.merge(
|
|
69
|
+
method: :get,
|
|
70
|
+
url: url,
|
|
71
|
+
verify_ssl: false,
|
|
72
|
+
headers: headers), &(block || @block))
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def self.responsify(maybe_a_url)
|
|
76
|
+
if maybe_a_url.is_a? RestClient::Response
|
|
77
|
+
maybe_a_url
|
|
78
|
+
else
|
|
79
|
+
RestClient.get(maybe_a_url, akamai_debug_headers)
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def self.request_cache_miss(url)
|
|
84
|
+
url += url.include?('?') ? '&' : '?'
|
|
85
|
+
url += SecureRandom.hex
|
|
86
|
+
RestClient.get(url, akamai_debug_headers)
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
end
|
data/lib/akamai_rspec.rb
ADDED
metadata
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: akamai_rspec
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.2.1
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Bianca Gibson
|
|
8
|
+
autorequire:
|
|
9
|
+
bindir: bin
|
|
10
|
+
cert_chain: []
|
|
11
|
+
date: 2015-07-19 00:00:00.000000000 Z
|
|
12
|
+
dependencies:
|
|
13
|
+
- !ruby/object:Gem::Dependency
|
|
14
|
+
name: rest-client
|
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
|
16
|
+
requirements:
|
|
17
|
+
- - ~>
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: '1.7'
|
|
20
|
+
type: :runtime
|
|
21
|
+
prerelease: false
|
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
23
|
+
requirements:
|
|
24
|
+
- - ~>
|
|
25
|
+
- !ruby/object:Gem::Version
|
|
26
|
+
version: '1.7'
|
|
27
|
+
- !ruby/object:Gem::Dependency
|
|
28
|
+
name: json
|
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
|
30
|
+
requirements:
|
|
31
|
+
- - ~>
|
|
32
|
+
- !ruby/object:Gem::Version
|
|
33
|
+
version: '1.8'
|
|
34
|
+
type: :runtime
|
|
35
|
+
prerelease: false
|
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
37
|
+
requirements:
|
|
38
|
+
- - ~>
|
|
39
|
+
- !ruby/object:Gem::Version
|
|
40
|
+
version: '1.8'
|
|
41
|
+
- !ruby/object:Gem::Dependency
|
|
42
|
+
name: rspec
|
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
|
44
|
+
requirements:
|
|
45
|
+
- - ~>
|
|
46
|
+
- !ruby/object:Gem::Version
|
|
47
|
+
version: '3.2'
|
|
48
|
+
type: :runtime
|
|
49
|
+
prerelease: false
|
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
51
|
+
requirements:
|
|
52
|
+
- - ~>
|
|
53
|
+
- !ruby/object:Gem::Version
|
|
54
|
+
version: '3.2'
|
|
55
|
+
description:
|
|
56
|
+
email: bianca.gibson@rea-group.com
|
|
57
|
+
executables: []
|
|
58
|
+
extensions: []
|
|
59
|
+
extra_rdoc_files: []
|
|
60
|
+
files:
|
|
61
|
+
- lib/akamai_rspec.rb
|
|
62
|
+
- lib/akamai_rspec/akamai_headers.rb
|
|
63
|
+
- lib/akamai_rspec/matchers/caching.rb
|
|
64
|
+
- lib/akamai_rspec/matchers/honour_origin_headers.rb
|
|
65
|
+
- lib/akamai_rspec/matchers/matchers.rb
|
|
66
|
+
- lib/akamai_rspec/matchers/non_akamai.rb
|
|
67
|
+
- lib/akamai_rspec/matchers/redirects.rb
|
|
68
|
+
- lib/akamai_rspec/request.rb
|
|
69
|
+
homepage:
|
|
70
|
+
licenses: []
|
|
71
|
+
metadata: {}
|
|
72
|
+
post_install_message:
|
|
73
|
+
rdoc_options: []
|
|
74
|
+
require_paths:
|
|
75
|
+
- lib
|
|
76
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
77
|
+
requirements:
|
|
78
|
+
- - '>='
|
|
79
|
+
- !ruby/object:Gem::Version
|
|
80
|
+
version: '0'
|
|
81
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
82
|
+
requirements:
|
|
83
|
+
- - '>='
|
|
84
|
+
- !ruby/object:Gem::Version
|
|
85
|
+
version: '0'
|
|
86
|
+
requirements: []
|
|
87
|
+
rubyforge_project:
|
|
88
|
+
rubygems_version: 2.1.11
|
|
89
|
+
signing_key:
|
|
90
|
+
specification_version: 4
|
|
91
|
+
summary: Test your akamai configuration with rspec
|
|
92
|
+
test_files: []
|