http 0.7.4 → 0.8.0.pre

Sign up to get free protection for your applications and to get access to all the features.
Files changed (73) hide show
  1. checksums.yaml +4 -4
  2. data/.rspec +0 -1
  3. data/.rubocop.yml +5 -2
  4. data/CHANGES.md +24 -7
  5. data/CONTRIBUTING.md +25 -0
  6. data/Gemfile +24 -22
  7. data/Guardfile +2 -2
  8. data/README.md +34 -4
  9. data/Rakefile +7 -7
  10. data/examples/parallel_requests_with_celluloid.rb +2 -2
  11. data/http.gemspec +12 -12
  12. data/lib/http.rb +11 -10
  13. data/lib/http/cache.rb +146 -0
  14. data/lib/http/cache/headers.rb +100 -0
  15. data/lib/http/cache/null_cache.rb +13 -0
  16. data/lib/http/chainable.rb +14 -3
  17. data/lib/http/client.rb +64 -80
  18. data/lib/http/connection.rb +139 -0
  19. data/lib/http/content_type.rb +2 -2
  20. data/lib/http/errors.rb +7 -1
  21. data/lib/http/headers.rb +21 -8
  22. data/lib/http/headers/mixin.rb +1 -1
  23. data/lib/http/mime_type.rb +2 -2
  24. data/lib/http/mime_type/adapter.rb +2 -2
  25. data/lib/http/mime_type/json.rb +4 -4
  26. data/lib/http/options.rb +65 -74
  27. data/lib/http/redirector.rb +3 -3
  28. data/lib/http/request.rb +20 -13
  29. data/lib/http/request/caching.rb +95 -0
  30. data/lib/http/request/writer.rb +5 -5
  31. data/lib/http/response.rb +15 -9
  32. data/lib/http/response/body.rb +21 -8
  33. data/lib/http/response/caching.rb +142 -0
  34. data/lib/http/response/io_body.rb +63 -0
  35. data/lib/http/response/parser.rb +1 -1
  36. data/lib/http/response/status.rb +4 -12
  37. data/lib/http/response/status/reasons.rb +53 -53
  38. data/lib/http/response/string_body.rb +53 -0
  39. data/lib/http/version.rb +1 -1
  40. data/spec/lib/http/cache/headers_spec.rb +77 -0
  41. data/spec/lib/http/cache_spec.rb +182 -0
  42. data/spec/lib/http/client_spec.rb +123 -95
  43. data/spec/lib/http/content_type_spec.rb +25 -25
  44. data/spec/lib/http/headers/mixin_spec.rb +8 -8
  45. data/spec/lib/http/headers_spec.rb +213 -173
  46. data/spec/lib/http/options/body_spec.rb +5 -5
  47. data/spec/lib/http/options/form_spec.rb +3 -3
  48. data/spec/lib/http/options/headers_spec.rb +7 -7
  49. data/spec/lib/http/options/json_spec.rb +3 -3
  50. data/spec/lib/http/options/merge_spec.rb +26 -22
  51. data/spec/lib/http/options/new_spec.rb +10 -10
  52. data/spec/lib/http/options/proxy_spec.rb +8 -8
  53. data/spec/lib/http/options_spec.rb +2 -2
  54. data/spec/lib/http/redirector_spec.rb +32 -32
  55. data/spec/lib/http/request/caching_spec.rb +133 -0
  56. data/spec/lib/http/request/writer_spec.rb +26 -26
  57. data/spec/lib/http/request_spec.rb +63 -58
  58. data/spec/lib/http/response/body_spec.rb +13 -13
  59. data/spec/lib/http/response/caching_spec.rb +201 -0
  60. data/spec/lib/http/response/io_body_spec.rb +35 -0
  61. data/spec/lib/http/response/status_spec.rb +25 -25
  62. data/spec/lib/http/response/string_body_spec.rb +35 -0
  63. data/spec/lib/http/response_spec.rb +64 -45
  64. data/spec/lib/http_spec.rb +103 -76
  65. data/spec/spec_helper.rb +10 -12
  66. data/spec/support/connection_reuse_shared.rb +100 -0
  67. data/spec/support/create_certs.rb +12 -12
  68. data/spec/support/dummy_server.rb +11 -11
  69. data/spec/support/dummy_server/servlet.rb +43 -31
  70. data/spec/support/proxy_server.rb +31 -25
  71. metadata +57 -8
  72. data/spec/support/example_server.rb +0 -30
  73. data/spec/support/example_server/servlet.rb +0 -102
