http.rb 1.1.0 → 1.2.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 +4 -4
- data/CHANGELOG +13 -0
- data/README.md +14 -0
- data/lib/HTTP/VERSION.rb +1 -1
- data/lib/HTTP/verbs.rb +28 -20
- data/test/HTTP/request_with_body_test.rb +76 -0
- data/test/HTTP/request_without_body_test.rb +53 -0
- metadata +3 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 448e7dce1f8dc9a0b23a659b351d10e241ccf1e3cf853663046ec4d7e6e0c8fe
|
|
4
|
+
data.tar.gz: 75123ecd90c4f5333b8c9a6d62435ab20b46623a5871eb8464a224a92c900ed1
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 7fadfa5b0e33af922edc397877c6fecdff9fd0e5fdb2c8bbb17b9aaeb33f7cddc61553129e1ae6dafc7ee7367a4e1e0a71fa380119020dafbb50e66873f2333c
|
|
7
|
+
data.tar.gz: d5b35c43b60b13b3e34b1b56a5d02189266401ccb3a9d63b9d87ead07330f96efb80e2577391eea8ed0ec2a734050d7b22aa0fb21e50cfe334b53ca700ede7a6
|
data/CHANGELOG
CHANGED
|
@@ -2,6 +2,19 @@
|
|
|
2
2
|
|
|
3
3
|
## 20260609
|
|
4
4
|
|
|
5
|
+
1.2.0: Extract request_without_body and request_with_body.
|
|
6
|
+
|
|
7
|
+
The logic for building request objects — constructing the Net::HTTP request class, encoding bodies, and assembling query strings — lived inside the define_method loops and was unreachable except through the eight named methods. Downstream gems needing a method without a named helper (notably webdav's PROPFIND) had to build raw Net::HTTP request objects and bypass that logic entirely. Those two loop bodies are now module functions, callable directly as HTTP.request_without_body(method, ...) and HTTP.request_with_body(method, ...); the named methods delegate to them and behave identically.
|
|
8
|
+
|
|
9
|
+
1. ~ HTTP/verbs.rb: + request_without_body() and request_with_body() module functions; the WITHOUT_BODY and WITH_BODY define_method loops now delegate to them.
|
|
10
|
+
2. + test/HTTP/request_without_body_test.rb
|
|
11
|
+
3. + test/HTTP/request_with_body_test.rb
|
|
12
|
+
4. ~ README.md: + Constructing requests for other methods section.
|
|
13
|
+
5. ~ HTTP::VERSION: /1.1.0/1.2.0/
|
|
14
|
+
6. ~ CHANGELOG: + 1.2.0 entry
|
|
15
|
+
|
|
16
|
+
## 20260609
|
|
17
|
+
|
|
5
18
|
1.1.0: Basic auth via the options hash.
|
|
6
19
|
|
|
7
20
|
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.
|
data/README.md
CHANGED
|
@@ -182,6 +182,20 @@ class A
|
|
|
182
182
|
end
|
|
183
183
|
```
|
|
184
184
|
|
|
185
|
+
### Constructing requests for other methods
|
|
186
|
+
|
|
187
|
+
The named methods cover the HTTP methods with a request class in Ruby's `Net::HTTP` stdlib. For anything else — a method without a named helper, such as `PROPFIND` — the same body encoding, query string, and request handling is available directly:
|
|
188
|
+
|
|
189
|
+
```ruby
|
|
190
|
+
# No body — args become a query string:
|
|
191
|
+
HTTP.request_without_body(:propfind, 'http://example.com/path', {depth: 1})
|
|
192
|
+
|
|
193
|
+
# With a body — string passthrough, JSON when the content type says so, form data otherwise:
|
|
194
|
+
HTTP.request_with_body(:propfind, 'http://example.com/path', xml, {'Content-Type' => 'application/xml'})
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
Both take the same `(method, uri, args_or_data, headers, options, &block)` arguments as the named methods, with the method as the first argument, and the named methods delegate to them. For full control over the request object, drop down to `HTTP.request(uri, request_object, headers, options, &block)`.
|
|
198
|
+
|
|
185
199
|
## Allowed values for the options hash
|
|
186
200
|
#### (These pass through to Net::HTTP, except for `no_redirect`, `username`, and `password`.)
|
|
187
201
|
|
data/lib/HTTP/VERSION.rb
CHANGED
data/lib/HTTP/verbs.rb
CHANGED
|
@@ -13,35 +13,43 @@ module HTTP
|
|
|
13
13
|
WITH_BODY = %i{post put patch}
|
|
14
14
|
end
|
|
15
15
|
|
|
16
|
+
def request_without_body(method, uri, args = {}, headers = {}, options = {}, &block)
|
|
17
|
+
uri = uri.is_a?(URI) ? uri : URI.parse(uri)
|
|
18
|
+
request_uri = uri.request_uri
|
|
19
|
+
unless args.empty?
|
|
20
|
+
request_uri += '?' + args.x_www_form_urlencode
|
|
21
|
+
end
|
|
22
|
+
request_object = Net::HTTP.const_get(method.to_s.capitalize).new(request_uri)
|
|
23
|
+
request(uri, request_object, headers, options, &block)
|
|
24
|
+
end
|
|
25
|
+
module_function :request_without_body
|
|
26
|
+
|
|
27
|
+
def request_with_body(method, uri, data = {}, headers = {}, options = {}, &block)
|
|
28
|
+
uri = uri.is_a?(URI) ? uri : URI.parse(uri)
|
|
29
|
+
request_object = Net::HTTP.const_get(method.to_s.capitalize).new(uri.request_uri)
|
|
30
|
+
content_type = headers.find{|k, v| k.downcase == 'content-type'}&.last.to_s
|
|
31
|
+
if data.is_a?(String)
|
|
32
|
+
request_object.body = data
|
|
33
|
+
elsif content_type.start_with?('application/json')
|
|
34
|
+
request_object.body = JSON.dump(data)
|
|
35
|
+
else
|
|
36
|
+
request_object.form_data = data
|
|
37
|
+
end
|
|
38
|
+
request(uri, request_object, headers, options, &block)
|
|
39
|
+
end
|
|
40
|
+
module_function :request_with_body
|
|
41
|
+
|
|
16
42
|
VERBS::WITHOUT_BODY.each do |verb|
|
|
17
43
|
define_method(verb) do |uri, args = {}, headers = {}, options = {}, &block|
|
|
18
|
-
|
|
19
|
-
request_uri = uri.request_uri
|
|
20
|
-
unless args.empty?
|
|
21
|
-
request_uri += '?' + args.x_www_form_urlencode
|
|
22
|
-
end
|
|
23
|
-
request_object = Net::HTTP.const_get(verb.to_s.capitalize).new(request_uri)
|
|
24
|
-
request(uri, request_object, headers, options, &block)
|
|
44
|
+
request_without_body(verb, uri, args, headers, options, &block)
|
|
25
45
|
end
|
|
26
|
-
|
|
27
46
|
module_function verb
|
|
28
47
|
end
|
|
29
48
|
|
|
30
49
|
VERBS::WITH_BODY.each do |verb|
|
|
31
50
|
define_method(verb) do |uri, data = {}, headers = {}, options = {}, &block|
|
|
32
|
-
|
|
33
|
-
request_object = Net::HTTP.const_get(verb.to_s.capitalize).new(uri.request_uri)
|
|
34
|
-
content_type = headers.find{|k, v| k.downcase == 'content-type'}&.last.to_s
|
|
35
|
-
if data.is_a?(String)
|
|
36
|
-
request_object.body = data
|
|
37
|
-
elsif content_type.start_with?('application/json')
|
|
38
|
-
request_object.body = JSON.dump(data)
|
|
39
|
-
else
|
|
40
|
-
request_object.form_data = data
|
|
41
|
-
end
|
|
42
|
-
request(uri, request_object, headers, options, &block)
|
|
51
|
+
request_with_body(verb, uri, data, headers, options, &block)
|
|
43
52
|
end
|
|
44
|
-
|
|
45
53
|
module_function verb
|
|
46
54
|
end
|
|
47
55
|
end
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# test/HTTP/request_with_body_test.rb
|
|
2
|
+
|
|
3
|
+
require_relative '../helper'
|
|
4
|
+
|
|
5
|
+
describe ".request_with_body" do
|
|
6
|
+
let(:uri){'http://example.com/path'}
|
|
7
|
+
let(:parsed_uri){URI.parse(uri)}
|
|
8
|
+
|
|
9
|
+
describe "with a string body" do
|
|
10
|
+
let(:body){'raw body'}
|
|
11
|
+
|
|
12
|
+
before do
|
|
13
|
+
stub_request(:post, 'http://example.com/path').
|
|
14
|
+
with(body: body).
|
|
15
|
+
to_return(status: 200, body: '', headers: {})
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
it "passes the string through unchanged" do
|
|
19
|
+
request_object = Net::HTTP::Post.new(parsed_uri.request_uri)
|
|
20
|
+
Net::HTTP::Post.stub(:new, request_object) do
|
|
21
|
+
response = HTTP.request_with_body(:post, uri, body)
|
|
22
|
+
_(request_object.body).must_equal(body)
|
|
23
|
+
_(response.success?).must_equal(true)
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
describe "with a JSON content type" do
|
|
29
|
+
let(:data){{a: 1, b: 2}}
|
|
30
|
+
let(:headers){{'Content-Type' => 'application/json'}}
|
|
31
|
+
|
|
32
|
+
before do
|
|
33
|
+
stub_request(:post, 'http://example.com/path').
|
|
34
|
+
with(body: JSON.dump(data)).
|
|
35
|
+
to_return(status: 200, body: '', headers: {})
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
it "JSON-encodes the data" do
|
|
39
|
+
request_object = Net::HTTP::Post.new(parsed_uri.request_uri)
|
|
40
|
+
Net::HTTP::Post.stub(:new, request_object) do
|
|
41
|
+
response = HTTP.request_with_body(:post, uri, data, headers)
|
|
42
|
+
_(request_object.body).must_equal(JSON.dump(data))
|
|
43
|
+
_(response.success?).must_equal(true)
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
describe "with no content type" do
|
|
49
|
+
let(:data){{a: 1, b: 2}}
|
|
50
|
+
|
|
51
|
+
before do
|
|
52
|
+
stub_request(:post, 'http://example.com/path').
|
|
53
|
+
with(body: data.x_www_form_urlencode).
|
|
54
|
+
to_return(status: 200, body: '', headers: {})
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
it "form-encodes the data" do
|
|
58
|
+
request_object = Net::HTTP::Post.new(parsed_uri.request_uri)
|
|
59
|
+
Net::HTTP::Post.stub(:new, request_object) do
|
|
60
|
+
response = HTTP.request_with_body(:post, uri, data)
|
|
61
|
+
_(request_object.body).must_equal(data.x_www_form_urlencode)
|
|
62
|
+
_(response.success?).must_equal(true)
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
describe "delegation from the named method" do
|
|
68
|
+
it "is reached by HTTP.post with the verb prepended" do
|
|
69
|
+
received_args = nil
|
|
70
|
+
HTTP.stub(:request_with_body, ->(*args, &block){received_args = args; nil}) do
|
|
71
|
+
HTTP.post(uri, {a: 1}, {'User-Agent' => 'Minitest'}, {use_ssl: false})
|
|
72
|
+
end
|
|
73
|
+
_(received_args).must_equal([:post, uri, {a: 1}, {'User-Agent' => 'Minitest'}, {use_ssl: false}])
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# test/HTTP/request_without_body_test.rb
|
|
2
|
+
|
|
3
|
+
require_relative '../helper'
|
|
4
|
+
|
|
5
|
+
describe ".request_without_body" do
|
|
6
|
+
let(:uri){'http://example.com/path'}
|
|
7
|
+
let(:parsed_uri){URI.parse(uri)}
|
|
8
|
+
|
|
9
|
+
describe "without args" do
|
|
10
|
+
before do
|
|
11
|
+
stub_request(:get, 'http://example.com/path').
|
|
12
|
+
to_return(status: 200, body: '', headers: {})
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
it "builds the request object for the given method" do
|
|
16
|
+
received_arg = nil
|
|
17
|
+
request_object = Net::HTTP::Get.new(parsed_uri.request_uri)
|
|
18
|
+
Net::HTTP::Get.stub(:new, ->(arg){received_arg = arg; request_object}) do
|
|
19
|
+
response = HTTP.request_without_body(:get, uri)
|
|
20
|
+
_(received_arg).must_equal(parsed_uri.request_uri)
|
|
21
|
+
_(response.success?).must_equal(true)
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
describe "with args" do
|
|
27
|
+
before do
|
|
28
|
+
stub_request(:get, 'http://example.com/path?a=1&b=2').
|
|
29
|
+
to_return(status: 200, body: '', headers: {})
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
it "appends the encoded query string to the request uri" do
|
|
33
|
+
received_arg = nil
|
|
34
|
+
request_uri = parsed_uri.request_uri + '?a=1&b=2'
|
|
35
|
+
request_object = Net::HTTP::Get.new(request_uri)
|
|
36
|
+
Net::HTTP::Get.stub(:new, ->(arg){received_arg = arg; request_object}) do
|
|
37
|
+
response = HTTP.request_without_body(:get, uri, {a: 1, b: 2})
|
|
38
|
+
_(received_arg).must_equal(request_uri)
|
|
39
|
+
_(response.success?).must_equal(true)
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
describe "delegation from the named method" do
|
|
45
|
+
it "is reached by HTTP.get with the verb prepended" do
|
|
46
|
+
received_args = nil
|
|
47
|
+
HTTP.stub(:request_without_body, ->(*args, &block){received_args = args; nil}) do
|
|
48
|
+
HTTP.get(uri, {a: 1}, {'User-Agent' => 'Minitest'}, {use_ssl: false})
|
|
49
|
+
end
|
|
50
|
+
_(received_args).must_equal([:get, uri, {a: 1}, {'User-Agent' => 'Minitest'}, {use_ssl: false}])
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
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.
|
|
4
|
+
version: 1.2.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- thoran
|
|
@@ -113,6 +113,8 @@ files:
|
|
|
113
113
|
- test/HTTP/patch_test.rb
|
|
114
114
|
- test/HTTP/post_test.rb
|
|
115
115
|
- test/HTTP/put_test.rb
|
|
116
|
+
- test/HTTP/request_with_body_test.rb
|
|
117
|
+
- test/HTTP/request_without_body_test.rb
|
|
116
118
|
- test/HTTP/trace_test.rb
|
|
117
119
|
- test/Net/HTTPResponse/StatusPredicates_test.rb
|
|
118
120
|
- test/helper.rb
|