http.rb 1.0.0 → 1.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: c6cf64d373fd047e68f56e4d612f0aa7569c69e183dde7057c7cef706861d7b0
4
- data.tar.gz: e817f97f6747c05c492823dfeea938f45db80fc77fb2ef5adb93e69818a12faa
3
+ metadata.gz: a5f552ac83d2afe5184c79455af215f58e18cc7e0f01e1a8bf684a877f8b9d9a
4
+ data.tar.gz: 274244f8126d9dbb09b17c1a46be7a7c037ecab83ca8ae5af5bc4d7f3463c07b
5
5
  SHA512:
6
- metadata.gz: 466fadc13d04a2333864c0e2c5337454bb6010293f86346d9a8d8ea06f4e577952a3451eb16997f6723882ca4fe8f598784c1675698b56a3f1594a2a39781f0a
7
- data.tar.gz: f52d5e6362127c020091e1d8b2317ad909edf1f3a36e4341f8dba1d8ba92a358ff9fab206eb7e276d7e4e670db7e9af55b885ae9e54224d94d05b6d9563f7d84
6
+ metadata.gz: e0fdfcf607047e62db109a3ec414cebf308b270e2757d510f8f337628f0b235a947f4769a5e78a32abd137ce764f63822ca9ff26ccfc5fbc01db39ead0ef1152
7
+ data.tar.gz: fb725d77aa4f4312803dadd481b62a705dd3286568469a1ae055a609a86d9991583dd69a7110864375b5835eecbba9ab06ad39ffbc4f61e428686787690908c2
data/CHANGELOG CHANGED
@@ -1,5 +1,17 @@
1
1
  # CHANGELOG
2
2
 
3
+ ## 20260609
4
+
5
+ 1.1.0: Basic auth via the options hash.
6
+
7
+ Until now basic authentication was only available through credentials embedded in the URI, which forced callers needing programmatic credentials (notably the webdav gem) to construct their own Net::HTTP request objects and bypass the verb methods entirely. The options hash now accepts username: and password:, extracted the same way no_redirect is, so they never leak through to Net::HTTP. This is additive: URI credentials still work as a fallback, and explicit options take precedence over them.
8
+
9
+ 1. ~ HTTP/request.rb: Extract :username and :password from the options hash; basic_auth now prefers the explicit credentials and falls back to the URI credentials.
10
+ 2. + test/HTTP/basic_auth_test.rb
11
+ 3. ~ README.md: + Basic authentication usage section; document the username and password options.
12
+ 4. ~ HTTP::VERSION: /1.0.0/1.1.0/
13
+ 5. ~ CHANGELOG: + 1.1.0 entry
14
+
3
15
  ## 20260522
4
16
 
5
17
  1.0.0: API stability declaration.
