dagger 1.3.1 → 1.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/ruby.yml +18 -0
- data/dagger.gemspec +1 -0
- data/lib/dagger.rb +67 -24
- data/lib/dagger/version.rb +2 -2
- data/spec/arguments_spec.rb +1 -1
- data/spec/persistent_spec.rb +1 -0
- metadata +17 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 85a53a6a5acd40ecd63cfbdf54a876d2d341626e9f5dcd2daffef6c223e89cdb
|
4
|
+
data.tar.gz: b18df51d7d507d68686cff2b4d08a204511f92a812aed2ba60c3f4833d3c7d27
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: fde76bd91f86ee78737bc428073f944c5fd2f9e585c50c92a65037b1ece4a424a5851635f30b86ecfdda4db6a072e9a0a20d6b27dc50ab4b286dafd14ca2c047
|
7
|
+
data.tar.gz: 64737c64a0a60fad0b01b3624725ce09aa264e5d582a616520be304277da817e23317ed88081162435057dd27d585a6c4b2b5bab76c78e4719fd68780ab0d830
|
@@ -0,0 +1,18 @@
|
|
1
|
+
name: Ruby
|
2
|
+
on: [push]
|
3
|
+
|
4
|
+
jobs:
|
5
|
+
build:
|
6
|
+
runs-on: ubuntu-latest
|
7
|
+
|
8
|
+
steps:
|
9
|
+
- uses: actions/checkout@v1
|
10
|
+
- name: Set up Ruby 2.6
|
11
|
+
uses: actions/setup-ruby@v1
|
12
|
+
with:
|
13
|
+
ruby-version: 2.6.x
|
14
|
+
- name: Build and test with Rake
|
15
|
+
run: |
|
16
|
+
gem install bundler
|
17
|
+
bundle install --jobs 4 --retry 3
|
18
|
+
bundle exec rspec
|
data/dagger.gemspec
CHANGED
@@ -19,6 +19,7 @@ Gem::Specification.new do |s|
|
|
19
19
|
s.add_development_dependency "rspec-mocks"
|
20
20
|
s.add_development_dependency "rspec-expectations"
|
21
21
|
|
22
|
+
s.add_runtime_dependency "net-http-persistent", "~> 3.0"
|
22
23
|
s.add_runtime_dependency "oj", "~> 2.1"
|
23
24
|
s.add_runtime_dependency "ox", "~> 2.4"
|
24
25
|
|
data/lib/dagger.rb
CHANGED
@@ -2,16 +2,24 @@ require 'dagger/version'
|
|
2
2
|
require 'dagger/response'
|
3
3
|
require 'dagger/parsers'
|
4
4
|
|
5
|
+
require 'net/http/persistent'
|
5
6
|
require 'net/https'
|
6
7
|
require 'base64'
|
7
8
|
|
9
|
+
class URI::HTTP
|
10
|
+
def scheme_and_host
|
11
|
+
[scheme, host].join('://')
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
8
15
|
module Dagger
|
9
16
|
|
17
|
+
DAGGER_NAME = "Dagger/#{VERSION}"
|
10
18
|
REDIRECT_CODES = [301, 302, 303].freeze
|
11
19
|
DEFAULT_RETRY_WAIT = 5.freeze # seconds
|
12
20
|
DEFAULT_HEADERS = {
|
13
21
|
'Accept' => '*/*',
|
14
|
-
'User-Agent' => "
|
22
|
+
'User-Agent' => "#{DAGGER_NAME} (Ruby Net::HTTP Wrapper, like curl)"
|
15
23
|
}
|
16
24
|
|
17
25
|
module Utils
|
@@ -25,6 +33,13 @@ module Dagger
|
|
25
33
|
uri
|
26
34
|
end
|
27
35
|
|
36
|
+
def self.resolve_uri(uri, host = nil, query = nil)
|
37
|
+
uri = host + uri if uri.to_s['//'].nil? && host
|
38
|
+
uri = parse_uri(uri.to_s)
|
39
|
+
uri.path.sub!(/\?.*|$/, '?' + Utils.encode(query)) if query and query.any?
|
40
|
+
uri
|
41
|
+
end
|
42
|
+
|
28
43
|
def self.encode(obj, key = nil)
|
29
44
|
if key.nil? && obj.is_a?(String) # && obj['=']
|
30
45
|
return obj
|
@@ -49,10 +64,14 @@ module Dagger
|
|
49
64
|
|
50
65
|
def self.init(uri, opts)
|
51
66
|
uri = Utils.parse_uri(uri)
|
52
|
-
http =
|
67
|
+
http = if opts.delete(:persistent)
|
68
|
+
Net::HTTP::Persistent.new(name: DAGGER_NAME)
|
69
|
+
else
|
70
|
+
Net::HTTP.new(uri.host, uri.port)
|
71
|
+
end
|
53
72
|
|
54
73
|
if uri.port == 443
|
55
|
-
http.use_ssl = true
|
74
|
+
http.use_ssl = true if http.respond_to?(:use_ssl) # persistent does it automatically
|
56
75
|
http.verify_mode = opts[:verify_ssl] === false ? OpenSSL::SSL::VERIFY_NONE : OpenSSL::SSL::VERIFY_PEER
|
57
76
|
end
|
58
77
|
|
@@ -60,27 +79,31 @@ module Dagger
|
|
60
79
|
http.send("#{key}=", opts[key]) if opts.has_key?(key)
|
61
80
|
end
|
62
81
|
|
63
|
-
new(http)
|
82
|
+
# new(http, [uri.scheme, uri.host].join('://'))
|
83
|
+
new(http, uri.scheme_and_host)
|
64
84
|
end
|
65
85
|
|
66
|
-
def initialize(http)
|
67
|
-
@http = http
|
86
|
+
def initialize(http, host = nil)
|
87
|
+
@http, @host = http, host
|
68
88
|
end
|
69
89
|
|
70
90
|
def get(uri, opts = {})
|
71
|
-
|
72
|
-
|
73
|
-
path = uri[0] == '/' ? uri : Utils.parse_uri(uri).request_uri
|
74
|
-
path.sub!(/\?.*|$/, '?' + Utils.encode(opts[:query])) if opts[:query] and opts[:query].any?
|
91
|
+
uri = Utils.resolve_uri(uri, @host, opts[:query])
|
92
|
+
raise ArgumentError.new("#{uri.scheme_and_host} does not match #{@host}") if @host != uri.scheme_and_host
|
75
93
|
|
94
|
+
opts[:follow] = 10 if opts[:follow] == true
|
76
95
|
headers = opts[:headers] || {}
|
77
96
|
headers['Accept'] = 'application/json' if opts[:json]
|
78
97
|
|
79
|
-
request = Net::HTTP::Get.new(
|
98
|
+
request = Net::HTTP::Get.new(uri, DEFAULT_HEADERS.merge(headers))
|
80
99
|
request.basic_auth(opts.delete(:username), opts.delete(:password)) if opts[:username]
|
81
100
|
|
82
|
-
|
83
|
-
|
101
|
+
if @http.respond_to?(:started?) # regular Net::HTTP
|
102
|
+
@http.start unless @http.started?
|
103
|
+
resp, data = @http.request(request)
|
104
|
+
else # persistent
|
105
|
+
resp, data = @http.request(uri, request)
|
106
|
+
end
|
84
107
|
|
85
108
|
if REDIRECT_CODES.include?(resp.code.to_i) && resp['Location'] && (opts[:follow] && opts[:follow] > 0)
|
86
109
|
opts[:follow] -= 1
|
@@ -124,7 +147,8 @@ module Dagger
|
|
124
147
|
return get(uri, opts.merge(query: query))
|
125
148
|
end
|
126
149
|
|
127
|
-
uri
|
150
|
+
uri = Utils.resolve_uri(uri, @host)
|
151
|
+
raise ArgumentError.new("#{uri.scheme_and_host} does not match #{@host}") if @host != uri.scheme_and_host
|
128
152
|
headers = DEFAULT_HEADERS.merge(opts[:headers] || {})
|
129
153
|
|
130
154
|
query = if data.is_a?(String)
|
@@ -138,21 +162,29 @@ module Dagger
|
|
138
162
|
|
139
163
|
if opts[:username] # opts[:password] is optional
|
140
164
|
str = [opts[:username], opts[:password]].compact.join(':')
|
141
|
-
headers['Authorization'] =
|
165
|
+
headers['Authorization'] = 'Basic ' + Base64.encode64(str)
|
142
166
|
end
|
143
167
|
|
144
|
-
|
145
|
-
|
168
|
+
if @http.respond_to?(:started?) # regular Net::HTTP
|
169
|
+
args = [method.to_s.downcase, uri.path, query, headers]
|
170
|
+
args.delete_at(2) if args[0] == 'delete' # Net::HTTP's delete does not accept data
|
171
|
+
|
172
|
+
@http.start unless @http.started?
|
173
|
+
resp, data = @http.send(*args)
|
174
|
+
else # Net::HTTP::Persistent
|
175
|
+
req = Kernel.const_get("Net::HTTP::#{method.capitalize}").new(uri.path, headers)
|
176
|
+
req.set_form_data(query)
|
177
|
+
|
178
|
+
resp, data = @http.request(uri, req)
|
179
|
+
end
|
146
180
|
|
147
|
-
@http.start unless @http.started?
|
148
|
-
resp, data = @http.send(*args)
|
149
181
|
@response = build_response(resp, data || resp.body)
|
150
182
|
|
151
183
|
rescue Errno::ECONNREFUSED, Errno::ECONNRESET, Errno::ETIMEDOUT, Errno::EINVAL, Timeout::Error, \
|
152
184
|
SocketError, EOFError, Net::HTTPBadResponse, Net::HTTPHeaderSyntaxError, Net::ProtocolError, OpenSSL::SSL::SSLError => e
|
153
185
|
|
154
186
|
if method.to_s.downcase != 'get' && retries = opts[:retries] and retries.to_i > 0
|
155
|
-
puts "Got #{e.class}! Retrying in a sec (#{retries} retries left)"
|
187
|
+
puts "[#{DAGGER_NAME}] Got #{e.class}! Retrying in a sec (#{retries} retries left)"
|
156
188
|
sleep (opts[:retry_wait] || DEFAULT_RETRY_WAIT)
|
157
189
|
request(method, uri, data, opts.merge(retries: retries - 1))
|
158
190
|
else
|
@@ -165,13 +197,21 @@ module Dagger
|
|
165
197
|
end
|
166
198
|
|
167
199
|
def open(&block)
|
168
|
-
@http.
|
200
|
+
if @http.is_a?(Net::HTTP::Persistent)
|
169
201
|
instance_eval(&block)
|
202
|
+
else
|
203
|
+
@http.start do
|
204
|
+
instance_eval(&block)
|
205
|
+
end
|
170
206
|
end
|
171
207
|
end
|
172
208
|
|
173
209
|
def close
|
174
|
-
|
210
|
+
if @http.is_a?(Net::HTTP::Persistent)
|
211
|
+
@http.shutdown # calls finish on pool connections
|
212
|
+
else
|
213
|
+
@http.finish if @http.started?
|
214
|
+
end
|
175
215
|
end
|
176
216
|
|
177
217
|
private
|
@@ -187,8 +227,11 @@ module Dagger
|
|
187
227
|
class << self
|
188
228
|
|
189
229
|
def open(uri, opts = {}, &block)
|
190
|
-
client = Client.init(uri, opts)
|
191
|
-
|
230
|
+
client = Client.init(uri, opts.merge(persistent: true))
|
231
|
+
if block_given?
|
232
|
+
client.open(&block)
|
233
|
+
client.close
|
234
|
+
end
|
192
235
|
client
|
193
236
|
end
|
194
237
|
|
data/lib/dagger/version.rb
CHANGED
data/spec/arguments_spec.rb
CHANGED
data/spec/persistent_spec.rb
CHANGED
@@ -9,6 +9,7 @@ describe 'Persistent mode' do
|
|
9
9
|
fake_client = double('Client')
|
10
10
|
expect(Dagger::Client).to receive(:new).once.and_return(fake_client)
|
11
11
|
expect(fake_client).to receive(:open).once #.and_return(fake_resp)
|
12
|
+
expect(fake_client).to receive(:close).once #.and_return(fake_resp)
|
12
13
|
|
13
14
|
obj = Dagger.open('https://www.google.com') do
|
14
15
|
get('/search?q=dagger+http+client')
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dagger
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tomás Pollak
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-
|
11
|
+
date: 2019-11-19 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -66,6 +66,20 @@ dependencies:
|
|
66
66
|
- - ">="
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: net-http-persistent
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '3.0'
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '3.0'
|
69
83
|
- !ruby/object:Gem::Dependency
|
70
84
|
name: oj
|
71
85
|
requirement: !ruby/object:Gem::Requirement
|
@@ -102,6 +116,7 @@ executables:
|
|
102
116
|
extensions: []
|
103
117
|
extra_rdoc_files: []
|
104
118
|
files:
|
119
|
+
- ".github/workflows/ruby.yml"
|
105
120
|
- ".gitignore"
|
106
121
|
- Gemfile
|
107
122
|
- README.md
|