@@ -1,13 +1,13 @@
1
- RSpec.describe HTTP::Options, 'body' do
1
+ RSpec.describe HTTP::Options, "body" do
2
2
  let(:opts) { HTTP::Options.new }
3
3
 
4
- it 'defaults to nil' do
4
+ it "defaults to nil" do
5
5
  expect(opts.body).to be nil
6
6
  end
7
7
 
8
- it 'may be specified with with_body' do
9
- opts2 = opts.with_body('foo')
8
+ it "may be specified with with_body" do
9
+ opts2 = opts.with_body("foo")
10
10
  expect(opts.body).to be nil
11
- expect(opts2.body).to eq('foo')
11
+ expect(opts2.body).to eq("foo")
12
12
  end
13
13
  end
@@ -1,11 +1,11 @@
1
- RSpec.describe HTTP::Options, 'form' do
1
+ RSpec.describe HTTP::Options, "form" do
2
2
  let(:opts) { HTTP::Options.new }
3
3
 
4
- it 'defaults to nil' do
4
+ it "defaults to nil" do
5
5
  expect(opts.form).to be nil
6
6
  end
7
7
 
8
- it 'may be specified with with_form_data' do
8
+ it "may be specified with with_form_data" do
9
9
  opts2 = opts.with_form(:foo => 42)
10
10
  expect(opts.form).to be nil
11
11
  expect(opts2.form).to eq(:foo => 42)
@@ -1,18 +1,18 @@
1
- RSpec.describe HTTP::Options, 'headers' do
1
+ RSpec.describe HTTP::Options, "headers" do
2
2
  let(:opts) { HTTP::Options.new }
3
3
 
4
- it 'defaults to be empty' do
4
+ it "defaults to be empty" do
5
5
  expect(opts.headers).to be_empty
6
6
  end
7
7
 
8
- it 'may be specified with with_headers' do
9
- opts2 = opts.with_headers('accept' => 'json')
8
+ it "may be specified with with_headers" do
9
+ opts2 = opts.with_headers("accept" => "json")
10
10
  expect(opts.headers).to be_empty
11
11
  expect(opts2.headers).to eq([%w(Accept json)])
12
12
  end
13
13
 
14
- it 'accepts any object that respond to :to_hash' do
15
- x = Struct.new(:to_hash).new('accept' => 'json')
16
- expect(opts.with_headers(x).headers['accept']).to eq('json')
14
+ it "accepts any object that respond to :to_hash" do
15
+ x = Struct.new(:to_hash).new("accept" => "json")
16
+ expect(opts.with_headers(x).headers["accept"]).to eq("json")
17
17
  end
18
18
  end
@@ -1,11 +1,11 @@
1
- RSpec.describe HTTP::Options, 'json' do
1
+ RSpec.describe HTTP::Options, "json" do
2
2
  let(:opts) { HTTP::Options.new }
3
3
 
4
- it 'defaults to nil' do
4
+ it "defaults to nil" do
5
5
  expect(opts.json).to be nil
6
6
  end
7
7
 
8
- it 'may be specified with with_json data' do
8
+ it "may be specified with with_json data" do
9
9
  opts2 = opts.with_json(:foo => 42)
10
10
  expect(opts.json).to be nil
11
11
  expect(opts2.json).to eq(:foo => 42)
@@ -1,49 +1,53 @@
1
- RSpec.describe HTTP::Options, 'merge' do
1
+
2
+ RSpec.describe HTTP::Options, "merge" do
2
3
  let(:opts) { HTTP::Options.new }
3
4
 
4
- it 'supports a Hash' do
5
+ it "supports a Hash" do
5
6
  old_response = opts.response
6
7
  expect(opts.merge(:response => :body).response).to eq(:body)
7
8
  expect(opts.response).to eq(old_response)
8
9
  end
9
10
 
10
- it 'supports another Options' do
11
+ it "supports another Options" do
11
12
  merged = opts.merge(HTTP::Options.new(:response => :body))
12
13
  expect(merged.response).to eq(:body)
13
14
  end
14
15
 
15
- it 'merges as excepted in complex cases' do
16
+ it "merges as excepted in complex cases" do
16
17
  # FIXME: yuck :(
17
18
 