data/README.md CHANGED
@@ -77,6 +77,22 @@ HTTP.post('http://example.com', {a: 1, b: 2}, {'User-Agent'=>'Custom'}, {use_ssl
77
77
  end
78
78
  ```
79
79
 
80
+ ### Basic authentication
81
+
82
+ Pass `username:` and `password:` through the options hash:
83
+
84
+ ```ruby
85
+ HTTP.get('http://example.com', {}, {}, {username: 'alice', password: 'secret'})
86
+ ```
87
+
88
+ Credentials embedded in the URI continue to work and serve as a fallback:
89
+
90
+ ```ruby
91
+ HTTP.get('http://alice:secret@example.com')
92
+ ```
93
+
94
+ When both are supplied, the options hash wins.
95
+
80
96
  ### Preventing redirections
81
97
 
82
98
  ```ruby
@@ -167,12 +183,19 @@ end
167
183
  ```
168
184
 
169
185
  ## Allowed values for the options hash
170
- #### (These pass through to Net::HTTP, except for `no_redirect`.)
186
+ #### (These pass through to Net::HTTP, except for `no_redirect`, `username`, and `password`.)
171
187
 
172
188
  ```Ruby
173
189
  no_redirect
174
190
  # Prevents redirection if a 3xx response is encountered.
175
191
 
192
+ username
193
+ # Username for HTTP basic authentication. Takes precedence over any
194
+ # credentials embedded in the URI.
195
+
196
+ password
197
+ # Password for HTTP basic authentication, paired with username.
198
+
176
199
  ca_file
177
200
  # Sets path of a CA certification file in PEM format.
178
201
  #
data/lib/HTTP/VERSION.rb CHANGED
@@ -2,5 +2,5 @@
2
2
  # HTTP::VERSION
3
3
 
4
4
  module HTTP
5
- VERSION = '1.0.0'
5
+ VERSION = '1.1.0'
6
6
  end
data/lib/HTTP/request.rb CHANGED
@@ -16,13 +16,19 @@ module HTTP
16
16
  uri = uri.is_a?(URI) ? uri : URI.parse(uri)
17
17
  http = Net::HTTP.new(uri.host, uri.port)
18
18
  no_redirect = options.delete(:no_redirect)
19
+ username = options.delete(:username)
20
+ password = options.delete(:password)
19
21
  config = retry_config(options)
20
22
  http.options = options.merge(
21
23
  use_ssl: (options[:use_ssl] || uri.use_ssl?),
22
24
  verify_mode: (options[:verify_mode] || OpenSSL::SSL::VERIFY_PEER)
23
25
  )
24
26
  request_object.headers = headers
25
- request_object.basic_auth(uri.user, uri.password) if uri.user
27
+ if username
28
+ request_object.basic_auth(username, password)
29
+ elsif uri.user
30
+ request_object.basic_auth(uri.user, uri.password)
31
+ end
26
32
  verb = request_object.method.downcase.to_sym
27
33
  response = (
28
34
  if config[:retries] > 0 && config[:verbs].include?(verb)
@@ -0,0 +1,106 @@
1
+ # test/HTTP/basic_auth_test.rb
2
+
3
+ require_relative '../helper'
4
+
5
+ describe "basic auth" do
6
+ describe "via the options hash" do
7
+ let(:uri){'http://example.com/path'}
8
+ let(:parsed_uri){URI.parse(uri)}
9
+
10
+ before do
11
+ stub_request(:get, uri).
12
+ to_return(status: 200, body: '', headers: {})
13
+ end
14
+
15
+ it "sets the Authorization header from the username and password options" do
16
+ request_object = Net::HTTP::Get.new(parsed_uri.request_uri)
17
+ Net::HTTP::Get.stub(:new, request_object) do
18
+ response = HTTP.get(uri, {}, {}, {username: 'alice', password: 'secret'})
19
+ _(request_object['Authorization']).must_equal("Basic #{['alice:secret'].pack('m0')}")
20
+ _(response.success?).must_equal(true)
21
+ end
22
+ end
23
+ end
24
+
25
+ describe "via the URI" do
26
+ let(:uri){'http://alice:secret@example.com/path'}
27
+ let(:parsed_uri){URI.parse(uri)}
28
+
29
+ before do
30
+ stub_request(:get, 'http://example.com/path').
31
+ to_return(status: 200, body: '', headers: {})
32
+ end
33
+
34
+ it "sets the Authorization header from the embedded credentials" do
35
+ request_object = Net::HTTP::Get.new(parsed_uri.request_uri)
36
+ Net::HTTP::Get.stub(:new, request_object) do
37
+ response = HTTP.get(uri)
38
+ _(request_object['Authorization']).must_equal("Basic #{['alice:secret'].pack('m0')}")
39
+ _(response.success?).must_equal(true)
40
+ end
41
+ end
42
+ end
43
+
44
+ describe "with a username but no password" do
45
+ let(:uri){'http://example.com/path'}
46
+ let(:parsed_uri){URI.parse(uri)}
47
+
48
+ before do
49
+ stub_request(:get, uri).
50
+ to_return(status: 200, body: '', headers: {})
51
+ end
52
+
53
+ it "sends an empty password" do
54
+ request_object = Net::HTTP::Get.new(parsed_uri.request_uri)
55
+ Net::HTTP::Get.stub(:new, request_object) do
56
+ response = HTTP.get(uri, {}, {}, {username: 'alice'})
57
+ _(request_object['Authorization']).must_equal("Basic #{['alice:'].pack('m0')}")
58
+ _(response.success?).must_equal(true)
59
+ end
60
+ end
61
+ end
62
+
63
+ describe "with credentials in both the options hash and the URI" do
64
+ let(:uri){'http://alice:secret@example.com/path'}
65
+ let(:parsed_uri){URI.parse(uri)}
66
+
67
+ before do
68
+ stub_request(:get, 'http://example.com/path').
69
+ to_return(status: 200, body: '', headers: {})
70
+ end
71
+
72
+ it "prefers the options credentials over the URI credentials" do
73
+ request_object = Net::HTTP::Get.new(parsed_uri.request_uri)
74
+ Net::HTTP::Get.stub(:new, request_object) do
75
+ response = HTTP.get(uri, {}, {}, {username: 'bob', password: 'hunter2'})
76
+ _(request_object['Authorization']).must_equal("Basic #{['bob:hunter2'].pack('m0')}")
77
+ _(response.success?).must_equal(true)
78
+ end
79
+ end
80
+ end
81
+
82
+ describe "leakage into Net::HTTP options" do
83
+ let(:uri){'http://example.com/path'}
84
+ let(:parsed_uri){URI.parse(uri)}
85
+
86
+ before do
87
+ stub_request(:get, uri).
88
+ to_return(status: 200, body: '', headers: {})
89
+ end
90
+
91
+ it "does not pass the auth options through to Net::HTTP" do
92
+ passed_options = nil
93
+ net_http_object = Net::HTTP.new(parsed_uri.host, parsed_uri.port)
94
+ original_options_setter = net_http_object.method(:options=)
95
+ net_http_object.define_singleton_method(:options=) do |options|
96
+ passed_options = options
97
+ original_options_setter.call(options)
98
+ end
99
+ Net::HTTP.stub(:new, net_http_object) do
100
+ HTTP.get(uri, {}, {}, {username: 'alice', password: 'secret'})
101
+ end
102
+ _(passed_options.key?(:username)).must_equal(false)
103
+ _(passed_options.key?(:password)).must_equal(false)
104
+ end
105
+ end
106
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: http.rb
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - thoran
@@ -105,6 +105,7 @@ files:
105
105
  - lib/String/url_encode.rb
106
106
  - lib/URI/Generic/use_sslQ.rb
107
107
  - test/HTTP/RETRY_test.rb
108
+ - test/HTTP/basic_auth_test.rb
108
109
  - test/HTTP/delete_test.rb
109
110
  - test/HTTP/get_test.rb
110
111
  - test/HTTP/head_test.rb
@@ -133,7 +134,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
133
134
  - !ruby/object:Gem::Version
134
135
  version: '0'
135
136
  requirements: []
136
- rubygems_version: 4.0.12
137
+ rubygems_version: 4.0.13
137
138
  specification_version: 4
138
139
  summary: HTTP made easy.
139
140
  test_files: []