dagger 0.5.1 → 0.6.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
  SHA1:
3
- metadata.gz: 554b365474524830ac1017cac8b57354d8fed85a
4
- data.tar.gz: be62ee9a3bab4868326fb4cf15db03776e0591bf
3
+ metadata.gz: 212d001704ff60792d0e250469c8271d0ccbdc77
4
+ data.tar.gz: fecce54d5ca8b521df7ee101d1a7f01797562034
5
5
  SHA512:
6
- metadata.gz: f03630f6ccd2603de2aa87cca29987a08dd3de8190ea4eb85820b0a46a3735287a1da5b9c704cd8d6d6d644a7e209c7b4d4c56144117839fb6b71ab630b66937
7
- data.tar.gz: 4dbc25a2e30be77ec37e29e2ecd240a01871e2fa56420524a21aa48c643892289f9f16715e433e7c2cab36bf5bb1616be4109fb57deaf972f18432ebf94dc970
6
+ metadata.gz: 10e9e8a85477e41656a1b7c28b797092903fa017fbe0764504d3bbc5271e170b62929915e24744203c37cbd5f1f2622814dc63395d7d277acad556ca42ca5ff3
7
+ data.tar.gz: a0aafed3e61cdf7e720436fd48ce1ee8dcd203d9806bec82746d4a4e09d8cb6379c5c61911468edbffd0a0f3da6d8a4d67d38c43d3d98a758a1c83269a8427fb
data/Gemfile CHANGED
@@ -1,4 +1,4 @@
1
- source :rubygems
1
+ source 'https://rubygems.org'
2
2
 
3
3
  # specified in tuktuk.gemspec
4
4
  gemspec
data/lib/dagger.rb CHANGED
@@ -10,117 +10,157 @@ module Dagger
10
10
 
11
11
  REDIRECT_CODES = [301, 302, 303].freeze
12
12
  DEFAULT_HEADERS = {
13
- 'Accept' => '*/*',
13
+ 'Accept' => '*/*',
14
14
  'User-Agent' => "Dagger/#{VERSION} (Ruby Net::HTTP Wrapper, like curl)"
15
15
  }
16
16
 
17
- def self.get(uri, query = nil, opts = {})
18
- opts[:follow] = 10 if opts[:follow] == true
17
+ module Utils
19
18
 
20
- uri = parse_uri(uri)
21
- uri.query = encode(query) if query
22
- http = client(uri, opts)
23
- request = Net::HTTP::Get.new(uri.request_uri, DEFAULT_HEADERS.merge(opts[:headers] || {}))
24
-
25
- if opts[:username] # && opts[:password]
26
- request.basic_auth(opts.delete(:username), opts.delete(:password))
19
+ def self.parse_uri(uri)
20
+ uri = 'http://' + uri unless uri.to_s['http']
21
+ uri = URI.parse(uri)
22
+ raise ArgumentError.new("Invalid URI: #{uri}") unless uri.is_a?(URI::HTTP)
23
+ uri.path = '/' if uri.path == ''
24
+ uri
27
25
  end
28
26
 
29
- resp, data = http.request(request)
27
+ def self.encode(value, key = nil)
28
+ case value
29
+ when Hash then value.map { |k,v| encode(v, append_key(key,k)) }.join('&')
30
+ when Array then value.map { |v| encode(v, "#{key}[]") }.join('&')
31
+ when nil then ''
32
+ else
33
+ "#{key}=#{URI.escape(value.to_s)}"
34
+ end
35
+ end
30
36
 
31
- if REDIRECT_CODES.include?(resp.code.to_i) && resp['Location'] && (opts[:follow] && opts[:follow] > 0)
32
- opts[:follow] -= 1
33
- return get(resp['Location'], nil, opts)
37
+ def self.append_key(root_key, key)
38
+ root_key.nil? ? key : "#{root_key}[#{key.to_s}]"
34
39
  end
35
40
 