18
19
  foo = HTTP::Options.new(
19
20
  :response => :body,
20
- :params => {:baz => 'bar'},
21
- :form => {:foo => 'foo'},
22
- :body => 'body-foo',
23
- :json => {:foo => 'foo'},
24
- :headers => {:accept => 'json', :foo => 'foo'},
21
+ :params => {:baz => "bar"},
22
+ :form => {:foo => "foo"},
23
+ :body => "body-foo",
24
+ :json => {:foo => "foo"},
25
+ :headers => {:accept => "json", :foo => "foo"},
25
26
  :proxy => {})
26
27
 
27
28
  bar = HTTP::Options.new(
28
29
  :response => :parsed_body,
29
- :params => {:plop => 'plip'},
30
- :form => {:bar => 'bar'},
31
- :body => 'body-bar',
32
- :json => {:bar => 'bar'},
33
- :headers => {:accept => 'xml', :bar => 'bar'},
34
- :proxy => {:proxy_address => '127.0.0.1', :proxy_port => 8080})
30
+ :persistent => "https://www.googe.com",
31
+ :params => {:plop => "plip"},
32
+ :form => {:bar => "bar"},
33
+ :body => "body-bar",
34
+ :json => {:bar => "bar"},
35
+ :headers => {:accept => "xml", :bar => "bar"},
36
+ :proxy => {:proxy_address => "127.0.0.1", :proxy_port => 8080})
35
37
 
36
38
  expect(foo.merge(bar).to_hash).to eq(
37
39
  :response => :parsed_body,
38
- :params => {:plop => 'plip'},
39
- :form => {:bar => 'bar'},
40
- :body => 'body-bar',
41
- :json => {:bar => 'bar'},
42
- :headers => {'Accept' => 'xml', 'Foo' => 'foo', 'Bar' => 'bar'},
43
- :proxy => {:proxy_address => '127.0.0.1', :proxy_port => 8080},
40
+ :params => {:plop => "plip"},
41
+ :form => {:bar => "bar"},
42
+ :body => "body-bar",
43
+ :json => {:bar => "bar"},
44
+ :persistent => "https://www.googe.com",
45
+ :headers => {"Foo" => "foo", "Accept" => "xml", "Bar" => "bar"},
46
+ :proxy => {:proxy_address => "127.0.0.1", :proxy_port => 8080},
44
47
  :follow => nil,
45
48
  :socket_class => described_class.default_socket_class,
46
49
  :ssl_socket_class => described_class.default_ssl_socket_class,
47
- :ssl_context => nil)
50
+ :ssl_context => nil,
51
+ :cache => described_class.default_cache)
48
52
  end
49
53
  end
@@ -1,26 +1,26 @@
1
- RSpec.describe HTTP::Options, 'new' do
2
- it 'supports a Options instance' do
1
+ RSpec.describe HTTP::Options, "new" do
2
+ it "supports a Options instance" do
3
3
  opts = HTTP::Options.new
4
4
  expect(HTTP::Options.new(opts)).to eq(opts)
5
5
  end
6
6
 
7
- context 'with a Hash' do
8
- it 'coerces :response correctly' do
7
+ context "with a Hash" do
8
+ it "coerces :response correctly" do
9
9
  opts = HTTP::Options.new(:response => :object)
10
10
  expect(opts.response).to eq(:object)
11
11
  end
12
12
 
13
- it 'coerces :headers correctly' do
14
- opts = HTTP::Options.new(:headers => {:accept => 'json'})
13
+ it "coerces :headers correctly" do
14
+ opts = HTTP::Options.new(:headers => {:accept => "json"})
15
15
  expect(opts.headers).to eq([%w(Accept json)])
16
16
  end
17
17
 
18
- it 'coerces :proxy correctly' do
19
- opts = HTTP::Options.new(:proxy => {:proxy_address => '127.0.0.1', :proxy_port => 8080})
20
- expect(opts.proxy).to eq(:proxy_address => '127.0.0.1', :proxy_port => 8080)
18
+ it "coerces :proxy correctly" do
19
+ opts = HTTP::Options.new(:proxy => {:proxy_address => "127.0.0.1", :proxy_port => 8080})
20
+ expect(opts.proxy).to eq(:proxy_address => "127.0.0.1", :proxy_port => 8080)
21
21
  end
22
22
 
23
- it 'coerces :form correctly' do
23
+ it "coerces :form correctly" do
24
24
  opts = HTTP::Options.new(:form => {:foo => 42})
25
25
  expect(opts.form).to eq(:foo => 42)
26
26
  end
@@ -1,18 +1,18 @@
1
- RSpec.describe HTTP::Options, 'proxy' do
1
+ RSpec.describe HTTP::Options, "proxy" do
2
2
  let(:opts) { HTTP::Options.new }
