http 0.7.4 → 0.8.0.pre
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 +4 -4
- data/.rspec +0 -1
- data/.rubocop.yml +5 -2
- data/CHANGES.md +24 -7
- data/CONTRIBUTING.md +25 -0
- data/Gemfile +24 -22
- data/Guardfile +2 -2
- data/README.md +34 -4
- data/Rakefile +7 -7
- data/examples/parallel_requests_with_celluloid.rb +2 -2
- data/http.gemspec +12 -12
- data/lib/http.rb +11 -10
- data/lib/http/cache.rb +146 -0
- data/lib/http/cache/headers.rb +100 -0
- data/lib/http/cache/null_cache.rb +13 -0
- data/lib/http/chainable.rb +14 -3
- data/lib/http/client.rb +64 -80
- data/lib/http/connection.rb +139 -0
- data/lib/http/content_type.rb +2 -2
- data/lib/http/errors.rb +7 -1
- data/lib/http/headers.rb +21 -8
- data/lib/http/headers/mixin.rb +1 -1
- data/lib/http/mime_type.rb +2 -2
- data/lib/http/mime_type/adapter.rb +2 -2
- data/lib/http/mime_type/json.rb +4 -4
- data/lib/http/options.rb +65 -74
- data/lib/http/redirector.rb +3 -3
- data/lib/http/request.rb +20 -13
- data/lib/http/request/caching.rb +95 -0
- data/lib/http/request/writer.rb +5 -5
- data/lib/http/response.rb +15 -9
- data/lib/http/response/body.rb +21 -8
- data/lib/http/response/caching.rb +142 -0
- data/lib/http/response/io_body.rb +63 -0
- data/lib/http/response/parser.rb +1 -1
- data/lib/http/response/status.rb +4 -12
- data/lib/http/response/status/reasons.rb +53 -53
- data/lib/http/response/string_body.rb +53 -0
- data/lib/http/version.rb +1 -1
- data/spec/lib/http/cache/headers_spec.rb +77 -0
- data/spec/lib/http/cache_spec.rb +182 -0
- data/spec/lib/http/client_spec.rb +123 -95
- data/spec/lib/http/content_type_spec.rb +25 -25
- data/spec/lib/http/headers/mixin_spec.rb +8 -8
- data/spec/lib/http/headers_spec.rb +213 -173
- data/spec/lib/http/options/body_spec.rb +5 -5
- data/spec/lib/http/options/form_spec.rb +3 -3
- data/spec/lib/http/options/headers_spec.rb +7 -7
- data/spec/lib/http/options/json_spec.rb +3 -3
- data/spec/lib/http/options/merge_spec.rb +26 -22
- data/spec/lib/http/options/new_spec.rb +10 -10
- data/spec/lib/http/options/proxy_spec.rb +8 -8
- data/spec/lib/http/options_spec.rb +2 -2
- data/spec/lib/http/redirector_spec.rb +32 -32
- data/spec/lib/http/request/caching_spec.rb +133 -0
- data/spec/lib/http/request/writer_spec.rb +26 -26
- data/spec/lib/http/request_spec.rb +63 -58
- data/spec/lib/http/response/body_spec.rb +13 -13
- data/spec/lib/http/response/caching_spec.rb +201 -0
- data/spec/lib/http/response/io_body_spec.rb +35 -0
- data/spec/lib/http/response/status_spec.rb +25 -25
- data/spec/lib/http/response/string_body_spec.rb +35 -0
- data/spec/lib/http/response_spec.rb +64 -45
- data/spec/lib/http_spec.rb +103 -76
- data/spec/spec_helper.rb +10 -12
- data/spec/support/connection_reuse_shared.rb +100 -0
- data/spec/support/create_certs.rb +12 -12
- data/spec/support/dummy_server.rb +11 -11
- data/spec/support/dummy_server/servlet.rb +43 -31
- data/spec/support/proxy_server.rb +31 -25
- metadata +57 -8
- data/spec/support/example_server.rb +0 -30
- data/spec/support/example_server/servlet.rb +0 -102
@@ -1,45 +1,45 @@
|
|
1
1
|
RSpec.describe HTTP::ContentType do
|
2
|
-
describe
|
3
|
-
context
|
4
|
-
subject { described_class.parse
|
5
|
-
its(:mime_type) { is_expected.to eq
|
2
|
+
describe ".parse" do
|
3
|
+
context "with text/plain" do
|
4
|
+
subject { described_class.parse "text/plain" }
|
5
|
+
its(:mime_type) { is_expected.to eq "text/plain" }
|
6
6
|
its(:charset) { is_expected.to be_nil }
|
7
7
|
end
|
8
8
|
|
9
|
-
context
|
10
|
-
subject { described_class.parse
|
11
|
-
its(:mime_type) { is_expected.to eq
|
9
|
+
context "with tEXT/plaIN" do
|
10
|
+
subject { described_class.parse "tEXT/plaIN" }
|
11
|
+
its(:mime_type) { is_expected.to eq "text/plain" }
|
12
12
|
its(:charset) { is_expected.to be_nil }
|
13
13
|
end
|
14
14
|
|
15
|
-
context
|
16
|
-
subject { described_class.parse
|
17
|
-
its(:mime_type) { is_expected.to eq
|
18
|
-
its(:charset) { is_expected.to eq
|
15
|
+
context "with text/plain; charset=utf-8" do
|
16
|
+
subject { described_class.parse "text/plain; charset=utf-8" }
|
17
|
+
its(:mime_type) { is_expected.to eq "text/plain" }
|
18
|
+
its(:charset) { is_expected.to eq "utf-8" }
|
19
19
|
end
|
20
20
|
|
21
21
|
context 'with text/plain; charset="utf-8"' do
|
22
22
|
subject { described_class.parse 'text/plain; charset="utf-8"' }
|
23
|
-
its(:mime_type) { is_expected.to eq
|
24
|
-
its(:charset) { is_expected.to eq
|
23
|
+
its(:mime_type) { is_expected.to eq "text/plain" }
|
24
|
+
its(:charset) { is_expected.to eq "utf-8" }
|
25
25
|
end
|
26
26
|
|
27
|
-
context
|
28
|
-
subject { described_class.parse
|
29
|
-
its(:mime_type) { is_expected.to eq
|
30
|
-
its(:charset) { is_expected.to eq
|
27
|
+
context "with text/plain; charSET=utf-8" do
|
28
|
+
subject { described_class.parse "text/plain; charSET=utf-8" }
|
29
|
+
its(:mime_type) { is_expected.to eq "text/plain" }
|
30
|
+
its(:charset) { is_expected.to eq "utf-8" }
|
31
31
|
end
|
32
32
|
|
33
|
-
context
|
34
|
-
subject { described_class.parse
|
35
|
-
its(:mime_type) { is_expected.to eq
|
36
|
-
its(:charset) { is_expected.to eq
|
33
|
+
context "with text/plain; foo=bar; charset=utf-8" do
|
34
|
+
subject { described_class.parse "text/plain; foo=bar; charset=utf-8" }
|
35
|
+
its(:mime_type) { is_expected.to eq "text/plain" }
|
36
|
+
its(:charset) { is_expected.to eq "utf-8" }
|
37
37
|
end
|
38
38
|
|
39
|
-
context
|
40
|
-
subject { described_class.parse
|
41
|
-
its(:mime_type) { is_expected.to eq
|
42
|
-
its(:charset) { is_expected.to eq
|
39
|
+
context "with text/plain;charset=utf-8;foo=bar" do
|
40
|
+
subject { described_class.parse "text/plain;charset=utf-8;foo=bar" }
|
41
|
+
its(:mime_type) { is_expected.to eq "text/plain" }
|
42
|
+
its(:charset) { is_expected.to eq "utf-8" }
|
43
43
|
end
|
44
44
|
end
|
45
45
|
end
|
@@ -12,23 +12,23 @@ RSpec.describe HTTP::Headers::Mixin do
|
|
12
12
|
let(:headers) { HTTP::Headers.new }
|
13
13
|
let(:dummy) { dummy_class.new headers }
|
14
14
|
|
15
|
-
describe
|
16
|
-
it
|
15
|
+
describe "#headers" do
|
16
|
+
it "returns @headers instance variable" do
|
17
17
|
expect(dummy.headers).to be headers
|
18
18
|
end
|
19
19
|
end
|
20
20
|
|
21
|
-
describe
|
22
|
-
it
|
21
|
+
describe "#[]" do
|
22
|
+
it "proxies to headers#[]" do
|
23
23
|
expect(headers).to receive(:[]).with(:accept)
|
24
24
|
dummy[:accept]
|
25
25
|
end
|
26
26
|
end
|
27
27
|
|
28
|
-
describe
|
29
|
-
it
|
30
|
-
expect(headers).to receive(:[]=).with(:accept,
|
31
|
-
dummy[:accept] =
|
28
|
+
describe "#[]=" do
|
29
|
+
it "proxies to headers#[]" do
|
30
|
+
expect(headers).to receive(:[]=).with(:accept, "text/plain")
|
31
|
+
dummy[:accept] = "text/plain"
|
32
32
|
end
|
33
33
|
end
|
34
34
|
end
|
@@ -1,189 +1,229 @@
|
|
1
1
|
RSpec.describe HTTP::Headers do
|
2
2
|
subject(:headers) { described_class.new }
|
3
3
|
|
4
|
-
it
|
4
|
+
it "is Enumerable" do
|
5
5
|
expect(headers).to be_an Enumerable
|
6
6
|
end
|
7
7
|
|
8
|
-
describe
|
9
|
-
it
|
10
|
-
headers.set
|
11
|
-
expect(headers[
|
8
|
+
describe "#set" do
|
9
|
+
it "sets header value" do
|
10
|
+
headers.set "Accept", "application/json"
|
11
|
+
expect(headers["Accept"]).to eq "application/json"
|
12
12
|
end
|
13
13
|
|
14
|
-
it
|
15
|
-
headers.set :content_type,
|
16
|
-
expect(headers[
|
14
|
+
it "normalizes header name" do
|
15
|
+
headers.set :content_type, "application/json"
|
16
|
+
expect(headers["Content-Type"]).to eq "application/json"
|
17
17
|
end
|
18
18
|
|
19
|
-
it
|
20
|
-
headers.set :set_cookie,
|
21
|
-
headers.set :set_cookie,
|
22
|
-
expect(headers[
|
19
|
+
it "overwrites previous value" do
|
20
|
+
headers.set :set_cookie, "hoo=ray"
|
21
|
+
headers.set :set_cookie, "woo=hoo"
|
22
|
+
expect(headers["Set-Cookie"]).to eq "woo=hoo"
|
23
23
|
end
|
24
24
|
|
25
|
-
it
|
26
|
-
headers.set :set_cookie,
|
25
|
+
it "allows set multiple values" do
|
26
|
+
headers.set :set_cookie, "hoo=ray"
|
27
27
|
headers.set :set_cookie, %w(hoo=ray woo=hoo)
|
28
|
-
expect(headers[
|
28
|
+
expect(headers["Set-Cookie"]).to eq %w(hoo=ray woo=hoo)
|
29
|
+
end
|
30
|
+
|
31
|
+
it "fails with empty header name" do
|
32
|
+
expect { headers.set "", "foo bar" }
|
33
|
+
.to raise_error HTTP::InvalidHeaderNameError
|
34
|
+
end
|
35
|
+
|
36
|
+
it "fails with invalid header name" do
|
37
|
+
expect { headers.set "foo bar", "baz" }
|
38
|
+
.to raise_error HTTP::InvalidHeaderNameError
|
29
39
|
end
|
30
40
|
end
|
31
41
|
|
32
|
-
describe
|
33
|
-
it
|
34
|
-
headers[
|
35
|
-
expect(headers[
|
42
|
+
describe "#[]=" do
|
43
|
+
it "sets header value" do
|
44
|
+
headers["Accept"] = "application/json"
|
45
|
+
expect(headers["Accept"]).to eq "application/json"
|
36
46
|
end
|
37
47
|
|
38
|
-
it
|
39
|
-
headers[:content_type] =
|
40
|
-
expect(headers[
|
48
|
+
it "normalizes header name" do
|
49
|
+
headers[:content_type] = "application/json"
|
50
|
+
expect(headers["Content-Type"]).to eq "application/json"
|
41
51
|
end
|
42
52
|
|
43
|
-
it
|
44
|
-
headers[:set_cookie] =
|
45
|
-
headers[:set_cookie] =
|
46
|
-
expect(headers[
|
53
|
+
it "overwrites previous value" do
|
54
|
+
headers[:set_cookie] = "hoo=ray"
|
55
|
+
headers[:set_cookie] = "woo=hoo"
|
56
|
+
expect(headers["Set-Cookie"]).to eq "woo=hoo"
|
47
57
|
end
|
48
58
|
|
49
|
-
it
|
50
|
-
headers[:set_cookie] =
|
59
|
+
it "allows set multiple values" do
|
60
|
+
headers[:set_cookie] = "hoo=ray"
|
51
61
|
headers[:set_cookie] = %w(hoo=ray woo=hoo)
|
52
|
-
expect(headers[
|
62
|
+
expect(headers["Set-Cookie"]).to eq %w(hoo=ray woo=hoo)
|
53
63
|
end
|
54
64
|
end
|
55
65
|
|
56
|
-
describe
|
57
|
-
before { headers.set
|
66
|
+
describe "#delete" do
|
67
|
+
before { headers.set "Content-Type", "application/json" }
|
58
68
|
|
59
|
-
it
|
60
|
-
headers.delete
|
61
|
-
expect(headers[
|
69
|
+
it "removes given header" do
|
70
|
+
headers.delete "Content-Type"
|
71
|
+
expect(headers["Content-Type"]).to be_nil
|
62
72
|
end
|
63
73
|
|
64
|
-
it
|
74
|
+
it "normalizes header name" do
|
65
75
|
headers.delete :content_type
|
66
|
-
expect(headers[
|
76
|
+
expect(headers["Content-Type"]).to be_nil
|
77
|
+
end
|
78
|
+
|
79
|
+
it "fails with empty header name" do
|
80
|
+
expect { headers.delete "" }
|
81
|
+
.to raise_error HTTP::InvalidHeaderNameError
|
82
|
+
end
|
83
|
+
|
84
|
+
it "fails with invalid header name" do
|
85
|
+
expect { headers.delete "foo bar" }
|
86
|
+
.to raise_error HTTP::InvalidHeaderNameError
|
67
87
|
end
|
68
88
|
end
|
69
89
|
|
70
|
-
describe
|
71
|
-
it
|
72
|
-
headers.add
|
73
|
-
expect(headers[
|
90
|
+
describe "#add" do
|
91
|
+
it "sets header value" do
|
92
|
+
headers.add "Accept", "application/json"
|
93
|
+
expect(headers["Accept"]).to eq "application/json"
|
74
94
|
end
|
75
95
|
|
76
|
-
it
|
77
|
-
headers.add :content_type,
|
78
|
-
expect(headers[
|
96
|
+
it "normalizes header name" do
|
97
|
+
headers.add :content_type, "application/json"
|
98
|
+
expect(headers["Content-Type"]).to eq "application/json"
|
79
99
|
end
|
80
100
|
|
81
|
-
it
|
82
|
-
headers.add :set_cookie,
|
83
|
-
headers.add :set_cookie,
|
84
|
-
expect(headers[
|
101
|
+
it "appends new value if header exists" do
|
102
|
+
headers.add :set_cookie, "hoo=ray"
|
103
|
+
headers.add :set_cookie, "woo=hoo"
|
104
|
+
expect(headers["Set-Cookie"]).to eq %w(hoo=ray woo=hoo)
|
85
105
|
end
|
86
106
|
|
87
|
-
it
|
88
|
-
headers.add :set_cookie,
|
107
|
+
it "allows append multiple values" do
|
108
|
+
headers.add :set_cookie, "hoo=ray"
|
89
109
|
headers.add :set_cookie, %w(woo=hoo yup=pie)
|
90
|
-
expect(headers[
|
110
|
+
expect(headers["Set-Cookie"]).to eq %w(hoo=ray woo=hoo yup=pie)
|
111
|
+
end
|
112
|
+
|
113
|
+
it "fails with empty header name" do
|
114
|
+
expect { headers.add "", "foobar" }
|
115
|
+
.to raise_error HTTP::InvalidHeaderNameError
|
116
|
+
end
|
117
|
+
|
118
|
+
it "fails with invalid header name" do
|
119
|
+
expect { headers.add "foo bar", "baz" }
|
120
|
+
.to raise_error HTTP::InvalidHeaderNameError
|
91
121
|
end
|
92
122
|
end
|
93
123
|
|
94
|
-
describe
|
95
|
-
before { headers.set
|
124
|
+
describe "#get" do
|
125
|
+
before { headers.set "Content-Type", "application/json" }
|
96
126
|
|
97
|
-
it
|
98
|
-
expect(headers.get
|
127
|
+
it "returns array of associated values" do
|
128
|
+
expect(headers.get "Content-Type").to eq %w(application/json)
|
99
129
|
end
|
100
130
|
|
101
|
-
it
|
131
|
+
it "normalizes header name" do
|
102
132
|
expect(headers.get :content_type).to eq %w(application/json)
|
103
133
|
end
|
104
134
|
|
105
|
-
context
|
106
|
-
it
|
135
|
+
context "when header does not exists" do
|
136
|
+
it "returns empty array" do
|
107
137
|
expect(headers.get :accept).to eq []
|
108
138
|
end
|
109
139
|
end
|
140
|
+
|
141
|
+
it "fails with empty header name" do
|
142
|
+
expect { headers.get "" }
|
143
|
+
.to raise_error HTTP::InvalidHeaderNameError
|
144
|
+
end
|
145
|
+
|
146
|
+
it "fails with invalid header name" do
|
147
|
+
expect { headers.get "foo bar" }
|
148
|
+
.to raise_error HTTP::InvalidHeaderNameError
|
149
|
+
end
|
110
150
|
end
|
111
151
|
|
112
|
-
describe
|
113
|
-
context
|
114
|
-
it
|
152
|
+
describe "#[]" do
|
153
|
+
context "when header does not exists" do
|
154
|
+
it "returns nil" do
|
115
155
|
expect(headers[:accept]).to be_nil
|
116
156
|
end
|
117
157
|
end
|
118
158
|
|
119
|
-
context
|
120
|
-
before { headers.set
|
159
|
+
context "when header has a single value" do
|
160
|
+
before { headers.set "Content-Type", "application/json" }
|
121
161
|
|
122
|
-
it
|
162
|
+
it "normalizes header name" do
|
123
163
|
expect(headers[:content_type]).to_not be_nil
|
124
164
|
end
|
125
165
|
|
126
|
-
it
|
127
|
-
expect(headers[:content_type]).to eq
|
166
|
+
it "returns it returns a single value" do
|
167
|
+
expect(headers[:content_type]).to eq "application/json"
|
128
168
|
end
|
129
169
|
end
|
130
170
|
|
131
|
-
context
|
171
|
+
context "when header has a multiple values" do
|
132
172
|
before do
|
133
|
-
headers.add :set_cookie,
|
134
|
-
headers.add :set_cookie,
|
173
|
+
headers.add :set_cookie, "hoo=ray"
|
174
|
+
headers.add :set_cookie, "woo=hoo"
|
135
175
|
end
|
136
176
|
|
137
|
-
it
|
177
|
+
it "normalizes header name" do
|
138
178
|
expect(headers[:set_cookie]).to_not be_nil
|
139
179
|
end
|
140
180
|
|
141
|
-
it
|
181
|
+
it "returns array of associated values" do
|
142
182
|
expect(headers[:set_cookie]).to eq %w(hoo=ray woo=hoo)
|
143
183
|
end
|
144
184
|
end
|
145
185
|
end
|
146
186
|
|
147
|
-
describe
|
187
|
+
describe "#to_h" do
|
148
188
|
before do
|
149
|
-
headers.add :content_type,
|
150
|
-
headers.add :set_cookie,
|
151
|
-
headers.add :set_cookie,
|
189
|
+
headers.add :content_type, "application/json"
|
190
|
+
headers.add :set_cookie, "hoo=ray"
|
191
|
+
headers.add :set_cookie, "woo=hoo"
|
152
192
|
end
|
153
193
|
|
154
|
-
it
|
194
|
+
it "returns a Hash" do
|
155
195
|
expect(headers.to_h).to be_a ::Hash
|
156
196
|
end
|
157
197
|
|
158
|
-
it
|
198
|
+
it "returns Hash with normalized keys" do
|
159
199
|
expect(headers.to_h.keys).to match_array %w(Content-Type Set-Cookie)
|
160
200
|
end
|
161
201
|
|
162
|
-
context
|
163
|
-
it
|
164
|
-
expect(headers.to_h[
|
202
|
+
context "for a header with single value" do
|
203
|
+
it "provides a value as is" do
|
204
|
+
expect(headers.to_h["Content-Type"]).to eq "application/json"
|
165
205
|
end
|
166
206
|
end
|
167
207
|
|
168
|
-
context
|
169
|
-
it
|
170
|
-
expect(headers.to_h[
|
208
|
+
context "for a header with multiple values" do
|
209
|
+
it "provides an array of values" do
|
210
|
+
expect(headers.to_h["Set-Cookie"]).to eq %w(hoo=ray woo=hoo)
|
171
211
|
end
|
172
212
|
end
|
173
213
|
end
|
174
214
|
|
175
|
-
describe
|
215
|
+
describe "#to_a" do
|
176
216
|
before do
|
177
|
-
headers.add :content_type,
|
178
|
-
headers.add :set_cookie,
|
179
|
-
headers.add :set_cookie,
|
217
|
+
headers.add :content_type, "application/json"
|
218
|
+
headers.add :set_cookie, "hoo=ray"
|
219
|
+
headers.add :set_cookie, "woo=hoo"
|
180
220
|
end
|
181
221
|
|
182
|
-
it
|
222
|
+
it "returns an Array" do
|
183
223
|
expect(headers.to_a).to be_a Array
|
184
224
|
end
|
185
225
|
|
186
|
-
it
|
226
|
+
it "returns Array of key/value pairs with normalized keys" do
|
187
227
|
expect(headers.to_a).to eq [
|
188
228
|
%w(Content-Type application/json),
|
189
229
|
%w(Set-Cookie hoo=ray),
|
@@ -192,41 +232,41 @@ RSpec.describe HTTP::Headers do
|
|
192
232
|
end
|
193
233
|
end
|
194
234
|
|
195
|
-
describe
|
235
|
+
describe "#inspect" do
|
196
236
|
before { headers.set :set_cookie, %w(hoo=ray woo=hoo) }
|
197
237
|
subject { headers.inspect }
|
198
238
|
|
199
239
|
it { is_expected.to eq '#<HTTP::Headers {"Set-Cookie"=>["hoo=ray", "woo=hoo"]}>' }
|
200
240
|
end
|
201
241
|
|
202
|
-
describe
|
242
|
+
describe "#keys" do
|
203
243
|
before do
|
204
|
-
headers.add :content_type,
|
205
|
-
headers.add :set_cookie,
|
206
|
-
headers.add :set_cookie,
|
244
|
+
headers.add :content_type, "application/json"
|
245
|
+
headers.add :set_cookie, "hoo=ray"
|
246
|
+
headers.add :set_cookie, "woo=hoo"
|
207
247
|
end
|
208
248
|
|
209
|
-
it
|
249
|
+
it "returns uniq keys only" do
|
210
250
|
expect(headers.keys.size).to eq 2
|
211
251
|
end
|
212
252
|
|
213
|
-
it
|
214
|
-
expect(headers.keys).to include(
|
253
|
+
it "normalizes keys" do
|
254
|
+
expect(headers.keys).to include("Content-Type", "Set-Cookie")
|
215
255
|
end
|
216
256
|
end
|
217
257
|
|
218
|
-
describe
|
258
|
+
describe "#each" do
|
219
259
|
before do
|
220
|
-
headers.add :set_cookie,
|
221
|
-
headers.add :content_type,
|
222
|
-
headers.add :set_cookie,
|
260
|
+
headers.add :set_cookie, "hoo=ray"
|
261
|
+
headers.add :content_type, "application/json"
|
262
|
+
headers.add :set_cookie, "woo=hoo"
|
223
263
|
end
|
224
264
|
|
225
|
-
it
|
265
|
+
it "yields each key/value pair separatedly" do
|
226
266
|
expect { |b| headers.each(&b) }.to yield_control.exactly(3).times
|
227
267
|
end
|
228
268
|
|
229
|
-
it
|
269
|
+
it "yields headers in the same order they were added" do
|
230
270
|
expect { |b| headers.each(&b) }.to yield_successive_args(
|
231
271
|
%w(Set-Cookie hoo=ray),
|
232
272
|
%w(Content-Type application/json),
|
@@ -234,30 +274,30 @@ RSpec.describe HTTP::Headers do
|
|
234
274
|
)
|
235
275
|
end
|
236
276
|
|
237
|
-
it
|
277
|
+
it "returns self instance if block given" do
|
238
278
|
expect(headers.each { |*| }).to be headers
|
239
279
|
end
|
240
280
|
|
241
|
-
it
|
281
|
+
it "returns Enumerator if no block given" do
|
242
282
|
expect(headers.each).to be_a Enumerator
|
243
283
|
end
|
244
284
|
end
|
245
285
|
|
246
|
-
describe
|
286
|
+
describe ".empty?" do
|
247
287
|
subject { headers.empty? }
|
248
288
|
|
249
|
-
context
|
289
|
+
context "initially" do
|
250
290
|
it { is_expected.to be true }
|
251
291
|
end
|
252
292
|
|
253
|
-
context
|
254
|
-
before { headers.add :accept,
|
293
|
+
context "when header exists" do
|
294
|
+
before { headers.add :accept, "text/plain" }
|
255
295
|
it { is_expected.to be false }
|
256
296
|
end
|
257
297
|
|
258
|
-
context
|
298
|
+
context "when last header was removed" do
|
259
299
|
before do
|
260
|
-
headers.add :accept,
|
300
|
+
headers.add :accept, "text/plain"
|
261
301
|
headers.delete :accept
|
262
302
|
end
|
263
303
|
|
@@ -265,154 +305,154 @@ RSpec.describe HTTP::Headers do
|
|
265
305
|
end
|
266
306
|
end
|
267
307
|
|
268
|
-
describe
|
308
|
+
describe "#hash" do
|
269
309
|
let(:left) { described_class.new }
|
270
310
|
let(:right) { described_class.new }
|
271
311
|
|
272
|
-
it
|
273
|
-
left.add :accept,
|
274
|
-
right.add :accept,
|
312
|
+
it "equals if two headers equals" do
|
313
|
+
left.add :accept, "text/plain"
|
314
|
+
right.add :accept, "text/plain"
|
275
315
|
|
276
316
|
expect(left.hash).to eq right.hash
|
277
317
|
end
|
278
318
|
end
|
279
319
|
|
280
|
-
describe
|
320
|
+
describe "#==" do
|
281
321
|
let(:left) { described_class.new }
|
282
322
|
let(:right) { described_class.new }
|
283
323
|
|
284
|
-
it
|
285
|
-
left.add :accept,
|
286
|
-
right.add :accept,
|
324
|
+
it "compares header keys and values" do
|
325
|
+
left.add :accept, "text/plain"
|
326
|
+
right.add :accept, "text/plain"
|
287
327
|
|
288
328
|
expect(left).to eq right
|
289
329
|
end
|
290
330
|
|
291
|
-
it
|
292
|
-
left.add :accept,
|
331
|
+
it "allows comparison with Array of key/value pairs" do
|
332
|
+
left.add :accept, "text/plain"
|
293
333
|
expect(left).to eq [%w(Accept text/plain)]
|
294
334
|
end
|
295
335
|
|
296
|
-
it
|
297
|
-
left.add :accept,
|
298
|
-
left.add :cookie,
|
299
|
-
right.add :cookie,
|
300
|
-
right.add :accept,
|
336
|
+
it "sensitive to headers order" do
|
337
|
+
left.add :accept, "text/plain"
|
338
|
+
left.add :cookie, "woo=hoo"
|
339
|
+
right.add :cookie, "woo=hoo"
|
340
|
+
right.add :accept, "text/plain"
|
301
341
|
|
302
342
|
expect(left).to_not eq right
|
303
343
|
end
|
304
344
|
|
305
|
-
it
|
306
|
-
left.add :cookie,
|
307
|
-
left.add :cookie,
|
308
|
-
right.add :cookie,
|
309
|
-
right.add :cookie,
|
345
|
+
it "sensitive to header values order" do
|
346
|
+
left.add :cookie, "hoo=ray"
|
347
|
+
left.add :cookie, "woo=hoo"
|
348
|
+
right.add :cookie, "woo=hoo"
|
349
|
+
right.add :cookie, "hoo=ray"
|
310
350
|
|
311
351
|
expect(left).to_not eq right
|
312
352
|
end
|
313
353
|
end
|
314
354
|
|
315
|
-
describe
|
316
|
-
before { headers.set :content_type,
|
355
|
+
describe "#dup" do
|
356
|
+
before { headers.set :content_type, "application/json" }
|
317
357
|
|
318
358
|
subject(:dupped) { headers.dup }
|
319
359
|
|
320
360
|
it { is_expected.to be_a described_class }
|
321
361
|
it { is_expected.not_to be headers }
|
322
362
|
|
323
|
-
it
|
324
|
-
expect(dupped[:content_type]).to eq
|
363
|
+
it "has headers copied" do
|
364
|
+
expect(dupped[:content_type]).to eq "application/json"
|
325
365
|
end
|
326
366
|
|
327
|
-
context
|
328
|
-
before { dupped.set :content_type,
|
367
|
+
context "modifying a copy" do
|
368
|
+
before { dupped.set :content_type, "text/plain" }
|
329
369
|
|
330
|
-
it
|
331
|
-
expect(dupped[:content_type]).to eq
|
370
|
+
it "modifies dupped copy" do
|
371
|
+
expect(dupped[:content_type]).to eq "text/plain"
|
332
372
|
end
|
333
373
|
|
334
|
-
it
|
335
|
-
expect(headers[:content_type]).to eq
|
374
|
+
it "does not affects original headers" do
|
375
|
+
expect(headers[:content_type]).to eq "application/json"
|
336
376
|
end
|
337
377
|
end
|
338
378
|
end
|
339
379
|
|
340
|
-
describe
|
380
|
+
describe "#merge!" do
|
341
381
|
before do
|
342
|
-
headers.set :host,
|
343
|
-
headers.set :accept,
|
344
|
-
headers.merge! :accept =>
|
382
|
+
headers.set :host, "example.com"
|
383
|
+
headers.set :accept, "application/json"
|
384
|
+
headers.merge! :accept => "plain/text", :cookie => %w(hoo=ray woo=hoo)
|
345
385
|
end
|
346
386
|
|
347
|
-
it
|
348
|
-
expect(headers[:host]).to eq
|
387
|
+
it "leaves headers not presented in other as is" do
|
388
|
+
expect(headers[:host]).to eq "example.com"
|
349
389
|
end
|
350
390
|
|
351
|
-
it
|
352
|
-
expect(headers[:accept]).to eq
|
391
|
+
it "overwrites existing values" do
|
392
|
+
expect(headers[:accept]).to eq "plain/text"
|
353
393
|
end
|
354
394
|
|
355
|
-
it
|
395
|
+
it "appends other headers, not presented in base" do
|
356
396
|
expect(headers[:cookie]).to eq %w(hoo=ray woo=hoo)
|
357
397
|
end
|
358
398
|
end
|
359
399
|
|
360
|
-
describe
|
400
|
+
describe "#merge" do
|
361
401
|
before do
|
362
|
-
headers.set :host,
|
363
|
-
headers.set :accept,
|
402
|
+
headers.set :host, "example.com"
|
403
|
+
headers.set :accept, "application/json"
|
364
404
|
end
|
365
405
|
|
366
406
|
subject(:merged) do
|
367
|
-
headers.merge :accept =>
|
407
|
+
headers.merge :accept => "plain/text", :cookie => %w(hoo=ray woo=hoo)
|
368
408
|
end
|
369
409
|
|
370
410
|
it { is_expected.to be_a described_class }
|
371
411
|
it { is_expected.not_to be headers }
|
372
412
|
|
373
|
-
it
|
413
|
+
it "does not affects original headers" do
|
374
414
|
expect(merged.to_h).to_not eq headers.to_h
|
375
415
|
end
|
376
416
|
|
377
|
-
it
|
378
|
-
expect(merged[:host]).to eq
|
417
|
+
it "leaves headers not presented in other as is" do
|
418
|
+
expect(merged[:host]).to eq "example.com"
|
379
419
|
end
|
380
420
|
|
381
|
-
it
|
382
|
-
expect(merged[:accept]).to eq
|
421
|
+
it "overwrites existing values" do
|
422
|
+
expect(merged[:accept]).to eq "plain/text"
|
383
423
|
end
|
384
424
|
|
385
|
-
it
|
425
|
+
it "appends other headers, not presented in base" do
|
386
426
|
expect(merged[:cookie]).to eq %w(hoo=ray woo=hoo)
|
387
427
|
end
|
388
428
|
end
|
389
429
|
|
390
|
-
describe
|
430
|
+
describe ".coerce" do
|
391
431
|
let(:dummyClass) { Class.new { def respond_to?(*); end } }
|
392
432
|
|
393
|
-
it
|
394
|
-
hashie = double :to_hash => {
|
395
|
-
expect(described_class.coerce(hashie)[
|
433
|
+
it "accepts any object that respond to #to_hash" do
|
434
|
+
hashie = double :to_hash => {"accept" => "json"}
|
435
|
+
expect(described_class.coerce(hashie)["accept"]).to eq "json"
|
396
436
|
end
|
397
437
|
|
398
|
-
it
|
399
|
-
hashie = double :to_h => {
|
400
|
-
expect(described_class.coerce(hashie)[
|
438
|
+
it "accepts any object that respond to #to_h" do
|
439
|
+
hashie = double :to_h => {"accept" => "json"}
|
440
|
+
expect(described_class.coerce(hashie)["accept"]).to eq "json"
|
401
441
|
end
|
402
442
|
|
403
|
-
it
|
443
|
+
it "accepts any object that respond to #to_a" do
|
404
444
|
hashie = double :to_a => [%w(accept json)]
|
405
|
-
expect(described_class.coerce(hashie)[
|
445
|
+
expect(described_class.coerce(hashie)["accept"]).to eq "json"
|
406
446
|
end
|
407
447
|
|
408
|
-
it
|
448
|
+
it "fails if given object cannot be coerced" do
|
409
449
|
expect { described_class.coerce dummyClass.new }.to raise_error HTTP::Error
|
410
450
|
end
|
411
451
|
|
412
|
-
context
|
413
|
-
let(:headers) { {
|
452
|
+
context "with duplicate header keys (mixed case)" do
|
453
|
+
let(:headers) { {"Set-Cookie" => "hoo=ray", "set-cookie" => "woo=hoo"} }
|
414
454
|
|
415
|
-
it
|
455
|
+
it "adds all headers" do
|
416
456
|
expect(described_class.coerce(headers).to_a).to match_array([
|
417
457
|
%w(Set-Cookie hoo=ray),
|
418
458
|
%w(Set-Cookie woo=hoo)
|
@@ -420,7 +460,7 @@ RSpec.describe HTTP::Headers do
|
|
420
460
|
end
|
421
461
|
end
|
422
462
|
|
423
|
-
it
|
463
|
+
it "is aliased as .[]" do
|
424
464
|
expect(described_class.method :coerce).to eq described_class.method(:[])
|
425
465
|
end
|
426
466
|
end
|