36
- build_response(resp, data || resp.body) # 1.8 vs 1.9 style responses
37
41
  end
38
42
 
39
- def self.post(uri, params = {}, options = {})
40
- send_request('post', uri, params, options)
41
- end
43
+ class Client
42
44
 
43
- def self.put(uri, params = {}, options = {})
44
- send_request('put', uri, params, options)
45
- end
45
+ def self.init(uri, opts)
46
+ uri = Utils.parse_uri(uri)
47
+ http = Net::HTTP.new(uri.host, uri.port)
46
48
 
47
- def self.delete(uri, params = {}, options = {})
48
- send_request('delete', uri, params, options)
49
- end
49
+ if uri.port == 443
50
+ http.use_ssl = true
51
+ http.verify_mode = opts[:verify_ssl] === false ? OpenSSL::SSL::VERIFY_NONE : OpenSSL::SSL::VERIFY_PEER
52
+ end
50
53
 
51
- def self.request(method, url, params = {}, options = {})
52
- return get(url, params, options) if method.to_s.downcase == 'get'
53
- send_request(method.to_s.downcase, url, params, options)
54
- end
54
+ [:open_timeout, :read_timeout, :ssl_version, :ciphers].each do |key|
55
+ http.send("#{key}=", opts[key]) if opts.has_key?(key)
56
+ end
57
+
58
+ new(http)
59
+ end
60
+
61
+ def initialize(http)
62
+ @http = http
63
+ end
64
+
65
+ def get(uri, opts = {})
66
+ opts[:follow] = 10 if opts[:follow] == true
67
+
68
+ path = uri[0] == '/' ? uri : Utils.parse_uri(uri)
69
+ path.sub!(/\?.*|$/, '?' + Utils.encode(opts[:query])) if opts[:query]
70
+
71
+ request = Net::HTTP::Get.new(path, DEFAULT_HEADERS.merge(opts[:headers] || {}))
72
+ request.basic_auth(opts.delete(:username), opts.delete(:password)) if opts[:username]
73
+
74
+ @resp, @data = @http.request(request)
75
+
76
+ if REDIRECT_CODES.include?(@resp.code.to_i) && @resp['Location'] && (opts[:follow] && opts[:follow] > 0)
77
+ opts[:follow] -= 1
78
+ return get(@resp['Location'], nil, opts)
79
+ end
80
+
81
+ response
82
+ end
83
+
84
+ def request(method, uri, data, opts = {})
85
+ return get(uri, opts.merge(query: data)) if method.to_s.downcase == 'get'
86
+
87
+ uri = Utils.parse_uri(uri)
88
+ headers = DEFAULT_HEADERS.merge(opts[:headers] || {})
89
+
90
+ query = if data.is_a?(String)
91
+ data
92
+ elsif opts[:json]
93
+ Oj.dump(data) # convert to JSON
94
+ headers['Content-Type'] = 'application/json'
95
+ else # querystring, then
96
+ Utils.encode(data)
97
+ end
55
98
 
56
- private
99
+ if opts[:username] # opts[:password] is optional
100
+ str = [opts[:username], opts[:password]].compact.join(':')
101
+ headers['Authorization'] = "Basic " + Base64.encode64(str)
102
+ end
57
103
 
58
- def self.send_request(method, uri, params, opts = {})
59
- uri = parse_uri(uri)
60
- headers = opts[:headers] || {}
104
+ args = [method.to_s.downcase, uri.path, query, headers]
105
+ args.delete_at(2) if args[0] == 'delete' # Net::HTTP's delete does not accept data
61
106
 
62
- query = if params.is_a?(String)
63
- params
64
- elsif opts[:json]
65
- Oj.dump(params) # convert to JSON
66
- headers['Content-Type'] = 'application/json'
67
- else
68
- encode(params)
107
+ @resp, @data = @http.send(*args)
108
+ response
69
109
  end
70
110
 