3
3
 
4
- it 'defaults to {}' do
4
+ it "defaults to {}" do
5
5
  expect(opts.proxy).to eq({})
6
6
  end
7
7
 
8
- it 'may be specified with with_proxy' do
9
- opts2 = opts.with_proxy(:proxy_address => '127.0.0.1', :proxy_port => 8080)
8
+ it "may be specified with with_proxy" do
9
+ opts2 = opts.with_proxy(:proxy_address => "127.0.0.1", :proxy_port => 8080)
10
10
  expect(opts.proxy).to eq({})
11
- expect(opts2.proxy).to eq(:proxy_address => '127.0.0.1', :proxy_port => 8080)
11
+ expect(opts2.proxy).to eq(:proxy_address => "127.0.0.1", :proxy_port => 8080)
12
12
  end
13
13
 
14
- it 'accepts proxy address, port, username, and password' do
15
- opts2 = opts.with_proxy(:proxy_address => '127.0.0.1', :proxy_port => 8080, :proxy_username => 'username', :proxy_password => 'password')
16
- expect(opts2.proxy).to eq(:proxy_address => '127.0.0.1', :proxy_port => 8080, :proxy_username => 'username', :proxy_password => 'password')
14
+ it "accepts proxy address, port, username, and password" do
15
+ opts2 = opts.with_proxy(:proxy_address => "127.0.0.1", :proxy_port => 8080, :proxy_username => "username", :proxy_password => "password")
16
+ expect(opts2.proxy).to eq(:proxy_address => "127.0.0.1", :proxy_port => 8080, :proxy_username => "username", :proxy_password => "password")
17
17
  end
18
18
  end
@@ -1,12 +1,12 @@
1
1
  RSpec.describe HTTP::Options do
2
2
  subject { described_class.new(:response => :body) }
3
3
 
4
- it 'behaves like a Hash for reading' do
4
+ it "behaves like a Hash for reading" do
5
5
  expect(subject[:response]).to eq(:body)
6
6
  expect(subject[:nosuchone]).to be nil
7
7
  end
8
8
 
9
- it 'coerces to a Hash' do
9
+ it "coerces to a Hash" do
10
10
  expect(subject.to_hash).to be_a(Hash)
11
11
  end
12
12
  end
@@ -1,20 +1,20 @@
1
1
  RSpec.describe HTTP::Redirector do
2
- def simple_response(status, body = '', headers = {})
3
- HTTP::Response.new(status, '1.1', headers, body)
2
+ def simple_response(status, body = "", headers = {})
3
+ HTTP::Response.new(status, "1.1", headers, body)
4
4
  end
5
5
 
6
6
  def redirect_response(location, status)
7
- simple_response status, '', 'Location' => location
7
+ simple_response status, "", "Location" => location
8
8
  end
9
9
 
10
10
  let(:max_hops) { 5 }
11
11
  subject(:redirector) { described_class.new max_hops }
12
12
 
13
- context 'following 300 redirect' do
14
- let(:orig_request) { HTTP::Request.new :post, 'http://www.example.com/' }
15
- let(:orig_response) { redirect_response 'http://example.com/', 300 }
13
+ context "following 300 redirect" do
14
+ let(:orig_request) { HTTP::Request.new :post, "http://www.example.com/" }
15
+ let(:orig_response) { redirect_response "http://example.com/", 300 }
16
16
 
17
- it 'follows without changing verb' do
17
+ it "follows without changing verb" do
18
18
  redirector.perform(orig_request, orig_response) do |request|
19
19
  expect(request.verb).to be orig_request.verb
20
20
  simple_response 200
@@ -22,11 +22,11 @@ RSpec.describe HTTP::Redirector do
22
22
  end
23
23
  end
24
24
 
25
- context 'following 301 redirect' do
26
- let(:orig_request) { HTTP::Request.new :post, 'http://www.example.com/' }
27
- let(:orig_response) { redirect_response 'http://example.com/', 301 }
25
+ context "following 301 redirect" do
26
+ let(:orig_request) { HTTP::Request.new :post, "http://www.example.com/" }
27
+ let(:orig_response) { redirect_response "http://example.com/", 301 }
28
28
 
29
- it 'follows without changing verb' do
29
+ it "follows without changing verb" do
30
30
  redirector.perform(orig_request, orig_response) do |request|
31
31
  expect(request.verb).to be orig_request.verb
32
32
  simple_response 200
@@ -34,11 +34,11 @@ RSpec.describe HTTP::Redirector do
34
34
  end
