http 4.0.5 → 4.1.0

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 94fd7f54004fd45a400c1e9befb46ea80d4bcdebae70929330355a5ea9056cf2
4
- data.tar.gz: 3bbd9c1f0a29267bff2b6682ddaeaa53832eb896ec471d6ab3db62d5cbd08be2
3
+ metadata.gz: 2fd67432d99ac8430c405776f6483ddb0e05d323ea9e8c18a0760936ba3c2608
4
+ data.tar.gz: bfcd8f950d05342a5fe993a0b88d47cbdc6418fbeef4e13b67eefb482ece7b77
5
5
  SHA512:
6
- metadata.gz: 5863fb462013166b6f76ff40929768f5a87ca86c02bd23c882bf5db1aefa6bed5be2a21785a45edecf66f6a6ac3418d86042b5c24f998e1f01489a661a1d9cae
7
- data.tar.gz: 04726c6858928f553380fbb221cc1164cc51917ae2122cd9b7424ef3f1ff072c7b32ae2231cb32569a4411487f6c805acee54ec09e309e6eba4675a783df8306
6
+ metadata.gz: 74790c3405ba4cd9ebe667d7e4ae61ae895bd9a67c36be057fe8dba446b8020ec74b06c77fbe904bccebcf23b307aa3a1fd85fd6ea48248abf2869069f5e109b
7
+ data.tar.gz: ce21f7ca1026c690eae83f18a688bab7d5a1da6344af13865819f5da911a4ff79a0b2424a9f22a6ac605273bb825dd848171c0f555d5d4130bd7b8e137532eea
data/CHANGES.md CHANGED
@@ -1,3 +1,10 @@
1
+ ## 4.1.0 (2019-03-11)
2
+
3
+ * [#533](https://github.com/httprb/http/pull/533)
4
+ Add URI normalizer feature that allows to swap default URI normalizer.
5
+ ([@mamoonraja])
6
+
7
+
1
8
  ## 4.0.5 (2019-02-15)
2
9
 
3
10
  * Backport [#532](https://github.com/httprb/http/pull/532) from master.
@@ -758,3 +765,4 @@ end
758
765
  [@tycoon]: https://github.com/tycooon
759
766
  [@paul]: https://github.com/paul
760
767
  [@RickCSong]: https://github.com/RickCSong
768
+ [@mamoonraja]: https://github.com/mamoonraja
@@ -42,14 +42,14 @@ module HTTP
42
42
  uri = make_request_uri(uri, opts)
43
43
  headers = make_request_headers(opts)
44
44
  body = make_request_body(opts, headers)
45
- proxy = opts.proxy
46
45
 
47
46
  req = HTTP::Request.new(
48
- :verb => verb,
49
- :uri => uri,
50
- :headers => headers,
51
- :proxy => proxy,
52
- :body => body
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
54
 
55
55
  opts.features.inject(req) do |request, (_name, feature)|
@@ -20,3 +20,4 @@ require "http/features/auto_inflate"
20
20
  require "http/features/auto_deflate"
21
21
  require "http/features/logging"
22
22
  require "http/features/instrumentation"
23
+ require "http/features/normalize_uri"
@@ -32,7 +32,8 @@ module HTTP
32
32
  :uri => request.uri,
33
33
  :headers => request.headers,
34
34
  :proxy => request.proxy,
35
- :body => deflated_body(request.body)
35
+ :body => deflated_body(request.body),
36
+ :uri_normalizer => request.uri_normalizer
36
37
  )
37
38
  end
38
39
 
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "http/uri"
4
+
5
+ module HTTP
6
+ module Features
7
+ class NormalizeUri < Feature
8
+ attr_reader :normalizer
9
+
10
+ def initialize(normalizer: HTTP::URI::NORMALIZER)
11
+ @normalizer = normalizer
12
+ end
13
+
14
+ HTTP::Options.register_feature(:normalize_uri, self)
15
+ end
16
+ end
17
+ end
@@ -66,6 +66,8 @@ module HTTP
66
66
  # Scheme is normalized to be a lowercase symbol e.g. :http, :https
67
67
  attr_reader :scheme
68
68
 
69
+ attr_reader :uri_normalizer
70
+
69
71
  # "Request URI" as per RFC 2616
70
72
  # http://www.w3.org/Protocols/rfc2616/rfc2616-sec5.html
71
73
  attr_reader :uri
@@ -73,25 +75,25 @@ module HTTP
73
75
 
74
76
  # @option opts [String] :version
75
77
  # @option opts [#to_s] :verb HTTP request method
78
+ # @option opts [#call] :uri_normalizer (HTTP::URI::NORMALIZER)
76
79
  # @option opts [HTTP::URI, #to_s] :uri
77
80
  # @option opts [Hash] :headers
78
81
  # @option opts [Hash] :proxy
79
82
  # @option opts [String, Enumerable, IO, nil] :body
80
83
  def initialize(opts)
81
- @verb = opts.fetch(:verb).to_s.downcase.to_sym
82
- @uri = normalize_uri(opts.fetch(:uri))
84
+ @verb = opts.fetch(:verb).to_s.downcase.to_sym
85
+ @uri_normalizer = opts[:uri_normalizer] || HTTP::URI::NORMALIZER
86
+
87
+ @uri = @uri_normalizer.call(opts.fetch(:uri))
83
88
  @scheme = @uri.scheme.to_s.downcase.to_sym if @uri.scheme
84
89
 
85
90
  raise(UnsupportedMethodError, "unknown method: #{verb}") unless METHODS.include?(@verb)
86
91
  raise(UnsupportedSchemeError, "unknown scheme: #{scheme}") unless SCHEMES.include?(@scheme)
87
92
 
88
93
  @proxy = opts[:proxy] || {}
89
- @body = (body = opts[:body]).is_a?(Request::Body) ? body : Request::Body.new(body)
90
94
  @version = opts[:version] || "1.1"
91
- @headers = HTTP::Headers.coerce(opts[:headers] || {})
92
-
93
- @headers[Headers::HOST] ||= default_host_header_value
94
- @headers[Headers::USER_AGENT] ||= USER_AGENT
95
+ @headers = prepare_headers(opts[:headers])
96
+ @body = prepare_body(opts[:body])
95
97
  end
96
98
 
97
99
  # Returns new Request with updated uri
@@ -100,12 +102,13 @@ module HTTP
100
102
  headers.delete(Headers::HOST)
101
103
 
102
104
  self.class.new(
103
- :verb => verb,
104
- :uri => @uri.join(uri),
105
- :headers => headers,
106
- :proxy => proxy,
107
- :body => body.source,
108
- :version => version
105
+ :verb => verb,
106
+ :uri => @uri.join(uri),
107
+ :headers => headers,
108
+ :proxy => proxy,
109
+ :body => body.source,
110
+ :version => version,
111
+ :uri_normalizer => uri_normalizer
109
112
  )
110
113
  end
111
114
 
@@ -213,17 +216,17 @@ module HTTP
213
216
  PORTS[@scheme] != port ? "#{host}:#{port}" : host
214
217
  end
215
218
 
216
- # @return [HTTP::URI] URI with all componentes but query being normalized.
217
- def normalize_uri(uri)
218
- uri = HTTP::URI.parse uri
219
+ def prepare_body(body)
220
+ body.is_a?(Request::Body) ? body : Request::Body.new(body)
221
+ end
219
222
 
220
- HTTP::URI.new(
221
- :scheme => uri.normalized_scheme,
222
- :authority => uri.normalized_authority,
223
- :path => uri.normalized_path,
224
- :query => uri.query,
225
- :fragment => uri.normalized_fragment
226
- )
223
+ def prepare_headers(headers)
224
+ headers = HTTP::Headers.coerce(headers || {})
225
+
226
+ headers[Headers::HOST] ||= default_host_header_value
227
+ headers[Headers::USER_AGENT] ||= USER_AGENT
228
+
229
+ headers
227
230
  end
228
231
  end
229
232
  end
@@ -26,6 +26,19 @@ module HTTP
26
26
  # @private
27
27
  HTTPS_SCHEME = "https"
28
28
 
29
+ # @private
30
+ NORMALIZER = lambda do |uri|
31
+ uri = HTTP::URI.parse uri
32
+
33
+ HTTP::URI.new(
34
+ :scheme => uri.normalized_scheme,
35
+ :authority => uri.normalized_authority,
36
+ :path => uri.normalized_path,
37
+ :query => uri.query,
38
+ :fragment => uri.normalized_fragment
39
+ )
40
+ end
41
+
29
42
  # Parse the given URI string, returning an HTTP::URI object
30
43
  #
31
44
  # @param [HTTP::URI, String, #to_str] uri to parse
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module HTTP
4
- VERSION = "4.0.5"
4
+ VERSION = "4.1.0"
5
5
  end
@@ -430,6 +430,26 @@ RSpec.describe HTTP do
430
430
  expect(response.to_s).to eq("#{body}-deflated")
431
431
  end
432
432
  end
433
+
434
+ context "with :normalize_uri" do
435
+ it "normalizes URI" do
436
+ response = HTTP.get "#{dummy.endpoint}/hello world"
437
+ expect(response.to_s).to eq("hello world")
438
+ end
439
+
440
+ it "uses the custom URI Normalizer method" do
441
+ client = HTTP.use(:normalize_uri => {:normalizer => :itself.to_proc})
442
+ response = client.get("#{dummy.endpoint}/hello world")
443
+ expect(response.status).to eq(400)
444
+ end
445
+
446
+ it "uses the default URI normalizer" do
447
+ client = HTTP.use :normalize_uri
448
+ expect(HTTP::URI::NORMALIZER).to receive(:call).and_call_original
449
+ response = client.get("#{dummy.endpoint}/hello world")
450
+ expect(response.to_s).to eq("hello world")
451
+ end
452
+ end
433
453
  end
434
454
 
435
455
  it "unifies socket errors into HTTP::ConnectionError" do
@@ -148,6 +148,11 @@ class DummyServer < WEBrick::HTTPServer
148
148
  res.body = req.body
149
149
  end
150
150
 
151
+ get "/hello world" do |_req, res|
152
+ res.status = 200
153
+ res.body = "hello world"
154
+ end
155
+
151
156
  post "/encoded-body" do |req, res|
152
157
  res.status = 200
153
158
 
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: 4.0.5
4
+ version: 4.1.0
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: 2019-02-15 00:00:00.000000000 Z
14
+ date: 2019-03-11 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: http_parser.rb
@@ -116,6 +116,7 @@ files:
116
116
  - lib/http/features/auto_inflate.rb
117
117
  - lib/http/features/instrumentation.rb
118
118
  - lib/http/features/logging.rb
119
+ - lib/http/features/normalize_uri.rb
119
120
  - lib/http/headers.rb
120
121
  - lib/http/headers/known.rb
121
122
  - lib/http/headers/mixin.rb
@@ -197,7 +198,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
197
198
  - !ruby/object:Gem::Version
198
199
  version: '0'
199
200
  requirements: []
200
- rubygems_version: 3.0.1
201
+ rubygems_version: 3.0.3
201
202
  signing_key:
202
203
  specification_version: 4
203
204
  summary: HTTP should be easy