http 1.0.0.pre1 → 1.0.0.pre2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a6a3c8891e4a8af6201fcda1333d5570ca5b0c15
4
- data.tar.gz: e527a9a5e0976f1e9ef793fd451c127b76738607
3
+ metadata.gz: 88e73e87efcb7c8c34d776d5bffcf72f45c195da
4
+ data.tar.gz: d9e4ef53d51cf7fa664999fd9e81c43e40d0a73c
5
5
  SHA512:
6
- metadata.gz: 4811c0bf41f037a2615f165d03ee1fd8dee7b42a4e743e1ec35638ca2ab96c82d9b808dfe96eff083003588b98c1dcc1502b8eb23c268e7ef239e388e27a00dc
7
- data.tar.gz: 9e7357f1161890a87449b6c92040fff54d9b829481de267d85f0c9337e0ec8e9e3a6a13319ef6055875b09fd39d854f62a48179e1e248da1671c47bc609faf21
6
+ metadata.gz: afb56806f4e58c1781db4722362319930d12489b60a258a83e3bfcd035f362ab22e9605078a23d89ebf6d265508482652bdf5e26ffeb4311fba061c458e1e576
7
+ data.tar.gz: cefe686bd8276230e515498becaa20c43aa14ee4203b47497ca7cbd4c9ec56ebe15c6a908737e042001135fd664c543401d22a97674386aa08b420475e2c8530
data/.rubocop.yml CHANGED
@@ -24,7 +24,7 @@ Metrics/ModuleLength:
24
24
  Max: 120
25
25
 
26
26
  Metrics/ParameterLists:
27
- Max: 3
27
+ Max: 5
28
28
  CountKeywordArgs: true
29
29
 
30
30
  Metrics/AbcSize:
data/CHANGES.md CHANGED
@@ -1,4 +1,4 @@
1
- ## 1.0.0.pre1 (2015-12-05)
1
+ ## 1.0.0.pre2 (2015-12-18)
2
2
 
