noms-command 0.5.0 → 2.1.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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