noms-command 0.5.0 → 2.1.1

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.
@@ -0,0 +1,61 @@
1
+ #!ruby
2
+
3
+ require 'noms/command/version'
4
+
5
+ require 'httpclient'
6
+
7
+ require 'noms/command/base'
8
+ require 'noms/command/useragent/requester'
9
+ require 'noms/command/useragent/response/httpclient'
10
+
11
+ class NOMS
12
+
13
+ end
14
+
15
+ class NOMS::Command
16
+
17
+ end
18
+
19
+ class NOMS::Command::UserAgent < NOMS::Command::Base
20
+
21
+ end
22
+
23
+ class NOMS::Command::UserAgent::Requester < NOMS::Command::Base
24
+
25
+ end
26
+
27
+ class NOMS::Command::UserAgent::Requester::HTTPClient < NOMS::Command::Base
28
+
29
+ def initialize(opt={})
30
+ @log = opt[:logger] || default_logger
31
+ @log.debug "Creating #{self.class} with options: #{opt.inspect}"
32
+ @client_opts = opt
33
+ @client = ::HTTPClient.new :agent_name => "noms/#{NOMS::Command::VERSION} httpclient/#{::HTTPClient::VERSION}"
34
+ @cookies = opt.has_key?(:cookies) ? opt[:cookies] : true
35
+ if @cookies
36
+ cookie_jar = File.join(NOMS::Command.home, 'cookies.txt')
37
+ @client.set_cookie_store(cookie_jar)
38
+ else
39
+ @client.cookie_manager = nil
40
+ end
41
+ @client.ssl_config.verify_mode = OpenSSL::SSL::VERIFY_NONE
42
+ end
43
+
44
+ def request(opt={})
45
+ response = @client.request(opt[:method].to_s.upcase, opt[:url], '', opt[:body], opt[:headers])
46
+ noms_response = NOMS::Command::UserAgent::Response::HTTPClient.new(response)
47
+ if @cookies
48
+ # @client.save_cookie_store - There is a bug where
49
+ # it thinks @is_saved is satisfied all the time and
50
+ # the file isn't written, which is why we call
51
+ # cookie manager directly.
52
+ @client.cookie_manager.save_all_cookies(true)
53
+ end
54
+ noms_response
55
+ end
56
+
57
+ def set_auth(domain, username, password)
58
+ @client.set_auth(domain, username, password)
59
+ end
60
+
61
+ end
@@ -0,0 +1,73 @@
1
+ #!ruby
2
+
3
+ require 'noms/command/version'
4
+
5
+ require 'uri'
6
+ require 'typhoeus'
7
+
8
+ require 'noms/command/base'
9
+ require 'noms/command/useragent/requester'
10
+ require 'noms/command/useragent/response/typhoeus'
11
+
12
+ class NOMS
13
+
14
+ end
15
+
16
+ class NOMS::Command
17
+
18
+ end
19
+
20
+ class NOMS::Command::UserAgent < NOMS::Command::Base
21
+
22
+ end
23
+
24
+ class NOMS::Command::UserAgent::Requester < NOMS::Command::Base
25
+
26
+ end
27
+
28
+ class NOMS::Command::UserAgent::Requester::Typhoeus < NOMS::Command::Base
29
+
30
+ def initialize(opt={})
31
+ @log = opt[:logger] || default_logger
32
+ @log.debug "Creating #{self.class} with options: #{opt.inspect}"
33
+ @agent_name = "noms/#{NOMS::Command::VERSION} typhoeus/#{::Typhoeus::VERSION}"
34
+ @auth = { }
35
+ @client_opts = {
36
+ :ssl_verifypeer => false
37
+ }
38
+ cookies = opt.has_key?(:cookies) ? opt[:cookies] : true
39
+
40
+ if cookies
41
+ cookie_jar = File.join(NOMS::Command.home, 'cookies.txt')
42
+ @client_opts = @client_opts.merge({
43
+ :cookiefile => cookie_jar,
44
+ :cookiejar => cookie_jar
45
+ })
46
+ end
47
+ end
48
+
49
+ def get_auth(url)
50
+ url = URI.parse(url) unless url.respond_to? :scheme
51
+ domain = url.scheme + '://' + url.host + ':' + url.port.to_s + '/'
52
+ @auth[domain] || { }
53
+ end
54
+
55
+ def request(opt={})
56
+ url = opt[:url]
57
+ spec = @client_opts.merge({
58
+ :method => opt[:method] || opt[:get],
59
+ :headers => {
60
+ 'User-Agent' => @agent_name
61
+ }.merge(opt[:headers]),
62
+ :body => opt[:body]
63
+ }).merge(get_auth(url))
64
+ request = ::Typhoeus::Request.new(opt[:url], spec)
65
+ response = request.run
66
+ NOMS::Command::UserAgent::Response::Typhoeus.new(response)
67
+ end
68
+
69
+ def set_auth(domain, username, password)
70
+ @auth[domain] = { :userpwd => [username, password].join(':') }
71
+ end
72
+
73
+ end
@@ -0,0 +1,202 @@
1
+ #!ruby
2
+
3
+ require 'noms/command/version'
4
+
5
+ require 'time'
6
+
7
+ require 'noms/command'
8
+
9
+ class NOMS
10
+
11
+ end
12
+
13
+ class NOMS::Command
14
+
15
+ end
16
+
17
+ class NOMS::Command::UserAgent < NOMS::Command::Base
18
+
19
+ end
20
+
21
+ class NOMS::Command::UserAgent::Response < NOMS::Command::Base
22
+
23
+ attr_reader :expires, :cache_control, :etag, :last_modified
24
+ attr_accessor :auth_hash, :from_cache, :date, :original_date
25
+
26
+ def self.from_cache(cache_text, opts={})
27
+ unless cache_text.nil? or cache_text.empty?
28
+ self.from_json(cache_text, opts)
29
+ end
30
+ end
31
+
32
+ def self.from_json(json_text, opts={})
33
+ return self.new(JSON.parse(json_text), opts)
34
+ end
35
+
36
+ # Constructor, pass in HTTP response subclass object
37
+ # In the base clase (which is what gets unfrozen)
38
+ # This is a hash.
39
+ def initialize(httpresponse, opts={})
40
+ @log = opts[:logger] || default_logger
41
+ @response = httpresponse
42
+ self.from_cache = false
43
+ self.auth_hash = nil
44
+
45
+ if httpresponse.respond_to? :[]
46
+ self.from_cache = httpresponse['from_cache']
47
+ self.auth_hash = httpresponse['auth_hash']
48
+ self.original_date = Time.httpdate(httpresponse['original_date'])
49
+ self.date = Time.httpdate(httpresponse['date'])
50
+ end
51
+
52
+ @cache_control = self.header 'Cache-Control'
53
+ @date = get_header_time('Date') || Time.now
54
+ @original_date ||= @date
55
+ @expires = get_expires
56
+ @etag = self.header 'Etag'
57
+ @last_modified = get_header_time 'Last-modified'
58
+ end
59
+
60
+ # The response body
61
+ def body
62
+ @response['body']
63
+ end
64
+
65
+ # The success status
66
+ def success?
67
+ # We created this object explicitly, so it's always successful
68
+ true
69
+ end
70
+
71
+ # A hash or headers, or specific header
72
+ def header(hdr=nil)
73
+ if hdr.nil?
74
+ @response['header']
75
+ else
76
+ Hash[@response['header'].map { |h, v| [h.downcase, v] }][hdr.downcase] unless @response.nil?
77
+ end
78
+ end
79
+
80
+ # An integer status code
81
+ def status
82
+ @response['status']
83
+ end
84
+
85
+ # The status message including code
86
+ def statusText
87
+ @response['statusText']
88
+ end
89
+
90
+ # MIME Type of content
91
+ def content_type
92
+ self.header 'Content-Type'
93
+ end
94
+
95
+ def header_params(s)
96
+ Hash[s.split(';').map do |field|
97
+ param, value = field.split('=', 2)
98
+ value ||= ''
99
+ [param.strip, value.strip]
100
+ end]
101
+ end
102
+
103
+ def content_encoding
104
+ if self.content_type
105
+ header_params(self.content_type)['charset']
106
+ end
107
+ end
108
+
109
+ def to_json
110
+ self.to_hash.to_json
111
+ end
112
+
113
+ def to_cache
114
+ self.to_json
115
+ end
116
+
117
+ def to_hash
118
+ {
119
+ 'body' => self.body,
120
+ 'header' => self.header,
121
+ 'status' => self.status,
122
+ 'statusText' => self.statusText,
123
+ 'auth_hash' => self.auth_hash,
124
+ 'from_cache' => self.from_cache,
125
+ 'date' => self.date.httpdate,
126
+ 'original_date' => self.original_date.httpdate
127
+ }
128
+ end
129
+
130
+ def auth_hash=(hvalue)
131
+ @auth_hash = hvalue
132
+ end
133
+
134
+ def get_expires
135
+
136
+ expires = [ ]
137
+
138
+ if @cache_control and (m = /max-age=(\d+)/.match(@cache_control))
139
+ expires << (@date + m[1].to_i)
140
+ end
141
+
142
+ if self.header('Expires')
143
+ begin
144
+ expires << Time.httpdate(self.header('Expires'))
145
+ rescue ArgumentError => e
146
+ @log.debug "Response had 'Expires' header but could not parse (#{e.class}): #{e.message}"
147
+ end
148
+ end
149
+
150
+ return nil if expires.empty?
151
+
152
+ expires.empty? ? nil : expires.min
153
+ end
154
+
155
+ def get_header_time(hdr)
156
+ value = self.header hdr
157
+ if value
158
+ begin
159
+ Time.httpdate(value)
160
+ rescue ArgumentError => e
161
+ @log.debug "Response has a '#{hdr}' but could not parse (#{e.class}): #{e.message}"
162
+ end
163
+ end
164
+ end
165
+
166
+ def cacheable?
167
+ return false unless self.status == 200
168
+ return false unless @expires
169
+ return false if self.from_cache?
170
+ return false if /no-cache/.match @cache_control
171
+ return false if /no-store/.match @cache_control
172
+ return false if self.header 'Pragma' and /no-cache/.match self.header('Pragma')
173
+
174
+ true
175
+ end
176
+
177
+ def cached!
178
+ @from_cache = true
179
+ end
180
+
181
+ def from_cache?
182
+ @from_cache
183
+ end
184
+
185
+ def current?
186
+ return false if (@cache_control and /must-revalidate/.match @cache_control)
187
+ return false unless @expires
188
+ return false if Time.now > @expires
189
+ true
190
+ end
191
+
192
+ def age
193
+ Time.now - self.original_date
194
+ end
195
+
196
+ def cacheable_copy
197
+ other = self.dup
198
+ other.logger = nil
199
+ other
200
+ end
201
+
202
+ end
@@ -0,0 +1,59 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'noms/command/version'
4
+
5
+ require 'httpclient'
6
+
7
+ class NOMS
8
+
9
+ end
10
+
11
+ class NOMS::Command
12
+
13
+ end
14
+
15
+ class NOMS::Command::UserAgent < NOMS::Command::Base
16
+
17
+ end
18
+
19
+ class NOMS::Command::UserAgent::Response < NOMS::Command::Base
20
+
21
+ end
22
+
23
+ class NOMS::Command::UserAgent::Response::HTTPClient < NOMS::Command::UserAgent::Response
24
+
25
+ def initialize(httpresponse, opts={})
26
+ super
27
+ @log = opts[:logger] || default_logger
28
+ @response = httpresponse
29
+ end
30
+
31
+ def body
32
+ @response.content
33
+ end
34
+
35
+ def success?
36
+ @response.ok?
37
+ end
38
+
39
+ def header(hdr=nil)
40
+ if hdr.nil?
41
+ @response.headers
42
+ else
43
+ @response.header[hdr.downcase].first
44
+ end
45
+ end
46
+
47
+ def status
48
+ @response.status.to_i unless @response.status.nil?
49
+ end
50
+
51
+ def statusText
52
+ @response.status.to_s + ' ' + @response.reason unless @response.status.nil?
53
+ end
54
+
55
+ def content_type
56
+ @response.contenttype
57
+ end
58
+
59
+ end
@@ -0,0 +1,74 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'noms/command/version'
4
+
5
+ require 'typhoeus'
6
+
7
+ class NOMS
8
+
9
+ end
10
+
11
+ class NOMS::Command
12
+
13
+ end
14
+
15
+ class NOMS::Command::UserAgent < NOMS::Command::Base
16
+
17
+ end
18
+
19
+ class NOMS::Command::UserAgent::Response < NOMS::Command::Base
20
+
21
+ end
22
+
23
+ class NOMS::Command::UserAgent::Response::Typhoeus < NOMS::Command::UserAgent::Response
24
+
25
+ def initialize(httpresponse, opts={})
26
+ super
27
+ if @response.return_code != :ok
28
+ raise NOMS::Command::Error.new "Client error[#{@response.return_code.inspect}]: #{@response.return_message}"
29
+ end
30
+ content_encoding = self.content_encoding || 'utf-8'
31
+ @body = @response.body
32
+
33
+ if @body
34
+
35
+ begin
36
+ @log.debug "Forcing body string encoding to #{content_encoding}"
37
+ @body.force_encoding(content_encoding)
38
+ rescue Encoding::UndefinedConversionError
39
+ @log.debug " (coercing 'binary' to '#{content_encoding}')"
40
+ @body = @body.encode('utf8', 'binary', :undef => :replace, :invalid => :replace)
41
+ end
42
+
43
+ end
44
+ end
45
+
46
+ def body
47
+ @body || @response.body
48
+ end
49
+
50
+ def success?
51
+ @response.success?
52
+ end
53
+
54
+ def header(hdr=nil)
55
+ if hdr.nil?
56
+ @response.headers
57
+ else
58
+ Hash[@response.headers.map { |h, v| [h.downcase, v] }][hdr.downcase]
59
+ end
60
+ end
61
+
62
+ def status
63
+ @response.code.to_i
64
+ end
65
+
66
+ def statusText
67
+ @response.code.to_s + ' ' + @response.status_message
68
+ end
69
+
70
+ def content_type
71
+ @response.headers['Content-Type']
72
+ end
73
+
74
+ end