3
3
  * [#265](https://github.com/httprb/http/pull/265/):
4
4
  Remove deprecations ([@tarcieri]):
@@ -14,182 +14,199 @@
14
14
  - HTTP::Response#status_code (use #status or #code)
15
15
  - HTTP::Response::Status#symbolize (use #to_sym)
16
16
 
17
+ * [#269](https://github.com/httprb/http/pull/273/):
18
+ Close connection in case of error during request.
19
+ ([@ixti])
20
+
21
+ * [#271](https://github.com/httprb/http/pull/273/):
22
+ High-level exception wrappers for low-level I/O errors.
23
+ ([@ixti])
24
+
25
+ * [#273](https://github.com/httprb/http/pull/273/):
26
+ Add encoding option.
27
+ ([@connorhd])
28
+
29
+ * [#275](https://github.com/httprb/http/pull/273/):
30
+ Support for disabling Nagle's algorithm with `HTTP.nodelay`.
31
+ ([@nerdrew])
32
+
17
33
  ## 0.9.8 (2015-09-29)
18
34
 
19
35
  * [#260](https://github.com/httprb/http/pull/258):
20
36
  Fixed global timeout persisting time left across requests when reusing connections.
21
- ([@zanker][])
37
+ ([@zanker])
38
+
22
39
 
23
40
  ## 0.9.7 (2015-09-19)
24
41
 
25
42
  * [#258](https://github.com/httprb/http/pull/258):
26
43
  Unified strategy for handling exception-based and exceptionless non-blocking
27
- I/O. Fixes SSL support on JRuby 9000. ([@tarcieri][])
44
+ I/O. Fixes SSL support on JRuby 9000. ([@tarcieri])
28
45
 
29
46
 
30
47
  ## 0.9.6 (2015-09-06)
31
48
 
32
49
  * [#254](https://github.com/httprb/http/pull/254):
33
50
  Removed use of an ActiveSupport specific method #present?
34
- ([@tarcieri][])
51
+ ([@tarcieri])
35
52
 
36
53
 
37
54
  ## 0.9.5 (2015-09-06)
38
55
 
39
56
  * [#252](https://github.com/httprb/http/pull/252):
40
57
  Fixed infinite hang/timeout when a request contained more than ~16,363 bytes.
41
- ([@zanker][])
58
+ ([@zanker])
42
59
 
43
60
 
44
61
  ## 0.9.4 (2015-08-26)
45
62
 
46
63
  * [#246](https://github.com/httprb/http/issues/246):
47
64
  Fixes regression when body streaming was failing on some URIs.
48
- ([@zanker][])
65
+ ([@zanker])
49
66
  * [#243](https://github.com/httprb/http/issues/243):
50
- Fixes require timeout statements. ([@ixti][])
67
+ Fixes require timeout statements. ([@ixti])
51
68
 
52
69
 
53
70
  ## 0.9.3 (2015-08-19)
54
71
 
55
72
  * [#246](https://github.com/httprb/http/issues/246):
56
- Fixed request URI normalization. ([@ixti][])
73
+ Fixed request URI normalization. ([@ixti])
57
74
  - Avoids query component normalization
58
75
  - Omits fragment component in headline
59
76
 
60
77
 
61
78
  ## 0.9.2 (2015-08-18)
62
79
 
63
- * Fixed exceptionless NIO EOF handling. ([@zanker][])
80
+ * Fixed exceptionless NIO EOF handling. ([@zanker])
64
81
 
65
82
 
66
83
  ## 0.9.1 (2015-08-14)
67
84
 
68
85
  * [#246](https://github.com/httprb/http/issues/246):
69
- Fix params special-chars escaping. ([@ixti][])
86
+ Fix params special-chars escaping. ([@ixti])
70
87
 
71
88
 
72
89
  ## 0.9.0 (2015-07-23)
73
90
 
74
91
  * [#240](https://github.com/httprb/http/pull/240):
75
- Support for caching removed. ([@tarcieri][])
92
+ Support for caching removed. ([@tarcieri])
76
93
  * JRuby 9000 compatibility
77
94
 
78
95
 
79
96
  ## 0.8.14 (2015-08-19)
80
97
 
81
- * Backport request URI normalization fixes from master. ([@ixti][])
98
+ * Backport request URI normalization fixes from master. ([@ixti])
82
99
 
83
100
 
84
101
  ## 0.8.13 (2015-08-14)
85
102
 
86
- * Backport params special-chars escaping fix from `v0.9.1`. ([@ixti][])
103
+ * Backport params special-chars escaping fix from `v0.9.1`. ([@ixti])
87
104
 
88
105
 
89
106
  ## 0.8.12 (2015-05-26)
90
107
 
91
- * Fix `HTTP.timeout` API (was loosing previously defined options). ([@ixti][])
108
+ * Fix `HTTP.timeout` API (was loosing previously defined options). ([@ixti])
92
109
 
93
110
 
94
111
  ## 0.8.11 (2015-05-22)
95
112
 
96
113
  * [#229](https://github.com/httprb/http/pull/229):
97
- SNI support for HTTPS connections. ([@tarcieri][])
114
+ SNI support for HTTPS connections. ([@tarcieri])
98
115
  * [#227](https://github.com/httprb/http/pull/227):
99
- Use "http.rb" in the User-Agent string. ([@tarcieri][])
116
+ Use "http.rb" in the User-Agent string. ([@tarcieri])
100
117
 
101
118
 
102
119
  ## 0.8.10 (2015-05-14)
103
120
 
104
- * Fix cookie headers generation. ([@ixti][])
121
+ * Fix cookie headers generation. ([@ixti])
105
122
 
106
123
 
107
124
  ## 0.8.9 (2015-05-11)
108
125
 
109
- * Add cookies support. ([@ixti][])
126
+ * Add cookies support. ([@ixti])
110
127
  * [#219](https://github.com/httprb/http/pull/219):
111
- Enforce stringified body encoding. ([@Connorhd][])
128
+ Enforce stringified body encoding. ([@Connorhd])
112
129
 
113
130
 
114
131
  ## 0.8.8 (2015-05-09)
115
132
 
116
133
  * [#217](https://github.com/httprb/http/issues/217):
117
- Fix CONNECT header for proxies. ([@Connorhd][])
134
+ Fix CONNECT header for proxies. ([@Connorhd])
118
135
 
119
136
 
120
137
  ## 0.8.7 (2015-05-08)
121
138
 
122
- * Fix `HTTP.timeout` API with options only given. ([@ixti][])
139
+ * Fix `HTTP.timeout` API with options only given. ([@ixti])
123
140
 
124
141
 
125
142
  ## 0.8.6 (2015-05-08)
126
143
 
127
144
  * [#215](https://github.com/httprb/http/pull/215):
128
- Reset global timeouts after the request finishes. ([@zanker][])
145
+ Reset global timeouts after the request finishes. ([@zanker])
129
146
 
130
147
 
131
148
  ## 0.8.5 (2015-05-06)
132
149
 
133
150
  * [#205](https://github.com/httprb/http/issues/205):
134
- Add simple timeouts configuration API. ([@ixti][])
135
- * Deprecate `Request#request_header`. Use `Request#headline` instead. ([@ixti][])
151
+ Add simple timeouts configuration API. ([@ixti])
152
+ * Deprecate `Request#request_header`. Use `Request#headline` instead. ([@ixti])
136
153
 
137
154
 
138
155
  ## 0.8.4 (2015-04-23)
139
156
 
140
- * Deprecate `#default_headers` and `#default_headers=`. ([@ixti][])
157
+ * Deprecate `#default_headers` and `#default_headers=`. ([@ixti])
141
158
  * [#207](https://github.com/httprb/http/issues/207):
142
- Deprecate chainable methods with `with_` prefix. ([@ixti][])
159
+ Deprecate chainable methods with `with_` prefix. ([@ixti])
143
160
  * [#186](https://github.com/httprb/http/pull/186):
144
- Add support of HTTPS connections through proxy. ([@Connorhd][])
161
+ Add support of HTTPS connections through proxy. ([@Connorhd])
145
162
 
146
163
 
147
164
  ## 0.8.3 (2015-04-07)
148
165
 
149
166
  * [#206](https://github.com/httprb/http/issues/206):
150
- Fix request headline. ([@ixti][])
151
- * Remove deprecated `Request#__method__`. ([@ixti][])
167
+ Fix request headline. ([@ixti])
168
+ * Remove deprecated `Request#__method__`. ([@ixti])
152
169
 
153
170
 
154
171
  ## 0.8.2 (2015-04-06)
155
172
 
156
173
  * [#203](https://github.com/httprb/http/issues/203):
157
- Fix Celluloid::IO compatibility. ([@ixti][])
158
- * Cleanup obsolete code. ([@zanker][])
174
+ Fix Celluloid::IO compatibility. ([@ixti])
175
+ * Cleanup obsolete code. ([@zanker])
159
176
 
160
177
 
161
178
  ## 0.8.1 (2015-04-02)
162
179
 
163
180
  * [#202](https://github.com/httprb/http/issues/202):
164
- Add missing `require "resolv"`. ([@ixti][])
181
+ Add missing `require "resolv"`. ([@ixti])
165
182
  * [#200](https://github.com/httprb/http/issues/200),
166
183
  [#201](https://github.com/httprb/http/pull/201):
167
- Add block-form `#persistent` calls. ([@ixti][])
184
+ Add block-form `#persistent` calls. ([@ixti])
168
185
 
169
186
 
170
187
  ## 0.8.0 (2015-04-01)
171
188
 
172
189
  * [#199](https://github.com/httprb/http/pull/199):
173
- Properly handle WaitWritable for SSL. ([@zanker][])
190
+ Properly handle WaitWritable for SSL. ([@zanker])
174
191
  * [#197](https://github.com/httprb/http/pull/197):
175
- Add support for non-ASCII URis. ([@ixti][])
192
+ Add support for non-ASCII URis. ([@ixti])
176
193
  * [#187](https://github.com/httprb/http/pull/187),
177
194
  [#194](https://github.com/httprb/http/pull/194),
178
195
  [#195](https://github.com/httprb/http/pull/195):
179
- Add configurable connection timeouts. ([@zanker][])
196
+ Add configurable connection timeouts. ([@zanker])
180
197
  * [#179](https://github.com/httprb/http/pull/179):
181
- Refactor requests redirect following logic. ([@ixti][])
182
- * Support for persistent HTTP connections ([@zanker][])
198
+ Refactor requests redirect following logic. ([@ixti])
199
+ * Support for persistent HTTP connections ([@zanker])
183
200
  * [#77](https://github.com/httprb/http/issues/77),
184
201
  [#177](https://github.com/httprb/http/pull/177):
185
- Add caching support. ([@Asmod4n][], [@pezra][])
202
+ Add caching support. ([@Asmod4n], [@pezra])
186
203
  * [#176](https://github.com/httprb/http/pull/176):
187
204
  Improve servers used in specs boot up. Issue was initially raised up
188
- by [@olegkovalenko][]. ([@ixti][])
189
- * Reflect FormData rename changes (FormData -> HTTP::FormData). ([@ixti][])
205
+ by [@olegkovalenko]. ([@ixti])
206
+ * Reflect FormData rename changes (FormData -> HTTP::FormData). ([@ixti])
190
207
  * [#173](https://github.com/httprb/http/pull/173):
191
208
  `HTTP::Headers` now raises `HTTP::InvalidHeaderNameError` in case of
192
- (surprise) invalid HTTP header field name (e.g.`"Foo:Bar"`). ([@ixti][])
209
+ (surprise) invalid HTTP header field name (e.g.`"Foo:Bar"`). ([@ixti])
193
210
 
194
211
 
195
212
  ## 0.7.3 (2015-03-24)
@@ -197,7 +214,7 @@
197
214
  * SECURITY FIX: http.rb failed to call the `#post_connection_check` method on
198
215
  SSL connections. This method implements hostname verification, and without it
199
216
  `http.rb` was vulnerable to MitM attacks. The problem was corrected by calling
200
- `#post_connection_check` (CVE-2015-1828) ([@zanker][])
217
+ `#post_connection_check` (CVE-2015-1828) ([@zanker])
201
218
 
202
219
 
203
220
  ## 0.7.2 (2015-03-02)
@@ -215,33 +232,33 @@
215
232
 
216
233
  * [#73](https://github.com/httprb/http/issues/73),
217
234
  [#167](https://github.com/httprb/http/pull/167):
218
- Add support of multipart form data. ([@ixti][])
235
+ Add support of multipart form data. ([@ixti])
219
236
  * Fix URI path normalization: `https://github.com` -> `https://github.com/`.
220
- ([@ixti][])
237
+ ([@ixti])
221
238
  * [#163](https://github.com/httprb/http/pull/163),
222
239
  [#166](https://github.com/httprb/http/pull/166),
223
240
  [#152](https://github.com/httprb/http/issues/152):
224
- Fix handling of EOF which caused infinite loop. ([@mickm][], [@ixti][])
225
- * Drop Ruby 1.8.7 support. ([@ixti][])
241
+ Fix handling of EOF which caused infinite loop. ([@mickm], [@ixti])
242
+ * Drop Ruby 1.8.7 support. ([@ixti])
226
243
  * [#150](https://github.com/httprb/http/issues/150):
227
- Fix default Host header value. ([@ixti][])
228
- * Remove BearerToken authorization header. ([@ixti][])
244
+ Fix default Host header value. ([@ixti])
245
+ * Remove BearerToken authorization header. ([@ixti])
229
246
  * `#auth` sugar now accepts only string value of Authorization header.
230
247
  Calling `#auth(:basic, opts)` is deprecated, use `#basic_auth(opts)` instead.
231
- ([@ixti][])
232
- * Fix handling of chunked responses without Content-Length header. ([@ixti][])
248
+ ([@ixti])
249
+ * Fix handling of chunked responses without Content-Length header. ([@ixti])
233
250
  * Remove `HTTP::Request#method` and deprecate `HTTP::Request#__method__`
234
- ([@sferik][])
251
+ ([@sferik])
235
252
  * Deprecate `HTTP::Response::STATUS_CODES`,
236
- use `HTTP::Response::Status::REASONS` instead ([@ixti][])
237
- * Deprecate `HTTP::Response::SYMBOL_TO_STATUS_CODE` ([@ixti][])
238
- * Deprecate `HTTP::Response#status_code` ([@ixti][])
239
- * `HTTP::Response#status` now returns `HTTP::Response::Status`. ([@ixti][])
253
+ use `HTTP::Response::Status::REASONS` instead ([@ixti])
254
+ * Deprecate `HTTP::Response::SYMBOL_TO_STATUS_CODE` ([@ixti])
255
+ * Deprecate `HTTP::Response#status_code` ([@ixti])
256
+ * `HTTP::Response#status` now returns `HTTP::Response::Status`. ([@ixti])
240
257
  * `HTTP::Response#reason` and `HTTP::Response#code` are proxies them
241
- to corresponding methods of `HTTP::Response#status` ([@ixti][])
258
+ to corresponding methods of `HTTP::Response#status` ([@ixti])
242
259
  * Rename `HTTP.with_follow` to `HTTP.follow` and mark former one as being
243
- deprecated ([@ixti][])
244
- * Delegate `HTTP::Response#readpartial` to `HTTP::Response::Body` ([@ixti][])
260
+ deprecated ([@ixti])
261
+ * Delegate `HTTP::Response#readpartial` to `HTTP::Response::Body` ([@ixti])
245
262
 
246
263
 
247
264
  ## 0.6.4 (2015-03-25)
@@ -249,57 +266,57 @@
249
266
  * SECURITY FIX: http.rb failed to call the `#post_connection_check` method on
250
267
  SSL connections. This method implements hostname verification, and without it
251
268
  `http.rb` was vulnerable to MitM attacks. The problem was corrected by calling
252
- `#post_connection_check` (CVE-2015-1828) ([@zanker][], backported by [@nicoolas25][])
269
+ `#post_connection_check` (CVE-2015-1828) ([@zanker], backported by [@nicoolas25])
253
270
 
254
271
 
255
272
  ## 0.6.3 (2014-11-14)
256
273
 
257
274
  * [#166](https://github.com/httprb/http/pull/166):
258
- Backported EOF fix from master branch. ([@ixti][])
275
+ Backported EOF fix from master branch. ([@ixti])
259
276
 
260
277
 
261
278
  ## 0.6.2 (2014-08-06)
262
279
 
263
280
  * [#150](https://github.com/httprb/http/issues/150):
264
- Fix default Host header value. ([@ixti][])
265
- * Deprecate BearerToken authorization header. ([@ixti][])
266
- * Fix handling of chunked responses without Content-Length header. ([@ixti][])
281
+ Fix default Host header value. ([@ixti])
282
+ * Deprecate BearerToken authorization header. ([@ixti])
283
+ * Fix handling of chunked responses without Content-Length header. ([@ixti])
267
284
  * Rename `HTTP.with_follow` to `HTTP.follow` and mark former one as being
268
- deprecated ([@ixti][])
285
+ deprecated ([@ixti])
269
286
 
270
287
 
271
288
  ## 0.6.1 (2014-05-07)
272
289
 
273
- * Fix request `Content-Length` calculation for Unicode ([@challengee][])
274
- * Add `Response#flush` ([@ixti][])
275
- * Fix `Response::Body#readpartial` default size ([@hannesg][], [@ixti][])
276
- * Add missing `CRLF` for chunked bodies ([@hannesg][])
277
- * Fix forgotten CGI require ([@ixti][])
278
- * Improve README ([@tarcieri][])
290
+ * Fix request `Content-Length` calculation for Unicode ([@challengee])
291
+ * Add `Response#flush` ([@ixti])
292
+ * Fix `Response::Body#readpartial` default size ([@hannesg], [@ixti])
293
+ * Add missing `CRLF` for chunked bodies ([@hannesg])
294
+ * Fix forgotten CGI require ([@ixti])
295
+ * Improve README ([@tarcieri])
279
296
 
280
297
 
281
298
  ## 0.6.0 (2014-04-04)
282
299
 
283
- * Rename `HTTP::Request#method` to `HTTP::Request#verb` ([@krainboltgreene][])
284
- * Add `HTTP::ResponseBody` class ([@tarcieri][])
285
- * Change API of response on `HTTP::Client.request` and "friends" (`#get`, `#post`, etc) ([@tarcieri][])
286
- * Add `HTTP::Response#readpartial` ([@tarcieri][])
287
- * Add `HTTP::Headers` class ([@ixti][])
288
- * Fix and improve following redirects ([@ixti][])
289
- * Add `HTTP::Request#redirect` ([@ixti][])
290
- * Add `HTTP::Response#content_type` ([@ixti][])
291
- * Add `HTTP::Response#mime_type` ([@ixti][])
292
- * Add `HTTP::Response#charset` ([@ixti][])
293
- * Improve error message upon invalid URI scheme ([@ixti][])
294
- * Consolidate errors under common `HTTP::Error` namespace ([@ixti][])
295
- * Add easy way of adding Authorization header ([@ixti][])
296
- * Fix proxy support ([@hundredwatt][])
297
- * Fix and improve query params handing ([@jwinter][])
298
- * Change API of custom MIME type parsers ([@ixti][])
299
- * Remove `HTTP::Chainable#with_response` ([@ixti][])
300
- * Remove `HTTP::Response::BodyDelegator` ([@ixti][])
301
- * Remove `HTTP::Response#parsed_body` ([@ixti][])
302
- * Bump up input buffer from 4K to 16K ([@tarcieri][])
300
+ * Rename `HTTP::Request#method` to `HTTP::Request#verb` ([@krainboltgreene])
301
+ * Add `HTTP::ResponseBody` class ([@tarcieri])
302
+ * Change API of response on `HTTP::Client.request` and "friends" (`#get`, `#post`, etc) ([@tarcieri])
303
+ * Add `HTTP::Response#readpartial` ([@tarcieri])
304
+ * Add `HTTP::Headers` class ([@ixti])
305
+ * Fix and improve following redirects ([@ixti])
306
+ * Add `HTTP::Request#redirect` ([@ixti])
307
+ * Add `HTTP::Response#content_type` ([@ixti])
308
+ * Add `HTTP::Response#mime_type` ([@ixti])
309
+ * Add `HTTP::Response#charset` ([@ixti])
310
+ * Improve error message upon invalid URI scheme ([@ixti])
311
+ * Consolidate errors under common `HTTP::Error` namespace ([@ixti])
312
+ * Add easy way of adding Authorization header ([@ixti])
313
+ * Fix proxy support ([@hundredwatt])
314
+ * Fix and improve query params handing ([@jwinter])
315
+ * Change API of custom MIME type parsers ([@ixti])
316
+ * Remove `HTTP::Chainable#with_response` ([@ixti])
317
+ * Remove `HTTP::Response::BodyDelegator` ([@ixti])
318
+ * Remove `HTTP::Response#parsed_body` ([@ixti])
319
+ * Bump up input buffer from 4K to 16K ([@tarcieri])
303
320
 
304
321
  ``` ruby
305
322
  # Main API change you will mention is that `request` method and it's
@@ -313,7 +330,7 @@ parsed_body = HTTP.get("http://example.com/users.json").parse
313
330
  # Second major change in API is work with request/response headers
314
331
  # It is now delegated to `HTTP::Headers` class, so you can check it's
315
332
  # documentation for details, here we will only outline main difference.
316
- # Duckface (`[]=`) does not appends headers anymore
333
+ # Duckface (`=`) does not appends headers anymore
317
334
 
318
335
  request[:content_type] = "text/plain"
319
336
  request[:content_type] = "text/html"
@@ -345,7 +362,7 @@ end
345
362
 
346
363
  ## 0.5.1 (2014-05-27)
347
364
 
348
- * Backports redirector fixes from 0.6.0 ([@ixti][])
365
+ * Backports redirector fixes from 0.6.0 ([@ixti])
349
366
  * EOL of 0.5.X branch.
350
367
 
351
368
 
data/README.md CHANGED
@@ -55,6 +55,10 @@ Top three reasons:
55
55
 
56
56
  Benchmarks performed using excon's benchmarking tool
57
57
 
58
+ DISCLAIMER: Most benchmarks you find in READMEs are crap,
59
+ including this one. These are out-of-date. If you care about
60
+ performance, benchmark for yourself for your own use cases!
61
+
58
62
  ## Help and Discussion
59
63
 
60
64
  If you need help or just want to talk about the http.rb,
@@ -180,6 +180,11 @@ module HTTP
180
180
  branch default_options.with_cookies(cookies)
181
181
  end
182
182
 
183
+ # Force a specific encoding for response body
184
+ def encoding(encoding)
185
+ branch default_options.with_encoding(encoding)
186
+ end
187
+
183
188
  # Accept the given MIME type(s)
184
189
  # @param type
185
190
  def accept(type)
@@ -217,6 +222,11 @@ module HTTP
217
222
  @default_options = HTTP::Options.new(opts)
218
223
  end
219
224
 
225
+ # Set TCP_NODELAY on the socket
226
+ def nodelay
227
+ branch default_options.with_nodelay(true)
228
+ end
229
+
220
230
  private
221
231
 
222
232
  # :nodoc:
data/lib/http/client.rb CHANGED
@@ -61,11 +61,12 @@ module HTTP
61
61
  end
62
62
 
63
63
  res = Response.new(
64
- @connection.status_code,
65
- @connection.http_version,
66
- @connection.headers,
67
- Response::Body.new(@connection),
68
- req.uri
64
+ :status => @connection.status_code,
65
+ :version => @connection.http_version,
66
+ :headers => @connection.headers,
67
+ :connection => @connection,
68
+ :encoding => options.encoding,
69
+ :uri => req.uri
69
70
  )
70
71
 
71
72
  @connection.finish_response if req.verb == :head
@@ -73,9 +74,7 @@ module HTTP
73
74
 
74
75
  res
75
76
  rescue
76
- # On any exception we reset the conn. This is a safety measure, to ensure
77
- # we don't have conns in a bad state resulting in mixed requests/responses
78
- close if persistent?
77
+ close
79
78
  raise
80
79
  end
81
80
 
@@ -20,6 +20,7 @@ module HTTP
20
20
 
21
21
  # @param [HTTP::Request] req
22
22
  # @param [HTTP::Options] options
23
+ # @raise [HTTP::ConnectionError] when failed to connect
23
24
  def initialize(req, options)
24
25
  @persistent = options.persistent?
25
26
  @keep_alive_timeout = options.keep_alive_timeout.to_f
@@ -30,11 +31,13 @@ module HTTP
30
31
  @parser = Response::Parser.new
31
32
 
32
33
  @socket = options.timeout_class.new(options.timeout_options)
33
- @socket.connect(options.socket_class, req.socket_host, req.socket_port)
34
+ @socket.connect(options.socket_class, req.socket_host, req.socket_port, options.nodelay)
34
35
 
35
36
  send_proxy_connect_request(req)
36
37
  start_tls(req, options)
37
38
  reset_timer
39
+ rescue SocketError, SystemCallError => e
40
+ raise ConnectionError, "failed to connect: #{e}"
38
41
  end
39
42
 
40
43
  # @see (HTTP::Response::Parser#status_code)
@@ -104,7 +107,7 @@ module HTTP
104
107
 
105
108
  set_keep_alive
106
109
  rescue IOError, Errno::ECONNRESET, Errno::EPIPE => e
107
- raise IOError, "problem making HTTP request: #{e}"
110
+ raise ConnectionError, "failed to read headers: #{e}"
108
111
  end
109
112
 
110
113
  # Callback for when we've reached the end of a response
data/lib/http/errors.rb CHANGED
@@ -2,6 +2,9 @@ module HTTP
2
2
  # Generic error
3
3
  class Error < StandardError; end
4
4
 
5
+ # Generic Connection error
6
+ class ConnectionError < Error; end
7
+
5
8
  # Generic Request error
6
9
  class RequestError < Error; end
7
10
 
data/lib/http/options.rb CHANGED
@@ -43,11 +43,13 @@ module HTTP
43
43
  :timeout_class => self.class.default_timeout_class,
44
44
  :timeout_options => {},
45
45
  :socket_class => self.class.default_socket_class,
46
+ :nodelay => false,
46
47
  :ssl_socket_class => self.class.default_ssl_socket_class,
47
48
  :ssl => {},
48
49
  :keep_alive_timeout => 5,
49
50
  :headers => {},
50
- :cookies => {}
51
+ :cookies => {},
52
+ :encoding => nil
51
53
  }
52
54
 
53
55
  opts_w_defaults = defaults.merge(options)
@@ -66,9 +68,13 @@ module HTTP
66
68
  end
67
69
  end
68
70
 
71
+ def_option :encoding do |encoding|
72
+ self.encoding = Encoding.find(encoding)
73
+ end
74
+
69
75
  %w(
70
76
  proxy params form json body follow response
71
- socket_class ssl_socket_class ssl_context ssl
77
+ socket_class nodelay ssl_socket_class ssl_context ssl
72
78
  persistent keep_alive_timeout timeout_class timeout_options
73
79
  ).each do |method_name|
74
80
  def_option method_name
@@ -18,7 +18,7 @@ module HTTP
18
18
  # Types valid to be used as body source
19
19
  VALID_BODY_TYPES = [String, NilClass, Enumerable]
20
20
 
21
- def initialize(socket, body, headers, headline) # rubocop:disable ParameterLists
21
+ def initialize(socket, body, headers, headline)
22
22
  @body = body
23
23
  @socket = socket
24
24
  @headers = headers
data/lib/http/response.rb CHANGED
@@ -23,12 +23,27 @@ module HTTP
23
23
  # @return [URI, nil]
24
24
  attr_reader :uri
25
25
 
26
- def initialize(status, version, headers, body, uri = nil) # rubocop:disable ParameterLists
27
- @version = version
28
- @body = body
29
- @uri = uri && HTTP::URI.parse(uri)
30
- @status = HTTP::Response::Status.new status
31
- @headers = HTTP::Headers.coerce(headers || {})
26
+ # Inits a new instance
27
+ #
28
+ # @option opts [Integer] :status Status code
29
+ # @option opts [String] :version HTTP version
30
+ # @option opts [Hash] :headers
31
+ # @option opts [HTTP::Connection] :connection
32
+ # @option opts [String] :encoding Encoding to use when reading body
33
+ # @option opts [String] :body
34
+ # @option opts [String] :uri
35
+ def initialize(opts)
36
+ @version = opts.fetch(:version)
37
+ @uri = opts.include?(:uri) && HTTP::URI.parse(opts.fetch(:uri))
38
+ @status = HTTP::Response::Status.new opts.fetch(:status)
39
+ @headers = HTTP::Headers.coerce(opts.fetch(:headers, {}))
40
+
41
+ if opts.include?(:connection)
42
+ encoding = opts[:encoding] || charset || Encoding::BINARY
43
+ @body = Response::Body.new(opts.fetch(:connection), encoding)
44
+ else
45
+ @body = opts.fetch(:body)
46
+ end
32
47
  end
33
48
 
34
49
  # @!method reason
@@ -70,19 +85,15 @@ module HTTP
70
85
  @content_type ||= ContentType.parse headers[Headers::CONTENT_TYPE]
71
86
  end
72
87
 
73
- # MIME type of response (if any)
74
- #
75
- # @return [String, nil]
76
- def mime_type
77
- @mime_type ||= content_type.mime_type
78
- end
88
+ # @!method mime_type
89
+ # MIME type of response (if any)
90
+ # @return [String, nil]
91
+ def_delegator :content_type, :mime_type
79
92
 
80
- # Charset of response (if any)
81
- #
82
- # @return [String, nil]
83
- def charset
84
- @charset ||= content_type.charset
85
- end
93
+ # @!method charset
94
+ # Charset of response (if any)
95
+ # @return [String, nil]
96
+ def_delegator :content_type, :charset
86
97
 
87
98
  def cookies
88
99
  @cookies ||= headers.each_with_object CookieJar.new do |(k, v), jar|
@@ -9,10 +9,11 @@ module HTTP
9
9
  include Enumerable
10
10
  def_delegator :to_s, :empty?
11
11
 
12
- def initialize(client)
13
- @client = client
14
- @streaming = nil
15
- @contents = nil
12
+ def initialize(client, encoding)
13
+ @client = client
14
+ @streaming = nil
15
+ @contents = nil
16
+ @encoding = encoding
16
17
  end
17
18
 
18
19
  # (see HTTP::Client#readpartial)
@@ -36,9 +37,9 @@ module HTTP
36
37
 
37
38
  begin
38
39
  @streaming = false
39
- @contents = "".force_encoding(Encoding::UTF_8)
40
+ @contents = "".force_encoding(@encoding)
40
41
  while (chunk = @client.readpartial)
41
- @contents << chunk.force_encoding(Encoding::ASCII_8BIT)
42
+ @contents << chunk.force_encoding(@encoding)
42
43
  end
43
44
  rescue
44
45
  @contents = nil
@@ -108,6 +108,7 @@ module HTTP
108
108
  end
109
109
 
110
110
  def __setobj__(obj)
111
+ fail TypeError, "Expected #{obj.inspect} to respond to #to_i" unless obj.respond_to? :to_i
111
112
  @code = obj.to_i
112
113
  end
113
114
 
@@ -18,10 +18,11 @@ module HTTP
18
18
  @total_timeout = time_left
19
19
  end
20
20
 
21
- def connect(socket_class, host, port)
21
+ def connect(socket_class, host, port, nodelay = false)
22
22
  reset_timer
23
23
  ::Timeout.timeout(time_left, TimeoutError) do
24
24
  @socket = socket_class.open(host, port)
25
+ @socket.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1) if nodelay
25
26
  end
26
27
 
27
28
  log_time
@@ -14,8 +14,9 @@ module HTTP
14
14
  end
15
15
 
16
16
  # Connects to a socket
17
- def connect(socket_class, host, port)
17
+ def connect(socket_class, host, port, nodelay = false)
18
18
  @socket = socket_class.open(host, port)
19
+ @socket.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1) if nodelay
19
20
  end
20
21
 
21
22
  # Starts a SSL connection on a socket
@@ -19,9 +19,10 @@ module HTTP
19
19
  @connect_timeout = options.fetch(:connect_timeout, CONNECT_TIMEOUT)
20
20
  end
21
21
 
22
- def connect(socket_class, host, port)
22
+ def connect(socket_class, host, port, nodelay = false)
23
23
  ::Timeout.timeout(connect_timeout, TimeoutError) do
24
24
  @socket = socket_class.open(host, port)
25
+ @socket.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1) if nodelay
25
26
  end
26
27
  end
27
28
 
data/lib/http/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module HTTP
2
- VERSION = "1.0.0.pre1".freeze
2
+ VERSION = "1.0.0.pre2".freeze
3
3
  end
@@ -26,11 +26,18 @@ RSpec.describe HTTP::Client do
26
26
  end
27
27
 
28
28
  def redirect_response(location, status = 302)
29
- HTTP::Response.new(status, "1.1", {"Location" => location}, "")
29
+ HTTP::Response.new(
30
+ :status => status,
31
+ :version => "1.1",
32
+ :headers => {"Location" => location},
33
+ :body => "")
30
34
  end
31
35
 
32
36
  def simple_response(body, status = 200)
33
- HTTP::Response.new(status, "1.1", {}, body)
37
+ HTTP::Response.new(
38
+ :status => status,
39
+ :version => "1.1",
40
+ :body => body)
34
41
  end
35
42
 
36
43
  describe "following redirects" do
@@ -53,8 +53,10 @@ RSpec.describe HTTP::Options, "merge" do
53
53
  :proxy => {:proxy_address => "127.0.0.1", :proxy_port => 8080},
54
54
  :follow => nil,
55
55
  :socket_class => described_class.default_socket_class,
56
+ :nodelay => false,
56
57
  :ssl_socket_class => described_class.default_ssl_socket_class,
57
58
  :ssl_context => nil,
58
- :cookies => {})
59
+ :cookies => {},
60
+ :encoding => nil)
59
61
  end
60
62
  end
@@ -1,6 +1,11 @@
1
1
  RSpec.describe HTTP::Redirector do
2
2
  def simple_response(status, body = "", headers = {})
3
- HTTP::Response.new(status, "1.1", headers, body)
3
+ HTTP::Response.new(
4
+ :status => status,
5
+ :version => "1.1",
6
+ :headers => headers,
7
+ :body => body
8
+ )
4
9
  end
5
10
 
6
11
  def redirect_response(status, location)
@@ -37,7 +37,7 @@ RSpec.describe HTTP::Request::Writer do
37
37
  let(:body) { 123 }
38
38
 
39
39
  it "raises an error" do
40
- expect { writer }.to raise_error
40
+ expect { writer }.to raise_error(HTTP::RequestError)
41
41
  end
42
42
  end
43
43
  end
@@ -59,12 +59,12 @@ RSpec.describe HTTP::Request::Writer do
59
59
 
60
60
  context "when Transfer-Encoding not set" do
61
61
  let(:headers) { HTTP::Headers.new }
62
- specify { expect { writer.stream }.to raise_error }
62
+ specify { expect { writer.stream }.to raise_error(HTTP::RequestError) }
63
63
  end
64
64
 
65
65
  context "when Transfer-Encoding is not chunked" do
66
66
  let(:headers) { HTTP::Headers.coerce "Transfer-Encoding" => "gzip" }
67
- specify { expect { writer.stream }.to raise_error }
67
+ specify { expect { writer.stream }.to raise_error(HTTP::RequestError) }
68
68
  end
69
69
  end
70
70
 
@@ -4,7 +4,7 @@ RSpec.describe HTTP::Response::Body do
4
4
 
5
5
  before { allow(client).to receive(:readpartial) { chunks.shift } }
6
6
 
7
- subject(:body) { described_class.new client }
7
+ subject(:body) { described_class.new client, Encoding::UTF_8 }
8
8
 
9
9
  it "streams bodies from responses" do
10
10
  expect(subject.to_s).to eq "Hello, World!"
@@ -1,7 +1,7 @@
1
1
  RSpec.describe HTTP::Response::Status do
2
2
  describe ".new" do
3
3
  it "fails if given value does not respond to #to_i" do
4
- expect { described_class.new double }.to raise_error
4
+ expect { described_class.new double }.to raise_error TypeError
5
5
  end
6
6
 
7
7
  it "accepts any object that responds to #to_i" do
@@ -2,7 +2,16 @@ RSpec.describe HTTP::Response do
2
2
  let(:body) { "Hello world!" }
3
3
  let(:uri) { "http://example.com/" }
4
4
  let(:headers) { {} }
5
- subject(:response) { HTTP::Response.new 200, "1.1", headers, body, uri }
5
+
6
+ subject(:response) do
7
+ HTTP::Response.new(
8
+ :status => 200,
9
+ :version => "1.1",
10
+ :headers => headers,
11
+ :body => body,
12
+ :uri => uri
13
+ )
14
+ end
6
15
 
7
16
  it "includes HTTP::Headers::Mixin" do
8
17
  expect(described_class).to include HTTP::Headers::Mixin
@@ -1,3 +1,5 @@
1
+ # encoding: UTF-8
2
+
1
3
  require "json"
2
4
 
3
5
  require "support/dummy_server"
@@ -160,14 +162,36 @@ RSpec.describe HTTP do
160
162
  context "loading binary data" do
161
163
  it "is encoded as bytes" do
162
164
  response = HTTP.get "#{dummy.endpoint}/bytes"
163
- expect(response.to_s.encoding).to eq(Encoding::ASCII_8BIT)
165
+ expect(response.to_s.encoding).to eq(Encoding::BINARY)
166
+ end
167
+ end
168
+
169
+ context "loading endpoint with charset" do
170
+ it "uses charset from headers" do
171
+ response = HTTP.get "#{dummy.endpoint}/iso-8859-1"
172
+ expect(response.to_s.encoding).to eq(Encoding::ISO8859_1)
173
+ expect(response.to_s.encode(Encoding::UTF_8)).to eq("testæ")
174
+ end
175
+
176
+ context "with encoding option" do
177
+ it "respects option" do
178
+ response = HTTP.get "#{dummy.endpoint}/iso-8859-1", "encoding" => Encoding::BINARY
179
+ expect(response.to_s.encoding).to eq(Encoding::BINARY)
180
+ end
164
181
  end
165
182
  end
166
183
 
167
- context "loading text" do
168
- it "is utf-8 encoded" do
184
+ context "passing a string encoding type" do
185
+ it "finds encoding" do
186
+ response = HTTP.get dummy.endpoint, "encoding" => "ascii"
187
+ expect(response.to_s.encoding).to eq(Encoding::ASCII)
188
+ end
189
+ end
190
+
191
+ context "loading text with no charset" do
192
+ it "is binary encoded" do
169
193
  response = HTTP.get dummy.endpoint
170
- expect(response.to_s.encoding).to eq(Encoding::UTF_8)
194
+ expect(response.to_s.encoding).to eq(Encoding::BINARY)
171
195
  end
172
196
  end
173
197
 
@@ -337,5 +361,40 @@ RSpec.describe HTTP do
337
361
  client = HTTP.headers("Cookie" => "foo=bar").cookies(:baz => :moo)
338
362
  expect(client.get(endpoint).to_s).to eq "foo: bar\nbaz: moo"
339
363
  end
364
+
365
+ it "unifies socket errors into HTTP::ConnectionError" do
366
+ expect { HTTP.get "http://thishostshouldnotexists.com" }.to raise_error HTTP::ConnectionError
367
+ expect { HTTP.get "http://127.0.0.1:000" }.to raise_error HTTP::ConnectionError
368
+ end
369
+ end
370
+
371
+ describe ".nodelay" do
372
+ before do
373
+ HTTP.default_options = {:socket_class => socket_spy_class}
374
+ end
375
+
376
+ after do
377
+ HTTP.default_options = {}
378
+ end
379
+
380
+ let(:socket_spy_class) do
381
+ Class.new(TCPSocket) do
382
+ def self.setsockopt_calls
383
+ @setsockopt_calls ||= []
384
+ end
385
+
386
+ def setsockopt(*args)
387
+ self.class.setsockopt_calls << args
388
+ super
389
+ end
390
+ end
391
+ end
392
+
393
+ it "sets TCP_NODELAY on the underlying socket" do
394
+ HTTP.get(dummy.endpoint)
395
+ expect(socket_spy_class.setsockopt_calls).to eq([])
396
+ HTTP.nodelay.get(dummy.endpoint)
397
+ expect(socket_spy_class.setsockopt_calls).to eq([[Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1]])
398
+ end
340
399
  end
341
400
  end
@@ -56,7 +56,7 @@ RSpec.shared_context "handles shared connections" do
56
56
  # rubocop:enable Style/RescueModifier
57
57
 
58
58
  # Should error because we tried to use a bad socket
59
- expect { client.get("#{server.endpoint}/socket").body.to_s }.to raise_error(IOError)
59
+ expect { client.get("#{server.endpoint}/socket").body.to_s }.to raise_error HTTP::ConnectionError
60
60
 
61
61
  # Should succeed since we create a new socket
62
62
  second_socket = client.get("#{server.endpoint}/socket").body.to_s
@@ -1,3 +1,5 @@
1
+ # encoding: UTF-8
2
+
1
3
  class DummyServer < WEBrick::HTTPServer
2
4
  class Servlet < WEBrick::HTTPServlet::AbstractServlet
3
5
  def self.sockets
@@ -129,6 +131,11 @@ class DummyServer < WEBrick::HTTPServer
129
131
  res.body = bytes.pack("c*")
130
132
  end
131
133
 
134
+ get "/iso-8859-1" do |_req, res|
135
+ res["Content-Type"] = "text/plain; charset=ISO-8859-1"
136
+ res.body = "testæ".encode(Encoding::ISO8859_1)
137
+ end
138
+
132
139
  get "/cookies" do |req, res|
133
140
  res["Set-Cookie"] = "foo=bar"
134
141
  res.body = req.cookies.map { |c| [c.name, c.value].join ": " }.join("\n")
@@ -173,7 +173,7 @@ RSpec.shared_context "HTTP handling" do
173
173
  # rubocop:enable Style/RescueModifier
174
174
 
175
175
  # Should error because we tried to use a bad socket
176
- expect { client.get("#{server.endpoint}/socket").body.to_s }.to raise_error(IOError)
176
+ expect { client.get("#{server.endpoint}/socket").body.to_s }.to raise_error HTTP::ConnectionError
177
177
 
178
178
  # Should succeed since we create a new socket
179
179
  second_socket_id = client.get("#{server.endpoint}/socket").body.to_s
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: http
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0.pre1
4
+ version: 1.0.0.pre2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Tony Arcieri
@@ -11,7 +11,7 @@ authors:
11
11
  autorequire:
12
12
  bindir: bin
13
13
  cert_chain: []
14
- date: 2015-12-05 00:00:00.000000000 Z
14
+ date: 2015-12-18 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: http_parser.rb
@@ -104,7 +104,6 @@ files:
104
104
  - LICENSE.txt
105
105
  - README.md
106
106
  - Rakefile
107
- - examples/parallel_requests_with_celluloid.rb
108
107
  - http.gemspec
109
108
  - lib/http.rb
110
109
  - lib/http/chainable.rb
@@ -1,38 +0,0 @@
1
- #!/usr/bin/env ruby
2
- #
3
- # Example of using the HTTP Gem with Celluloid::IO
4
- # Make sure to 'gem install celluloid-io' before running
5
- #
6
- # Run as: bundle exec examples/parallel_requests_with_celluloid.rb
7
- #
8
-
9
- require "celluloid/io"
10
- require "http"
11
-
12
- class HttpFetcher
13
- include Celluloid::IO
14
-
15
- def fetch(url)
16
- # Note: For SSL support specify:
17
- # ssl_socket_class: Celluloid::IO::SSLSocket
18
- HTTP.get(url, :socket_class => Celluloid::IO::TCPSocket)
19
- end
20
- end
21
-
22
- fetcher = HttpFetcher.new
23
-
24
- urls = %w(http://ruby-lang.org/ http://rubygems.org/ http://celluloid.io/)
25
-
26
- # Kick off a bunch of future calls to HttpFetcher to grab the URLs in parallel
27
- futures = urls.map { |u| [u, fetcher.future.fetch(u)] }
28
-
29
- # Consume the results as they come in
30
- futures.each do |url, future|
31
- # Wait for HttpFetcher#fetch to complete for this request
32
- response = future.value
33
- puts "Got #{url}: #{response.inspect}"
34
- end
35
-
36
- # Suppress Celluloid's shutdown messages
37
- # Otherwise the example is a bit noisy :|
38
- exit!