http 3.3.0 → 4.4.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.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -0
  3. data/.rubocop.yml +3 -1
  4. data/.travis.yml +10 -7
  5. data/CHANGES.md +135 -0
  6. data/README.md +14 -10
  7. data/Rakefile +1 -1
  8. data/http.gemspec +12 -5
  9. data/lib/http.rb +1 -2
  10. data/lib/http/chainable.rb +20 -29
  11. data/lib/http/client.rb +25 -19
  12. data/lib/http/connection.rb +5 -9
  13. data/lib/http/feature.rb +14 -0
  14. data/lib/http/features/auto_deflate.rb +27 -6
  15. data/lib/http/features/auto_inflate.rb +33 -6
  16. data/lib/http/features/instrumentation.rb +64 -0
  17. data/lib/http/features/logging.rb +55 -0
  18. data/lib/http/features/normalize_uri.rb +17 -0
  19. data/lib/http/headers/known.rb +3 -0
  20. data/lib/http/options.rb +27 -21
  21. data/lib/http/redirector.rb +2 -1
  22. data/lib/http/request.rb +38 -30
  23. data/lib/http/request/body.rb +30 -1
  24. data/lib/http/request/writer.rb +21 -7
  25. data/lib/http/response.rb +7 -15
  26. data/lib/http/response/parser.rb +56 -16
  27. data/lib/http/timeout/global.rb +12 -14
  28. data/lib/http/timeout/per_operation.rb +5 -7
  29. data/lib/http/uri.rb +13 -0
  30. data/lib/http/version.rb +1 -1
  31. data/spec/lib/http/client_spec.rb +34 -7
  32. data/spec/lib/http/features/auto_inflate_spec.rb +38 -22
  33. data/spec/lib/http/features/instrumentation_spec.rb +56 -0
  34. data/spec/lib/http/features/logging_spec.rb +67 -0
  35. data/spec/lib/http/redirector_spec.rb +13 -0
  36. data/spec/lib/http/request/body_spec.rb +51 -0
  37. data/spec/lib/http/request/writer_spec.rb +20 -0
  38. data/spec/lib/http/request_spec.rb +6 -0
  39. data/spec/lib/http/response/parser_spec.rb +45 -0
  40. data/spec/lib/http/response_spec.rb +3 -4
  41. data/spec/lib/http_spec.rb +45 -65
  42. data/spec/regression_specs.rb +7 -0
  43. data/spec/support/dummy_server/servlet.rb +5 -0
  44. data/spec/support/http_handling_shared.rb +60 -64
  45. metadata +32 -21
  46. data/.ruby-version +0 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 853087de359024f397422b0563f0232edfa247c2f201a060c10b7b8ea9aff00b
4
- data.tar.gz: b07ad1d88da70f9d76c5e272923dab3ce763077a8f8f7cb9ee6c37602acb6bb5
3
+ metadata.gz: cce9a8685f3b60f994e77174f79c2306f607d62016bf64b74fcebc4f86377ec0
4
+ data.tar.gz: 353702b62a1b9d3b2ea86ac5ac3ad88e9efa734c77e180128fa06c6c301895d3
5
5
  SHA512:
6
- metadata.gz: 654f47604b4e77c1138f9b82b5b902bf5d47f3bdc73979594633fc1d15c991eab5d933f001f1e6671bd432c498127f9b3ddb89cc2dc93fd3b792461961f1f1a0
7
- data.tar.gz: 4f8e97ea9830b1f36d5a0d636807e3f1296176640c2876d0f66c59d0643954e663d5c35ab14a538220b5f669195109a367b70d6ad281898ecb3830ce573cd485
6
+ metadata.gz: 84ddc4cf98e603d175a9ecb8db03abd32187888070abd96a437c4121750ac2b86b6cada5d00d527b398ff4a403c2b6448d45bed61c45dbd3be8658f4ad38b121
7
+ data.tar.gz: 750edced9ae715483d750f0b18777f84a4ee24848ec761c67d2c5b89d00ebbc99fbc1e02932d3d30a33eaea43e1d081ba97bcacaf2231f6693e50d218ee24e87
data/.gitignore CHANGED
@@ -2,6 +2,7 @@
2
2
  .bundle