35
35
  end
36
36
 
37
- context 'following 302 redirect' do
38
- let(:orig_request) { HTTP::Request.new :post, 'http://www.example.com/' }
39
- let(:orig_response) { redirect_response 'http://example.com/', 302 }
37
+ context "following 302 redirect" do
38
+ let(:orig_request) { HTTP::Request.new :post, "http://www.example.com/" }
39
+ let(:orig_response) { redirect_response "http://example.com/", 302 }
40
40
 
41
- it 'follows without changing verb' do
41
+ it "follows without changing verb" do
42
42
  redirector.perform(orig_request, orig_response) do |request|
43
43
  expect(request.verb).to be orig_request.verb
44
44
  simple_response 200
@@ -46,12 +46,12 @@ RSpec.describe HTTP::Redirector do
46
46
  end
47
47
  end
48
48
 
49
- context 'following 303 redirect' do
50
- context 'upon POST request' do
51
- let(:orig_request) { HTTP::Request.new :post, 'http://www.example.com/' }
52
- let(:orig_response) { redirect_response 'http://example.com/', 303 }
49
+ context "following 303 redirect" do
50
+ context "upon POST request" do
51
+ let(:orig_request) { HTTP::Request.new :post, "http://www.example.com/" }
52
+ let(:orig_response) { redirect_response "http://example.com/", 303 }
53
53
 
54
- it 'follows without changing verb' do
54
+ it "follows without changing verb" do
55
55
  redirector.perform(orig_request, orig_response) do |request|
56
56
  expect(request.verb).to be :get
57
57
  simple_response 200
@@ -59,11 +59,11 @@ RSpec.describe HTTP::Redirector do
59
59
  end
60
60
  end
61
61
 
62
- context 'upon HEAD request' do
63
- let(:orig_request) { HTTP::Request.new :head, 'http://www.example.com/' }
64
- let(:orig_response) { redirect_response 'http://example.com/', 303 }
62
+ context "upon HEAD request" do
63
+ let(:orig_request) { HTTP::Request.new :head, "http://www.example.com/" }
64
+ let(:orig_response) { redirect_response "http://example.com/", 303 }
65
65
 
66
- it 'follows without changing verb' do
66
+ it "follows without changing verb" do
67
67
  redirector.perform(orig_request, orig_response) do |request|
68
68
  expect(request.verb).to be :get
69
69
  simple_response 200
@@ -72,11 +72,11 @@ RSpec.describe HTTP::Redirector do
72
72
  end
73
73
  end
74
74
 
75
- context 'following 307 redirect' do
76
- let(:orig_request) { HTTP::Request.new :post, 'http://www.example.com/' }
77
- let(:orig_response) { redirect_response 'http://example.com/', 307 }
75
+ context "following 307 redirect" do
76
+ let(:orig_request) { HTTP::Request.new :post, "http://www.example.com/" }
77
+ let(:orig_response) { redirect_response "http://example.com/", 307 }
78
78
 
79
- it 'follows without changing verb' do
79
+ it "follows without changing verb" do
80
80
  redirector.perform(orig_request, orig_response) do |request|
81
81
  expect(request.verb).to be orig_request.verb
82
82
  simple_response 200
@@ -84,11 +84,11 @@ RSpec.describe HTTP::Redirector do
84
84
  end
85
85
  end
86
86
 
87
- context 'following 308 redirect' do
88
- let(:orig_request) { HTTP::Request.new :post, 'http://www.example.com/' }
89
- let(:orig_response) { redirect_response 'http://example.com/', 308 }
87
+ context "following 308 redirect" do
88
+ let(:orig_request) { HTTP::Request.new :post, "http://www.example.com/" }
89
+ let(:orig_response) { redirect_response "http://example.com/", 308 }
90
90
 
91
- it 'follows without changing verb' do
91
+ it "follows without changing verb" do
92
92
  redirector.perform(orig_request, orig_response) do |request|
93
93
  expect(request.verb).to be orig_request.verb
94
94
  simple_response 200