71
- if opts[:username] # opts[:password] is optional
72
- str = [opts[:username], opts[:password]].compact.join(':')
73
- headers['Authorization'] = "Basic " + Base64.encode64(str)
111
+ def response
112
+ raise 'No response yet!' unless @resp
113
+ @response ||= build_response(@resp, @data || @resp.body) # 1.8 vs 1.9 style responses
74
114
  end
75
115
 
76
- args = [method, uri.path, query, headers]
77
- args.delete_at(2) if method.to_s == 'delete' # Net::HTTP's delete does not accept data
116
+ private
78
117
 
79
- resp, data = client(uri, opts).send(*args)
80
- build_response(resp, data || resp.body) # 1.8 vs 1.9 style responses
81
- end
118
+ def build_response(resp, body)
119
+ resp.extend(Response)
120
+ resp.set_body(body) unless resp.body
121
+ resp
122
+ end
82
123
 
83
- def self.build_response(resp, body)
84
- resp.extend(Response)
85
- resp.set_body(body) unless resp.body
86
- resp
87
124
  end
88
125
 
89
- def self.client(uri, opts = {})
90
- http = Net::HTTP.new(uri.host, uri.port)
126
+ class << self
91
127
 
92
- if uri.port == 443
93
- http.use_ssl = true
94
- http.verify_mode = opts[:verify_ssl] === false ? OpenSSL::SSL::VERIFY_NONE : OpenSSL::SSL::VERIFY_PEER
128
+ def open(uri, opts = {}, &block)
129
+ uri = Utils.parse_uri(uri)
130
+ opts.merge!(use_ssl: uri.scheme == 'https')
131
+ opts.merge!(verify_mode: OpenSSL::SSL::VERIFY_NONE) if opts[:verify_ssl] === false
132
+
133
+ Net::HTTP.start(uri.host, uri.port, opts) do |http|
134
+ client = Client.new(http)
135
+ # yield(client)
136
+ client.instance_eval(&block)
137
+ end
95
138
  end
96
139
 
97
- [:open_timeout, :read_timeout, :ssl_version, :ciphers].each do |key|
98
- http.send("#{key}=", opts[key]) if opts.has_key?(key)
140
+ def get(uri, options = {})
141
+ request(:get, uri, nil, options)
99
142
  end
100
143
 
101
- http
102
- end
144
+ def post(uri, data, options = {})
145
+ request(:post, uri, data, options)
146
+ end
103
147
 
104
- def self.parse_uri(uri)
105
- uri = 'http://' + uri unless uri.to_s['http']
106
- uri = URI.parse(uri)
107
- raise ArgumentError.new("Invalid URI: #{uri}") unless uri.is_a?(URI::HTTP)
108
- uri.path = '/' if uri.path == ''
109
- uri
110
- end
148
+ def put(uri, data, options = {})
149
+ request(:put, uri, data, options)
150
+ end
111
151
 
112
- def self.encode(value, key = nil)
113
- case value
114
- when Hash then value.map { |k,v| encode(v, append_key(key,k)) }.join('&')
115
- when Array then value.map { |v| encode(v, "#{key}[]") }.join('&')
116
- when nil then ''
117
- else
118
- "#{key}=#{URI.escape(value.to_s)}"
152
+ def patch(uri, data, options = {})
153
+ request(:patch, uri, data, options)
154
+ end
155
+
156
+ def delete(uri, data, options = {})
157
+ request(:delete, uri, data, options)
158
+ end
159
+
160
+ def request(method, url, data = {}, options = {})
161
+ Client.init(url, options).request(method, url, data, options)
119
162
  end
120
- end
121
163
 
122
- def self.append_key(root_key, key)
123
- root_key.nil? ? key : "#{root_key}[#{key.to_s}]"
124
164
  end
125
165
 
126
166
  end
@@ -1,8 +1,32 @@
1
1
  require 'ox'
2
2
 
3
3
  XMLNode = Struct.new(:name, :text, :attributes, :children) do