3
3
  .config
4
4
  .rvmrc
5
+ .ruby-version
5
6
  .yardoc
6
7
  Gemfile.lock
7
8
  InstalledFiles
data/.rubocop.yml CHANGED
@@ -1,4 +1,5 @@
1
1
  AllCops:
2
+ TargetRubyVersion: 2.3
2
3
  DisplayCopNames: true
3
4
 
4
5
  ## Layout ######################################################################
@@ -19,7 +20,8 @@ Metrics/AbcSize:
19
20
 
20
21
  Metrics/BlockLength:
21
22
  Exclude:
22
- - spec/**/*
23
+ - "spec/**/*"
24
+ - "**/*.gemspec"
23
25
 
24
26
  Metrics/BlockNesting:
25
27
  Max: 2
data/.travis.yml CHANGED
@@ -6,7 +6,7 @@ cache: bundler
6
6
  before_install:
7
7
  - gem update --system
8
8
  - gem --version
9
- - gem install bundler --no-rdoc --no-ri
9
+ - gem install bundler --no-document
10
10
  - bundle --version
11
11
 
12
12
  install: bundle install --without development doc
@@ -17,20 +17,23 @@ env: JRUBY_OPTS="$JRUBY_OPTS --debug"
17
17
 
18
18
  rvm:
19
19
  # Include JRuby first because it takes the longest
20
- - jruby-9.1.13.0
21
- - 2.2
22
- - 2.3.4
23
- - 2.4.1
20
+ - jruby-9.2.5.0
21
+ - 2.3
22
+ - 2.4
23
+ - 2.5
24
+ - 2.6
25
+ - 2.7
24
26
 
25
27
  matrix:
26
28
  fast_finish: true
27
29
  include:
28
30
  # Only run RuboCop and Yardstick metrics on the latest Ruby
29
- - rvm: 2.4.1
31
+ - rvm: 2.7
30
32
  env: SUITE="rubocop"
31
- - rvm: 2.4.1
33
+ - rvm: 2.7
32
34
  env: SUITE="yardstick"
33
35
 
34
36
  branches:
35
37
  only:
36
38
  - master
