dagger 1.3.1 → 1.4.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: 07a24eae2c885b03f8f211c0ef2ec2d15e0e8aebce60338069376c0e6227a7cb
4
- data.tar.gz: 33bebffa563c1731c41fe5a9f50d94dacaf782f5bb61bdb831904234c7f86571
3
+ metadata.gz: 85a53a6a5acd40ecd63cfbdf54a876d2d341626e9f5dcd2daffef6c223e89cdb
4
+ data.tar.gz: b18df51d7d507d68686cff2b4d08a204511f92a812aed2ba60c3f4833d3c7d27
5
5
  SHA512:
6
- metadata.gz: ba8239c876e311a2e675941fe819dc4dc97e0174511d57444c8f42ce2b72681679bc652cb6b6b0b0748bfd53bec03f10b0c27f37258dfa11598273fc7de6fccd
7
- data.tar.gz: afc2b9d3c96eec74db16887604afe200feb6060fe8e6c31d6dff2e380c4fa2f59ce73bd0e21f5aa735586174bbc7e8d5ae904129800239c0df59b7902de31e89
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
@@ -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
 
@@ -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' => "Dagger/#{VERSION} (Ruby Net::HTTP Wrapper, like curl)"
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 = Net::HTTP.new(uri.host, uri.port)
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
- opts[:follow] = 10 if opts[:follow] == true
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(path, DEFAULT_HEADERS.merge(headers))
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
- @http.start unless @http.started?
83
- resp, data = @http.request(request)
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 = Utils.parse_uri(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'] = "Basic " + Base64.encode64(str)
165
+ headers['Authorization'] = 'Basic ' + Base64.encode64(str)
142
166
  end
143
167
 
144
- args = [method.to_s.downcase, uri.path, query, headers]
145
- args.delete_at(2) if args[0] == 'delete' # Net::HTTP's delete does not accept data
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.start do
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
- @http.finish if @http.started?
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
- client.open(&block) if block_given?
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
 
@@ -1,7 +1,7 @@
1
1
  module Dagger
2
2
  MAJOR = 1
3
- MINOR = 3
4
- PATCH = 1
3
+ MINOR = 4
4
+ PATCH = 0
5
5
 
6
6
  VERSION = [MAJOR, MINOR, PATCH].join('.')
7
7
  end
@@ -23,7 +23,7 @@ describe 'arguments' do
23
23
  describe 'invalid URL' do
24
24
 
25
25
  it 'raises error' do
26
- expect { send_request('asd123.rewqw') }.to raise_error(SocketError)
26
+ expect { send_request('asd123.rewqw') }.to raise_error(ArgumentError)
27
27
  end
28
28
 
29
29
  end
@@ -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.3.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-08-24 00:00:00.000000000 Z
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