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 +4 -4
- data/Gemfile +1 -1
- data/lib/dagger.rb +117 -77
- data/lib/dagger/ox_extension.rb +25 -1
- data/lib/dagger/version.rb +2 -2
- data/test/parsers_spec.rb +2 -2
- metadata +2 -3
- data/test/requests_spec.rb +0 -48
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 212d001704ff60792d0e250469c8271d0ccbdc77
|
4
|
+
data.tar.gz: fecce54d5ca8b521df7ee101d1a7f01797562034
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 10e9e8a85477e41656a1b7c28b797092903fa017fbe0764504d3bbc5271e170b62929915e24744203c37cbd5f1f2622814dc63395d7d277acad556ca42ca5ff3
|
7
|
+
data.tar.gz: a0aafed3e61cdf7e720436fd48ce1ee8dcd203d9806bec82746d4a4e09d8cb6379c5c61911468edbffd0a0f3da6d8a4d67d38c43d3d98a758a1c83269a8427fb
|
data/Gemfile
CHANGED
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
|
-
|
18
|
-
opts[:follow] = 10 if opts[:follow] == true
|
17
|
+
module Utils
|
19
18
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
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
|
-
|
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
|
-
|
32
|
-
|
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
|
-
|
40
|
-
send_request('post', uri, params, options)
|
41
|
-
end
|
43
|
+
class Client
|
42
44
|
|
43
|
-
|
44
|
-
|
45
|
-
|
45
|
+
def self.init(uri, opts)
|
46
|
+
uri = Utils.parse_uri(uri)
|
47
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
46
48
|
|
47
|
-
|
48
|
-
|
49
|
-
|
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
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
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
|
-
|
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
|
-
|
59
|
-
|
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
|
-
|
63
|
-
|
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
|
-
|
72
|
-
|
73
|
-
|
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
|
-
|
77
|
-
args.delete_at(2) if method.to_s == 'delete' # Net::HTTP's delete does not accept data
|
116
|
+
private
|
78
117
|
|
79
|
-
|
80
|
-
|
81
|
-
|
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
|
-
|
90
|
-
http = Net::HTTP.new(uri.host, uri.port)
|
126
|
+
class << self
|
91
127
|
|
92
|
-
|
93
|
-
|
94
|
-
|
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
|
-
|
98
|
-
|
140
|
+
def get(uri, options = {})
|
141
|
+
request(:get, uri, nil, options)
|
99
142
|
end
|
100
143
|
|
101
|
-
|
102
|
-
|
144
|
+
def post(uri, data, options = {})
|
145
|
+
request(:post, uri, data, options)
|
146
|
+
end
|
103
147
|
|
104
|
-
|
105
|
-
|
106
|
-
|
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
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
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
|
data/lib/dagger/ox_extension.rb
CHANGED
@@ -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 }
|
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
|
|
data/lib/dagger/version.rb
CHANGED
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.
|
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(:
|
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.
|
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
|
+
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: {}
|
data/test/requests_spec.rb
DELETED
@@ -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
|