@@ -0,0 +1,133 @@
1
+ RSpec.describe HTTP::Request::Caching do
2
+ let(:request) { HTTP::Request.new(:get, "http://example.com/") }
3
+
4
+ subject(:caching_request) { described_class.new request }
5
+
6
+ describe "#cache_headers" do
7
+ subject { caching_request.cache_headers }
8
+ it { is_expected.to be_a HTTP::Cache::Headers }
9
+ end
10
+
11
+ context "basic GET request" do
12
+ it "is cacheable" do
13
+ expect(subject.cacheable?).to be_truthy
14
+ end
15
+
16
+ it "does not invalidate cache" do
17
+ expect(subject.invalidates_cache?).to be_falsy
18
+ end
19
+
20
+ it "does not skip cache" do
21
+ expect(subject.skips_cache?).to be_falsy
22
+ end
23
+
24
+ it "can construct a new conditional version of itself based on a caching response" do
25
+ mod_date = Time.now.httpdate
26
+ headers = {"Etag" => "foo", "Last-Modified" => mod_date}
27
+ cached_resp = HTTP::Response.new(200, "http/1.1", headers, "")
28
+ cond_req = subject.conditional_on_changes_to(cached_resp)
29
+
30
+ expect(cond_req.headers["If-None-Match"]).to eq "foo"
31
+ expect(cond_req.headers["If-Modified-Since"]).to eq mod_date
32
+ end
33
+ end
34
+
35
+ context "GET request w/ must-revalidate" do
36
+ let(:request) do
37
+ headers = {"cache-control" => "must-revalidate"}
38
+ HTTP::Request.new(:get, "http://example.com/", headers)
39
+ end
40
+
41
+ it "is cacheable" do
42
+ expect(subject.cacheable?).to be_truthy
43
+ end
44
+
45
+ it "does not invalidate cache" do
46
+ expect(subject.invalidates_cache?).to be_falsy
47
+ end
48
+
49
+ it "does not skip cache" do
50
+ expect(subject.skips_cache?).to be_truthy
51
+ end
52
+
53
+ it "can construct a condition version of itself based on a caching response" do
54
+ mod_date = Time.now.httpdate
55
+ headers = {"Etag" => "foo", "Last-Modified" => mod_date}
56
+ cached_resp = HTTP::Response.new(200, "http/1.1", headers, "")
57
+ cond_req = subject.conditional_on_changes_to(cached_resp)
58
+
59
+ expect(cond_req.headers["If-None-Match"]).to eq "foo"
60
+ expect(cond_req.headers["If-Modified-Since"]).to eq mod_date
61
+ expect(cond_req.cache_headers.max_age).to eq 0
62
+ end
63
+ end
64
+
65
+ context "basic POST request" do
66
+ let(:request) { HTTP::Request.new(:post, "http://example.com/") }
67
+
68
+ it "is cacheable" do
69
+ expect(subject.cacheable?).to be_falsy
70
+ end
71
+
72
+ it "does not invalidate cache" do
73
+ expect(subject.invalidates_cache?).to be_truthy
74
+ end
75
+
76
+ it "does not skip cache" do
77
+ expect(subject.skips_cache?).to be_falsy
78
+ end
79
+ end
80
+
81
+ context "basic PUT request" do
82
+ let(:request) { HTTP::Request.new(:put, "http://example.com/") }
83
+
84
+ it "is cacheable" do
85
+ expect(subject.cacheable?).to be_falsy
86
+ end
87
+
88
+ it "does not invalidate cache" do
89
+ expect(subject.invalidates_cache?).to be_truthy
90
+ end
91
+
92
+ it "does not skip cache" do
93
+ expect(subject.skips_cache?).to be_falsy
94
+ end
95
+ end
96
+
97
+ context "basic delete request" do
98
+ let(:request) { HTTP::Request.new(:delete, "http://example.com/") }
99
+
100
+ it "is cacheable" do
101
+ expect(subject.cacheable?).to be_falsy
102
+ end
103
+
104
+ it "does not invalidate cache" do
105
+ expect(subject.invalidates_cache?).to be_truthy
106
+ end
107
+
108
+ it "does not skip cache" do
109
+ expect(subject.skips_cache?).to be_falsy
110
+ end
111
+ end
112
+
113
+ context "basic patch request" do
114
+ let(:request) { HTTP::Request.new(:patch, "http://example.com/") }
115
+
116
+ it "is cacheable" do
117
+ expect(subject.cacheable?).to be_falsy
118
+ end
119
+
120
+ it "does not invalidate cache" do
121
+ expect(subject.invalidates_cache?).to be_truthy
122
+ end
123
+
124
+ it "does not skip cache" do
125
+ expect(subject.skips_cache?).to be_falsy
126
+ end
127
+ end
128
+
129
+ describe "#caching" do
130
+ subject(:caching_request) { request.caching }
131
+ it { is_expected.to be caching_request }
132
+ end
133
+ end