4
+ # this lets us traverse an parsed object like this:
5
+ # doc[:child][:grandchild].value
4
6
  def [](key)
5
- children.select { |node| node.name.to_s == key.to_s }.first
7
+ found = children.select { |node| node.name.to_s == key.to_s }
8
+ found.empty? ? nil : found.size == 1 ? found.first : found
9
+ end
10
+
11
+ # returns first matching node
12
+ def first(key)
13
+ if found = self[key]
14
+ found.is_a?(XMLNode) ? found : found.first
15
+ else
16
+ children.find do |ch|
17
+ if res = ch.first(key)
18
+ return res
19
+ end
20
+ end
21
+ end
22
+ end
23
+
24
+ # returns all matching nodes
25
+ def all(key)
26
+ found = self[key]
27
+ direct = found.is_a?(XMLNode) ? [found] : found || []
28
+ indirect = children.map { |ch| ch.all(key) }.flatten.compact
29
+ direct + indirect
6
30
  end
7
31
  end
8
32
 
@@ -1,7 +1,7 @@
1
1
  module Dagger
2
2
  MAJOR = 0
3
- MINOR = 5
4
- PATCH = 1
3
+ MINOR = 6
4
+ PATCH = 0
5
5
 
6
6
  VERSION = [MAJOR, MINOR, PATCH].join('.')
7
7
  end
data/test/parsers_spec.rb CHANGED
@@ -6,7 +6,7 @@ require 'rspec/expectations'
6
6
  describe 'Parsers' do
7
7
 
8
8
  def send_request
9
- Dagger.get('http://foobar.com/test')
9
+ Dagger.post('http://foobar.com/test', { foo: 'bar'})
10
10
  end
11
11
 
12
12
  let(:fake_http) { double('Net::HTTP') }
@@ -15,7 +15,7 @@ describe 'Parsers' do
15
15
  before do
16
16
  allow(Net::HTTP).to receive(:new).and_return(fake_http)
17
17
  allow(fake_http).to receive(:verify_mode=).and_return(true)
18
- allow(fake_http).to receive(:request).and_return(fake_resp)
18
+ allow(fake_http).to receive(:post).and_return(fake_resp)
19
19
  end
20
20
 
21
21
  describe 'json' do
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: 0.5.1
4
+ version: 0.6.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: 2016-11-24 00:00:00.000000000 Z
11
+ date: 2016-12-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -114,7 +114,6 @@ files:
114
114
  - lib/dagger/response.rb
115
115
  - lib/dagger/version.rb
116
116
  - test/parsers_spec.rb
117
- - test/requests_spec.rb
118
117
  homepage: https://github.com/tomas/dagger
119
118
  licenses: []
120
119
  metadata: {}
@@ -1,48 +0,0 @@
1
- require './lib/dagger'
2
-
3
- require 'rspec/mocks'
4
- require 'rspec/expectations'
5
-
6
- describe 'Requests' do
7
-
8
- describe '.get' do
9
-
10
- def send_request(url)
11
- Dagger.get(url)
12
- end
13
-
14
- describe 'empty url' do
15
-
16
- it 'raises error' do
17
- expect { send_request('') }.to raise_error(ArgumentError)
18
- end
19
-
20
- end
21
-
22
- describe 'invalid URL' do
23
-
24
- it 'raises error' do
25
- expect { send_request('asd123.rewqw') }.to raise_error(SocketError)
26
- end
27
-
28
- end
29
-
30
- describe 'nonexisting host' do
31
-
32
- it 'raises error' do
33
- expect { send_request('http://www.foobar1234567890foobar.com/hello') }.to raise_error(SocketError)
34
- end
35
-
36
- end
37
-
38
- describe 'valid host' do
39
-
40
- it 'works' do
41
- expect(send_request('http://www.google.com')).to be_a(Net::HTTPResponse)
42
- end
43
-
44
- end
45
-
46
- end
47
-
48
- end