39
+ - 4-x-stable
data/CHANGES.md CHANGED
@@ -1,3 +1,134 @@
1
+ ## 4.4.1 (2020-03-29)
2
+
3
+ * Backport [#590](https://github.com/httprb/http/pull/590)
4
+ Fix parser failing on some edge cases.
5
+ ([@ixti])
6
+
7
+ ## 4.4.0 (2020-03-25)
8
+
9
+ * Backport [#587](https://github.com/httprb/http/pull/587)
10
+ Fix redirections when server responds with multiple Location headers.
11
+ ([@ixti])
12
+
13
+ * Backport [#599](https://github.com/httprb/http/pull/599)
14
+ Allow passing HTTP::FormData::{Multipart,UrlEncoded} object directly.
15
+ ([@ixti])
16
+
17
+ ## 4.3.0 (2020-01-09)
18
+
19
+ * Backport [#581](https://github.com/httprb/http/pull/581)
20
+ Add Ruby-2.7 compatibility.
21
+ ([@ixti], [@janko])
22
+
23
+
24
+ ## 4.2.0 (2019-10-22)
25
+
26
+ * Backport [#489](https://github.com/httprb/http/pull/489)
27
+ Fix HTTP parser.
28
+ ([@ixti], [@fxposter])
29
+
30
+
31
+ ## 4.1.1 (2019-03-12)
32
+
33
+ * Add `HTTP::Headers::ACCEPT_ENCODING` constant.
34
+ ([@ixti])
35
+
36
+
37
+ ## 4.1.0 (2019-03-11)
38
+
39
+ * [#533](https://github.com/httprb/http/pull/533)
40
+ Add URI normalizer feature that allows to swap default URI normalizer.
41
+ ([@mamoonraja])
42
+
43
+
44
+ ## 4.0.5 (2019-02-15)
45
+
46
+ * Backport [#532](https://github.com/httprb/http/pull/532) from master.
47
+ Fix pipes support in request bodies.
48
+ ([@ixti])
49
+
50
+
51
+ ## 4.0.4 (2019-02-12)
52
+
53
+ * Backport [#506](https://github.com/httprb/http/pull/506) from master.
54
+ Skip auto-deflate when there is no body.
55
+ ([@Bonias])
56
+
57
+
58
+ ## 4.0.3 (2019-01-18)
59
+
60
+ * Fix missing URL in response wrapped by auto inflate.
61
+ ([@ixti])
62
+
63
+ * Provide `HTTP::Request#inspect` method for debugging purposes.
64
+ ([@ixti])
65
+
66
+
67
+ ## 4.0.2 (2019-01-15)
68
+
69
+ * [#506](https://github.com/httprb/http/pull/506)
70
+ Fix instrumentation feature.
71
+ ([@paul])
72
+
73
+
74
+ ## 4.0.1 (2019-01-14)
75
+
76
+ * [#515](https://github.com/httprb/http/pull/515)
77
+ Fix `#build_request` and `#request` to respect default options.
78
+ ([@RickCSong])
79
+
80
+
81
+ ## 4.0.0 (2018-10-15)
82
+
83
+ * [#482](https://github.com/httprb/http/pull/482)
84
+ [#499](https://github.com/httprb/http/pull/499)
85
+ Introduce new features injection API with 2 new feaures: instrumentation
86
+ (compatible with ActiveSupport::Notification) and logging.
87
+ ([@paul])
88
+
89
+ * [#473](https://github.com/httprb/http/pull/473)
90
+ Handle early responses.
91
+ ([@janko-m])
92
+
93
+ * [#468](https://github.com/httprb/http/pull/468)
94
+ Rewind `HTTP::Request::Body#source` once `#each` is complete.
95
+ ([@ixti])
96
+
97
+ * [#467](https://github.com/httprb/http/pull/467)
98
+ Drop Ruby 2.2 support.
99
+ ([@ixti])
100
+
101
+ * [#436](https://github.com/httprb/http/pull/436)
102
+ Raise ConnectionError when writing to socket fails.
103
+ ([@janko-m])
104
+
105
+ * [#438](https://github.com/httprb/http/pull/438)
106
+ Expose `HTTP::Request::Body#source`.
107
+ ([@janko-m])
108
+
109
+ * [#446](https://github.com/httprb/http/pull/446)
110
+ Simplify setting a timeout.
111
+ ([@mikegee])
112
+
113
+ * [#451](https://github.com/httprb/http/pull/451)
114
+ Reduce memory usage when reading response body.
115
+ ([@janko-m])
116
+
117
+ * [#458](https://github.com/httprb/http/pull/458)
118
+ Extract HTTP::Client#build_request method.
119
+ ([@tycoon])
120
+
121
+ * [#462](https://github.com/httprb/http/pull/462)
122
+ Fix HTTP::Request#headline to allow two leading slashes in path.
123
+ ([@scarfacedeb])
124
+
125
+ * [#454](https://github.com/httprb/http/pull/454)
126
+ [#464](https://github.com/httprb/http/pull/464)
127
+ [#384](https://github.com/httprb/http/issues/384)
128
+ Fix #readpartial not respecting max length argument.
129
+ ([@janko-m], [@marshall-lee])
130
+
131
+
1
132
  ## 3.3.0 (2018-04-25)
2
133
 
3
134
  This version backports some of the fixes and improvements made to development
@@ -668,3 +799,7 @@ end
668
799
  [@scarfacedeb]: https://github.com/scarfacedeb
669
800
  [@mikegee]: https://github.com/mikegee
670
801
  [@tycoon]: https://github.com/tycooon
802
+ [@paul]: https://github.com/paul
803
+ [@RickCSong]: https://github.com/RickCSong
804
+ [@fxposter]: https://github.com/fxposter
805
+ [@mamoonraja]: https://github.com/mamoonraja
data/README.md CHANGED
@@ -1,15 +1,16 @@
1
1
  # ![http.rb](https://raw.github.com/httprb/http.rb/master/logo.png)
2
2
 
3
3
  [![Gem Version](https://badge.fury.io/rb/http.svg)](https://rubygems.org/gems/http)
4
- [![Build Status](https://secure.travis-ci.org/httprb/http.svg?branch=master)](https://travis-ci.org/httprb/http)
5
- [![Code Climate](https://codeclimate.com/github/httprb/http.svg?branch=master)](https://codeclimate.com/github/httprb/http)
6
- [![Coverage Status](https://coveralls.io/repos/httprb/http/badge.svg?branch=master)](https://coveralls.io/r/httprb/http)
7
- [![MIT licensed](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/httprb/http/blob/master/LICENSE.txt)
4
+ [![Build Status](https://secure.travis-ci.org/httprb/http.svg?branch=4-x-stable)](https://travis-ci.org/httprb/http)
5
+ [![Code Climate](https://codeclimate.com/github/httprb/http.svg?branch=4-x-stable)](https://codeclimate.com/github/httprb/http)
6
+ [![Coverage Status](https://coveralls.io/repos/httprb/http/badge.svg?branch=4-x-stable)](https://coveralls.io/r/httprb/http)
7
+ [![MIT licensed](https://img.shields.io/badge/license-MIT-blue.svg)](https://github.com/httprb/http/blob/4-x-stable/LICENSE.txt)
8
8
 
9
- _NOTE: This is the 3.x **stable** branch. For the 4.x **development** branch, please see:_
9
+ [Documentation]
10
10
 
11
- https://github.com/httprb/http/
11
+ _NOTE: This is the 4.x **stable** branch. For the 3.x **stable** branch, please see:_
12
12
 
13
+ https://github.com/httprb/http/tree/3-x-stable
13
14
 
14
15
  ## About
15
16
 
@@ -108,7 +109,7 @@ require "http"
108
109
 
109
110
  ## Documentation
110
111
 
111
- [Please see the http.rb wiki](https://github.com/httprb/http/wiki)
112
+ [Please see the http.rb wiki][documentation]
112
113
  for more detailed documentation and usage notes.
113
114
 
114
115
  The following API documentation is also available:
@@ -116,6 +117,8 @@ The following API documentation is also available:
116
117
  * [YARD API documentation](http://www.rubydoc.info/gems/http/frames)
117
118
  * [Chainable module (all chainable methods)](http://www.rubydoc.info/gems/http/HTTP/Chainable)
118
119
 
120
+ [documentation]: https://github.com/httprb/http/wiki
121
+
119
122
  ### Basic Usage
120
123
 
121
124
  Here's some simple examples to get you started:
@@ -161,10 +164,11 @@ and call `#readpartial` on it repeatedly until it returns `nil`:
161
164
  This library aims to support and is [tested against][travis] the following Ruby
162
165
  versions:
163
166
 
164
- * Ruby 2.2.x
165
167
  * Ruby 2.3.x
166
168
  * Ruby 2.4.x
167
- * JRuby 9.1.x.x
169
+ * Ruby 2.5.x
170
+ * Ruby 2.6.x
171
+ * JRuby 9.2.x.x
168
172
 
169
173
  If something doesn't work on one of these versions, it's a bug.
170
174
 
@@ -194,5 +198,5 @@ dropped.
194
198
 
195
199
  ## Copyright
196
200
 
197
- Copyright (c) 2011-2018 Tony Arcieri, Alexey V. Zapparov, Erik Michaels-Ober, Zachary Anker.
201
+ Copyright (c) 2011-2019 Tony Arcieri, Alexey V. Zapparov, Erik Michaels-Ober, Zachary Anker.
198
202
  See LICENSE.txt for further details.
data/Rakefile CHANGED
@@ -25,7 +25,7 @@ task :generate_status_codes do
25
25
 
26
26
  url = "http://www.iana.org/assignments/http-status-codes/http-status-codes.xml"
27
27
  xml = Nokogiri::XML HTTP.get url
28
- arr = xml.xpath("//xmlns:record").reduce [] do |a, e|
28
+ arr = xml.xpath("//xmlns:record").reduce([]) do |a, e|
29
29
  code = e.xpath("xmlns:value").text.to_s
30
30
  desc = e.xpath("xmlns:description").text.to_s
31
31
 
data/http.gemspec CHANGED
@@ -25,12 +25,19 @@ Gem::Specification.new do |gem|
25
25
  gem.require_paths = ["lib"]
26
26
  gem.version = HTTP::VERSION
27
27
 
28
- gem.required_ruby_version = ">= 2.2"
28
+ gem.required_ruby_version = ">= 2.3"
29
29
 
30
- gem.add_runtime_dependency "http_parser.rb", "~> 0.6.0"
31
- gem.add_runtime_dependency "http-form_data", "~> 2.0"
32
- gem.add_runtime_dependency "http-cookie", "~> 1.0"
33
30
  gem.add_runtime_dependency "addressable", "~> 2.3"
31
+ gem.add_runtime_dependency "http-cookie", "~> 1.0"
32
+ gem.add_runtime_dependency "http-form_data", "~> 2.2"
33
+ gem.add_runtime_dependency "http-parser", "~> 1.2.0"
34
+
35
+ gem.add_development_dependency "bundler", "~> 2.0"
34
36
 
35
- gem.add_development_dependency "bundler", "~> 1.0"
37
+ gem.metadata = {
38
+ "source_code_uri" => "https://github.com/httprb/http",
39
+ "wiki_uri" => "https://github.com/httprb/http/wiki",
40
+ "bug_tracker_uri" => "https://github.com/httprb/http/issues",
41
+ "changelog_uri" => "https://github.com/httprb/http/blob/v#{HTTP::VERSION}/CHANGES.md"
42
+ }
36
43
  end
data/lib/http.rb CHANGED
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "http/parser"
4
-
5
3
  require "http/errors"
6
4
  require "http/timeout/null"
7
5
  require "http/timeout/per_operation"
@@ -10,6 +8,7 @@ require "http/chainable"
10
8
  require "http/client"
11
9
  require "http/connection"
12
10
  require "http/options"
11
+ require "http/feature"
13
12
  require "http/request"
14
13
  require "http/request/writer"
15
14
  require "http/response"
@@ -70,45 +70,36 @@ module HTTP
70
70
  end
71
71
 
72
72
  # Make an HTTP request with the given verb
73
- # @param verb
74
- # @param uri
75
- # @option options [Hash]
76
- def request(verb, uri, options = {}) # rubocop:disable Style/OptionHash
77
- branch(options).request verb, uri
73
+ # @param (see Client#request)
74
+ def request(*args)
75
+ branch(default_options).request(*args)
78
76
  end
79
77
 
80
78
  # Prepare an HTTP request with the given verb
81
- # @param verb
82
- # @param uri
83
- # @option options [Hash]
84
- def build_request(verb, uri, options = {}) # rubocop:disable Style/OptionHash
85
- branch(options).build_request verb, uri
79
+ # @param (see Client#build_request)
80
+ def build_request(*args)
81
+ branch(default_options).build_request(*args)
86
82
  end
87
83
 
88
84
  # @overload timeout(options = {})
89
- # Syntax sugar for `timeout(:per_operation, options)`
90
- # @overload timeout(klass, options = {})
91
- # Adds a timeout to the request.
92
- # @param [#to_sym] klass
93
- # either :null, :global, or :per_operation
85
+ # Adds per operation timeouts to the request
94
86
  # @param [Hash] options
95
87
  # @option options [Float] :read Read timeout
96
88
  # @option options [Float] :write Write timeout
97
89
  # @option options [Float] :connect Connect timeout
98
- def timeout(klass, options = {}) # rubocop:disable Style/OptionHash
99
- if klass.is_a? Hash
100
- options = klass
101
- klass = :per_operation
102
- end
103
-
104
- klass = case klass.to_sym
105
- when :null then HTTP::Timeout::Null
106
- when :global then HTTP::Timeout::Global
107
- when :per_operation then HTTP::Timeout::PerOperation
108
- else raise ArgumentError, "Unsupported Timeout class: #{klass}"
109
- end
110
-
111
- %i[read write connect].each do |k|
90
+ # @overload timeout(global_timeout)
91
+ # Adds a global timeout to the full request
92
+ # @param [Numeric] global_timeout
93
+ def timeout(options)
94
+ klass, options = case options
95
+ when Numeric then [HTTP::Timeout::Global, {:global => options}]
96
+ when Hash then [HTTP::Timeout::PerOperation, options]
97
+ when :null then [HTTP::Timeout::Null, {}]
98
+ else raise ArgumentError, "Use `.timeout(global_timeout_in_seconds)` or `.timeout(connect: x, write: y, read: z)`."
99
+
100
+ end
101
+
102
+ %i[global read write connect].each do |k|
112
103
  next unless options.key? k
113
104
  options["#{k}_timeout".to_sym] = options.delete k
114
105
  end
data/lib/http/client.rb CHANGED
@@ -4,6 +4,7 @@ require "forwardable"
4
4
 
5
5
  require "http/form_data"
6
6
  require "http/options"
7
+ require "http/feature"
7
8
  require "http/headers"
8
9
  require "http/connection"
9
10
  require "http/redirector"
@@ -41,16 +42,19 @@ module HTTP
41
42
  uri = make_request_uri(uri, opts)
42
43
  headers = make_request_headers(opts)
43
44
  body = make_request_body(opts, headers)
44
- proxy = opts.proxy
45
-
46
- HTTP::Request.new(
47
- :verb => verb,
48
- :uri => uri,
49
- :headers => headers,
50
- :proxy => proxy,
51
- :body => body,
52
- :auto_deflate => opts.feature(:auto_deflate)
45
+
46
+ req = HTTP::Request.new(
47
+ :verb => verb,
48
+ :uri => uri,
49
+ :uri_normalizer => opts.feature(:normalize_uri)&.normalizer,
50
+ :proxy => opts.proxy,
51
+ :headers => headers,
52
+ :body => body
53
53
  )
54
+
55
+ opts.features.inject(req) do |request, (_name, feature)|
56
+ feature.wrap_request(request)
57
+ end
54
58
  end
55
59
 
56
60
  # @!method persistent?
@@ -78,10 +82,13 @@ module HTTP
78
82
  :proxy_headers => @connection.proxy_response_headers,
79
83
  :connection => @connection,
80
84
  :encoding => options.encoding,
81
- :auto_inflate => options.feature(:auto_inflate),
82
85
  :uri => req.uri
83
86
  )
84
87
 
88
+ res = options.features.inject(res) do |response, (_name, feature)|
89
+ feature.wrap_response(response)
90
+ end
91
+
85
92
  @connection.finish_response if req.verb == :head
86
93
  @state = :clean
87
94
 
@@ -153,14 +160,6 @@ module HTTP
153
160
  headers[Headers::COOKIE] = cookies
154
161
  end
155
162
 
156
- if (auto_deflate = opts.feature(:auto_deflate))
157
- # We need to delete Content-Length header. It will be set automatically
158
- # by HTTP::Request::Writer
159
- headers.delete(Headers::CONTENT_LENGTH)
160
-
161
- headers[Headers::CONTENT_ENCODING] = auto_deflate.method
162
- end
163
-
164
163
  headers
165
164
  end
166
165
 
@@ -170,7 +169,7 @@ module HTTP
170
169
  when opts.body
171
170
  opts.body
172
171
  when opts.form
173
- form = HTTP::FormData.create opts.form
172
+ form = make_form_data(opts.form)
174
173
  headers[Headers::CONTENT_TYPE] ||= form.content_type
175
174
  form
176
175
  when opts.json
@@ -179,5 +178,12 @@ module HTTP
179
178
  body
180
179
  end
181
180
  end
181
+
182
+ def make_form_data(form)
183
+ return form if form.is_a? HTTP::FormData::Multipart
184
+ return form if form.is_a? HTTP::FormData::Urlencoded
185
+
186
+ HTTP::FormData.create(form)
187
+ end
182
188
  end
183
189
  end