-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathrtclient.rb
More file actions
85 lines (82 loc) · 2.79 KB
/
Copy pathrtclient.rb
File metadata and controls
85 lines (82 loc) · 2.79 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
require 'net/http'
require 'openssl'
class RTResponse
LINE_SEP = /\n+([^ ]|$)/
ARRAY_SEP = /^--$/
KEY_VALUE_SEP = /(: |$)/
COMMENT = /^#/
LIST_SEP = /\s*,\s*/
attr_reader :raw, :version, :code, :status, :comments, :body
def initialize(body)
@raw = body
lines = body.split LINE_SEP
lines = [*lines[0..0], *lines.drop(1).each_slice(2).map(&:join)]
@version, @code, @status = lines.first.split(' ', 3)
lines.shift
@comments, lines = lines.partition{|line|COMMENT.match(line)}
@body = lines.slice_before(ARRAY_SEP).map{|item|
item.reject{|line|
ARRAY_SEP.match line
}.map{|line|
line.split KEY_VALUE_SEP, 2
}.map{|key,sep,value|
value.gsub!("\n"+(' '*(key.size+sep.size)),"\n") if value.index("\n")
[key, value]
}.to_h
}
end
def self.split_string(string); string.split LIST_SEP; end
def self.join_array(array); array.join(', '); end
def ok?; @code=="200"; end
def no_credentials?; @code=="401"; end
end
class String
def rt_split; RTResponse.split_string self; end
end
class Array
def rt_join; RTResponse.join_array self; end
end
class RTClient
class Error < RuntimeError; end
class ConnectionError < Error; end
class AuthenticationError < Error; end
def self.make_http_and_path(uri_string, ca_file=nil)
uri = URI.parse uri_string
http = Net::HTTP.new uri.host, uri.port
if uri.is_a? URI::HTTPS
http.use_ssl = true
http.verify_mode = (ca_file==false) ? OpenSSL::SSL::VERIFY_NONE : OpenSSL::SSL::VERIFY_PEER
http.ca_file = ca_file if ca_file
end
[http, uri.path]
end
def initialize(http:nil, path:nil, user:nil, pass:nil)
@http = http
@path = path
@user = user
@pass = pass
@cookie = nil
end
def call(*path, format:nil, fields:nil, content:nil, user:nil, pass:nil, noauth:false)
data = {}
data.merge! format:format if format
data.merge! fields:fields if fields
data.merge!(user:user, pass:pass) if user && pass
if content
content = content.map{|k,v| [k, v.respond_to?(:join) ? v.join("\n ") : v]}.map{|k,v|"#{k}: #{v}\n"}.join if content.respond_to?(:map)
data.merge! content:content
end
headers = @cookie ? {'Cookie'=>@cookie} : {}
response = @http.post "#{@path}/REST/1.0/#{path.join('/')}", URI.encode_www_form(data), headers
raise ConnectionError.new if response.code != "200"
@cookie = response['set-cookie'].partition(';').first
rtresponse = RTResponse.new response.body
if rtresponse.no_credentials?
raise AuthenticationError.new if noauth || (user&&pass) || !login
rtresponse = call(*path, format:format, fields:fields, content:content, noauth:true)
end
raise Error.new(rtresponse.raw) if !rtresponse.ok?
rtresponse
end
def login; call(user:@user, pass:@pass).ok?; end
end