sensu-plugins-http-boutetnico 1.0.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.
@@ -0,0 +1,232 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: false
3
+
4
+ #
5
+ # check-http-json
6
+ #
7
+ # DESCRIPTION:
8
+ # Takes either a URL or a combination of host/path/query/port/ssl, and checks
9
+ # for valid JSON output in the response. Can also optionally validate simple
10
+ # string key/value pairs, and optionally check if a specified value is within
11
+ # bounds.
12
+ #
13
+ # OUTPUT:
14
+ # plain text
15
+ #
16
+ # PLATFORMS:
17
+ # Linux
18
+ #
19
+ # DEPENDENCIES:
20
+ # gem: sensu-plugin
21
+ # gem: json
22
+ #
23
+ # USAGE:
24
+ # Check that will verify http status and JSON validity
25
+ # ./check-http-json.rb -u http://my.site.com/health.json
26
+ #
27
+ # Check that will verify http status, JSON validity, and that page.totalElements value is
28
+ # greater than 10
29
+ # ./check-http-json.rb -u http://my.site.com/metric.json --key page.totalElements --value-greater-than 10
30
+ #
31
+ # Check that will POST json
32
+ # ./check-http-json.rb -u http://my.site.com/metric.json -m POST --header 'Content-type: application/json' --post-body '{"serverId": "myserver"}'
33
+ #
34
+ # NOTES:
35
+ # Based on Check HTTP by Sonian Inc.
36
+ #
37
+ # LICENSE:
38
+ # Copyright 2013 Matt Revell <nightowlmatt@gmail.com>
39
+ # Released under the same terms as Sensu (the MIT license); see LICENSE
40
+ # for details.
41
+ #
42
+
43
+ require 'sensu-plugin/check/cli'
44
+ require 'json'
45
+ require 'net/http'
46
+ require 'net/https'
47
+
48
+ #
49
+ # Check JSON
50
+ #
51
+ class CheckJson < Sensu::Plugin::Check::CLI
52
+ option :url, short: '-u URL'
53
+ option :host, short: '-h HOST'
54
+ option :path, short: '-p PATH'
55
+ option :query, short: '-q QUERY'
56
+ option :port, short: '-P PORT', proc: proc(&:to_i)
57
+ option :method, short: '-m GET|POST'
58
+ option :postbody, short: '-b /file/with/post/body'
59
+ option :post_body, long: '--post-body VALUE'
60
+ option :header, short: '-H HEADER', long: '--header HEADER'
61
+ option :ssl, short: '-s', boolean: true, default: false
62
+ option :insecure, short: '-k', boolean: true, default: false
63
+ option :user, short: '-U', long: '--username USER'
64
+ option :password, short: '-a', long: '--password PASS'
65
+ option :cert, short: '-c FILE', long: '--cert FILE'
66
+ option :certkey, long: '--cert-key FILE'
67
+ option :cacert, short: '-C FILE', long: '--cacert FILE'
68
+ option :timeout, short: '-t SECS', proc: proc(&:to_i), default: 15
69
+ option :key, short: '-K KEY', long: '--key KEY'
70
+ option :value, short: '-v VALUE', long: '--value VALUE'
71
+ option :valueGt, long: '--value-greater-than VALUE'
72
+ option :valueLt, long: '--value-less-than VALUE'
73
+ option :whole_response, short: '-w', long: '--whole-response', boolean: true, default: false
74
+ option :dump_json, short: '-d', long: '--dump-json', boolean: true, default: false
75
+ option :pretty, long: '--pretty', boolean: true, default: false
76
+
77
+ option :response_code,
78
+ long: '--response-code REGEX',
79
+ description: 'Critical if HTTP response code does not match REGEX',
80
+ default: '^2([0-9]{2})$'
81
+
82
+ def run
83
+ if config[:url]
84
+ uri = URI.parse(config[:url])
85
+ config[:host] = uri.host
86
+ config[:path] = uri.path
87
+ config[:query] = uri.query
88
+ config[:port] = uri.port
89
+ config[:ssl] = uri.scheme == 'https'
90
+ else
91
+ # #YELLOW
92
+ unless config[:host] && config[:path]
93
+ unknown 'No URL specified'
94
+ end
95
+ config[:port] ||= config[:ssl] ? 443 : 80
96
+ end
97
+
98
+ begin
99
+ Timeout.timeout(config[:timeout]) do
100
+ acquire_resource
101
+ end
102
+ rescue Timeout::Error
103
+ critical 'Connection timed out'
104
+ rescue StandardError => e
105
+ critical "Connection error: #{e.message}"
106
+ end
107
+ end
108
+
109
+ def deep_value(data, desired_key, parent = '')
110
+ case data
111
+ when Array
112
+ data.each_with_index do |value, index|
113
+ arr_key = parent + '[' + index.to_s + ']'
114
+
115
+ if arr_key == desired_key
116
+ return value.nil? ? 'null' : value
117
+ end
118
+
119
+ if desired_key.include? arr_key
120
+ search = deep_value(value, desired_key, arr_key)
121
+
122
+ return search unless search.nil?
123
+ end
124
+ end
125
+ when Hash
126
+ data.each do |key, value|
127
+ key_prefix = parent.empty? ? '' : '.'
128
+ hash_key = parent + key_prefix + key
129
+
130
+ if hash_key == desired_key
131
+ return value.nil? ? 'null' : value
132
+ end
133
+
134
+ if desired_key.include?(hash_key + '.') || desired_key.include?(hash_key + '[')
135
+ search = deep_value(value, desired_key, hash_key)
136
+
137
+ return search unless search.nil?
138
+ end
139
+ end
140
+ end
141
+ end
142
+
143
+ def json_valid?(str)
144
+ ::JSON.parse(str)
145
+ true
146
+ rescue ::JSON::ParserError
147
+ false
148
+ end
149
+
150
+ def acquire_resource
151
+ http = Net::HTTP.new(config[:host], config[:port])
152
+
153
+ if config[:ssl]
154
+ http.use_ssl = true
155
+ if config[:cert]
156
+ cert_data = File.read(config[:cert])
157
+ http.cert = OpenSSL::X509::Certificate.new(cert_data)
158
+ if config[:certkey]
159
+ cert_data = File.read(config[:certkey])
160
+ end
161
+ http.key = OpenSSL::PKey::RSA.new(cert_data, nil)
162
+ end
163
+ http.ca_file = config[:cacert] if config[:cacert]
164
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE if config[:insecure]
165
+ end
166
+
167
+ req = if config[:method] == 'POST'
168
+ Net::HTTP::Post.new([config[:path], config[:query]].compact.join('?'))
169
+ else
170
+ Net::HTTP::Get.new([config[:path], config[:query]].compact.join('?'))
171
+ end
172
+ if config[:postbody]
173
+ post_body = IO.readlines(config[:postbody])
174
+ req.body = post_body.join
175
+ end
176
+ if config[:post_body]
177
+ req.body = config[:post_body]
178
+ end
179
+ unless config[:user].nil? && config[:password].nil?
180
+ req.basic_auth config[:user], config[:password]
181
+ end
182
+ if config[:header]
183
+ config[:header].split(',').each do |header|
184
+ h, v = header.split(':', 2)
185
+ req[h] = v.strip
186
+ end
187
+ end
188
+ res = http.request(req)
189
+
190
+ if res.code !~ /#{config[:response_code]}/
191
+ critical "http code: #{res.code}: body: #{res.body}" if config[:whole_response]
192
+ critical res.code
193
+ end
194
+ critical 'invalid JSON from request' unless json_valid?(res.body)
195
+ ok 'valid JSON returned' if config[:key].nil? && config[:value].nil?
196
+
197
+ json = ::JSON.parse(res.body)
198
+
199
+ begin
200
+ leaf = deep_value(json, config[:key])
201
+
202
+ raise "could not find key: #{config[:key]}" if leaf.nil?
203
+
204
+ message = "key has expected value: '#{config[:key]}' "
205
+ if config[:value]
206
+ raise "unexpected value for key: '#{leaf}' != '#{config[:value]}'" unless leaf.to_s == config[:value].to_s
207
+
208
+ message += "equals '#{config[:value]}'"
209
+ end
210
+ if config[:valueGt]
211
+ raise "unexpected value for key: '#{leaf}' not > '#{config[:valueGt]}'" unless leaf.to_f > config[:valueGt].to_f
212
+
213
+ message += "greater than '#{config[:valueGt]}'"
214
+ end
215
+ if config[:valueLt]
216
+ raise "unexpected value for key: '#{leaf}' not < '#{config[:valueLt]}'" unless leaf.to_f < config[:valueLt].to_f
217
+
218
+ message += "less than '#{config[:valueLt]}'"
219
+ end
220
+
221
+ ok message
222
+ rescue StandardError => e
223
+ if config[:dump_json]
224
+ json_response = config[:pretty] ? ::JSON.pretty_generate(json) : json
225
+ message = "key check failed: #{e}. Response: #{json_response}"
226
+ else
227
+ message = "key check failed: #{e}"
228
+ end
229
+ critical message
230
+ end
231
+ end
232
+ end
@@ -0,0 +1,461 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: false
3
+
4
+ #
5
+ # check-http
6
+ #
7
+ # DESCRIPTION:
8
+ # Takes either a URL or a combination of host/path/port/ssl, and checks for
9
+ # a 200 response (that matches a pattern, if given). Can use client certs.
10
+ #
11
+ # OUTPUT:
12
+ # plain text
13
+ #
14
+ # PLATFORMS:
15
+ # Linux
16
+ #
17
+ # DEPENDENCIES:
18
+ # gem: sensu-plugin
19
+ #
20
+ # USAGE:
21
+ # Basic HTTP check - expect a 200 response
22
+ # check-http.rb -u http://my.site.com
23
+ #
24
+ # Pattern check - expect a 200 response and the string 'OK' in the body
25
+ # check-http.rb -u http://my.site.com/health -q 'OK'
26
+ #
27
+ # Check if a response is greater than the specified minimum value
28
+ # check-http.rb -u https://my.site.com/redirect --min-bytes 10
29
+ #
30
+ # Check response code - expect a 301 response
31
+ # check-http.rb -u https://my.site.com/redirect --response-code 301 -r
32
+ #
33
+ # Use a proxy to check a URL
34
+ # check-http.rb -u https://www.google.com --proxy-url http://my.proxy.com:3128
35
+ #
36
+ # Use a proxy with username and password to check a URL
37
+ # NOTE: Use 'check token substition' to avoid credentials leakage!
38
+ # check-http.rb -u https://www.google.com --proxy-url http://a_user:a_pass@my.proxy.com:3128
39
+ #
40
+ # Check something with needing to set multiple headers
41
+ # check-http.rb -u https://www.google.com --header 'Origin: ma.local.box, SomeRandomHeader: foo'
42
+ #
43
+ # Check something that requires a POST with json data
44
+ # check-http.rb -u https://httpbin.org/post --method POST --header 'Content-type: application/json' --body '{"foo": "bar"}'
45
+ # NOTES:
46
+ #
47
+ # LICENSE:
48
+ # Copyright 2011 Sonian, Inc <chefs@sonian.net>
49
+ # Updated by Lewis Preson 2012 to accept basic auth credentials
50
+ # Updated by SweetSpot 2012 to require specified redirect
51
+ # Updated by Chris Armstrong 2013 to accept multiple headers
52
+ # Updated by Mark Clarkson 2018 to accept proxy auth credentials
53
+ # Released under the same terms as Sensu (the MIT license); see LICENSE
54
+ # for details.
55
+ #
56
+
57
+ require 'sensu-plugins-http'
58
+ require 'sensu-plugin/check/cli'
59
+ require 'net/http'
60
+ require 'net/https'
61
+ require 'digest'
62
+ require 'resolv-replace'
63
+
64
+ #
65
+ # Check HTTP
66
+ #
67
+ class CheckHttp < Sensu::Plugin::Check::CLI
68
+ option :ua,
69
+ short: '-x USER-AGENT',
70
+ long: '--user-agent USER-AGENT',
71
+ description: 'Specify a USER-AGENT',
72
+ default: 'Sensu-HTTP-Check'
73
+
74
+ option :url,
75
+ short: '-u URL',
76
+ long: '--url URL',
77
+ description: 'A URL to connect to'
78
+
79
+ option :host,
80
+ short: '-h HOST',
81
+ long: '--hostname HOSTNAME',
82
+ description: 'A HOSTNAME to connect to'
83
+
84
+ option :port,
85
+ short: '-P PORT',
86
+ long: '--port PORT',
87
+ proc: proc(&:to_i),
88
+ description: 'Select another port'
89
+
90
+ option :request_uri,
91
+ short: '-p PATH',
92
+ long: '--request-uri PATH',
93
+ description: 'Specify a uri path'
94
+
95
+ option :method,
96
+ short: '-m GET|HEAD|POST|PUT',
97
+ long: '--method GET|HEAD|POST|PUT',
98
+ description: 'Specify a GET, HEAD, POST, or PUT operation; defaults to GET',
99
+ in: %w[GET HEAD POST PUT],
100
+ default: 'GET'
101
+
102
+ option :header,
103
+ short: '-H HEADER',
104
+ long: '--header HEADER',
105
+ description: 'Send one or more comma-separated headers with the request'
106
+
107
+ option :headerfile,
108
+ long: '--headerfile FILE',
109
+ description: 'Send headers with the request, read from FILE, separated by newline'
110
+
111
+ option :body,
112
+ short: '-d BODY',
113
+ long: '--body BODY',
114
+ description: 'Send a data body string with the request'
115
+
116
+ option :ssl,
117
+ short: '-s',
118
+ boolean: true,
119
+ description: 'Enabling SSL connections',
120
+ default: false
121
+
122
+ option :insecure,
123
+ short: '-k',
124
+ boolean: true,
125
+ description: 'Enabling insecure connections',
126
+ default: false
127
+
128
+ option :user,
129
+ short: '-U',
130
+ long: '--username USER',
131
+ description: 'A username to connect as'
132
+
133
+ option :password,
134
+ short: '-a',
135
+ long: '--password PASS',
136
+ description: 'A password to use for the username'
137
+
138
+ option :cert,
139
+ short: '-c FILE',
140
+ long: '--cert FILE',
141
+ description: 'Cert to use'
142
+
143
+ option :cacert,
144
+ short: '-C FILE',
145
+ long: '--cacert FILE',
146
+ description: 'A CA Cert to use'
147
+
148
+ option :expiry,
149
+ short: '-e EXPIRY',
150
+ long: '--expiry EXPIRY',
151
+ proc: proc(&:to_i),
152
+ description: 'Warn EXPIRE days before cert expires'
153
+
154
+ option :pattern,
155
+ short: '-q PAT',
156
+ long: '--query PAT',
157
+ description: 'Query for a specific pattern that must exist'
158
+
159
+ option :negpattern,
160
+ short: '-n PAT',
161
+ long: '--negquery PAT',
162
+ description: 'Query for a specific pattern that must be absent'
163
+
164
+ option :sha256checksum,
165
+ short: '-S CHECKSUM',
166
+ long: '--checksum CHECKSUM',
167
+ description: 'SHA-256 checksum'
168
+
169
+ option :timeout,
170
+ short: '-t SECS',
171
+ long: '--timeout SECS',
172
+ proc: proc(&:to_i),
173
+ description: 'Set the total execution timeout in seconds',
174
+ default: 15
175
+
176
+ option :open_timeout,
177
+ long: '--open-timeout SECS',
178
+ proc: proc(&:to_i),
179
+ description: 'Number of seconds to wait for the connection to open',
180
+ default: 15
181
+
182
+ option :read_timeout,
183
+ long: '--read-timeout SECS',
184
+ proc: proc(&:to_i),
185
+ description: 'Number of seconds to wait for one block to be read',
186
+ default: 15
187
+
188
+ option :dns_timeout,
189
+ long: '--dns-timeout SECS',
190
+ proc: proc(&:to_f),
191
+ description: 'Number of seconds to allow for DNS resolution. Accepts decimal number.',
192
+ default: 0.8
193
+
194
+ option :redirectok,
195
+ short: '-r',
196
+ boolean: true,
197
+ description: 'Check if a redirect is ok',
198
+ default: false
199
+
200
+ option :redirectto,
201
+ short: '-R URL',
202
+ long: '--redirect-to URL',
203
+ description: 'Redirect to another page'
204
+
205
+ option :whole_response,
206
+ short: '-w',
207
+ long: '--whole-response',
208
+ boolean: true,
209
+ default: false,
210
+ description: 'Print whole output when check fails'
211
+
212
+ option :response_bytes,
213
+ short: '-b BYTES',
214
+ long: '--response-bytes BYTES',
215
+ description: 'Print BYTES of the output',
216
+ proc: proc(&:to_i)
217
+
218
+ option :require_bytes,
219
+ short: '-B BYTES',
220
+ long: '--require-bytes BYTES',
221
+ description: 'Check the response contains exactly BYTES bytes',
222
+ proc: proc(&:to_i)
223
+
224
+ option :min_bytes,
225
+ short: '-g BYTES',
226
+ long: '--min-bytes BYTES',
227
+ description: 'Check the response contains at least BYTES bytes',
228
+ proc: proc(&:to_i)
229
+
230
+ option :response_code,
231
+ long: '--response-code REGEX',
232
+ description: 'Critical if HTTP response code does not match REGEX'
233
+
234
+ option :proxy_url,
235
+ long: '--proxy-url PROXY_URL',
236
+ description: 'Use a proxy server to connect'
237
+
238
+ option :no_proxy,
239
+ long: '--noproxy',
240
+ boolean: true,
241
+ description: 'Do not use proxy server even from environment http_proxy setting',
242
+ default: false
243
+
244
+ option :aws_v4,
245
+ long: '--aws-v4',
246
+ boolean: true,
247
+ description: 'Sign http request with AWS v4 signature',
248
+ default: false
249
+
250
+ option :aws_v4_region,
251
+ long: '--aws-v4-region REGION',
252
+ description: 'Region to use for AWS v4 signing. Defaults to AWS_REGION or AWS_DEFAULT_REGION'
253
+
254
+ option :aws_v4_service,
255
+ long: '--aws-v4-service SERVICE',
256
+ description: 'Service name to use when building the v4 signature',
257
+ default: 'execute-api'
258
+
259
+ include SensuPluginsHttp::AwsV4
260
+
261
+ def run
262
+ if config[:url]
263
+ uri = URI.parse(config[:url])
264
+ config[:host] = uri.host
265
+ config[:port] = uri.port
266
+ config[:request_uri] = uri.request_uri
267
+ config[:ssl] = uri.scheme == 'https'
268
+ else
269
+ # #YELLOW
270
+ unless config[:host] && config[:request_uri]
271
+ unknown 'No URL specified'
272
+ end
273
+ config[:port] ||= config[:ssl] ? 443 : 80
274
+ end
275
+
276
+ # Use Ruby DNS Resolver and set DNS resolution timeout to dns_timeout value
277
+ hosts_resolver = Resolv::Hosts.new
278
+ dns_resolver = Resolv::DNS.new
279
+ dns_resolver.timeouts = config[:dns_timeout]
280
+ Resolv::DefaultResolver.replace_resolvers([hosts_resolver, dns_resolver])
281
+
282
+ begin
283
+ Timeout.timeout(config[:timeout]) do
284
+ acquire_resource
285
+ end
286
+ rescue Net::OpenTimeout
287
+ critical 'Request timed out opening connection'
288
+ rescue Net::ReadTimeout
289
+ critical 'Request timed out reading data'
290
+ rescue Timeout::Error
291
+ critical 'Request timed out'
292
+ rescue StandardError => e
293
+ critical "Request error: #{e.message}"
294
+ end
295
+ end
296
+
297
+ def acquire_resource
298
+ http = nil
299
+
300
+ if config[:no_proxy]
301
+ http = Net::HTTP.new(config[:host], config[:port], nil, nil)
302
+ elsif config[:proxy_url]
303
+ proxy_uri = URI.parse(config[:proxy_url])
304
+ if proxy_uri.host.nil?
305
+ unknown 'Invalid proxy url specified'
306
+ end
307
+ http = if proxy_uri.user && proxy_uri.password
308
+ Net::HTTP.new(config[:host], config[:port], proxy_uri.host, proxy_uri.port, proxy_uri.user, proxy_uri.password)
309
+ else
310
+ Net::HTTP.new(config[:host], config[:port], proxy_uri.host, proxy_uri.port)
311
+ end
312
+ else
313
+ http = Net::HTTP.new(config[:host], config[:port])
314
+ end
315
+ http.read_timeout = config[:read_timeout]
316
+ http.open_timeout = config[:open_timeout]
317
+ http.ssl_timeout = config[:timeout]
318
+ http.continue_timeout = config[:timeout]
319
+ http.keep_alive_timeout = config[:timeout]
320
+
321
+ warn_cert_expire = nil
322
+ if config[:ssl]
323
+ http.use_ssl = true
324
+ if config[:cert]
325
+ cert_data = File.read(config[:cert])
326
+ http.cert = OpenSSL::X509::Certificate.new(cert_data)
327
+ http.key = OpenSSL::PKey::RSA.new(cert_data, nil)
328
+ end
329
+ http.ca_file = config[:cacert] if config[:cacert]
330
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE if config[:insecure]
331
+
332
+ unless config[:expiry].nil?
333
+ expire_warn_date = Time.now + (config[:expiry] * 60 * 60 * 24)
334
+ # We can't raise inside the callback, have to check when we finish.
335
+ http.verify_callback = proc do |preverify_ok, ssl_context|
336
+ if ssl_context.current_cert.not_after <= expire_warn_date
337
+ warn_cert_expire = ssl_context.current_cert.not_after
338
+ end
339
+
340
+ preverify_ok
341
+ end
342
+ end
343
+ end
344
+
345
+ req = case config[:method]
346
+ when 'GET'
347
+ Net::HTTP::Get.new(config[:request_uri], 'User-Agent' => config[:ua])
348
+ when 'HEAD'
349
+ Net::HTTP::Head.new(config[:request_uri], 'User-Agent' => config[:ua])
350
+ when 'POST'
351
+ Net::HTTP::Post.new(config[:request_uri], 'User-Agent' => config[:ua])
352
+ when 'PUT'
353
+ Net::HTTP::Put.new(config[:request_uri], 'User-Agent' => config[:ua])
354
+ end
355
+
356
+ unless config[:user].nil? && config[:password].nil?
357
+ req.basic_auth config[:user], config[:password]
358
+ end
359
+ if config[:header]
360
+ config[:header].split(',').each do |header|
361
+ h, v = header.split(':', 2)
362
+ req[h.strip] = v.strip
363
+ end
364
+ end
365
+
366
+ if config[:headerfile]
367
+ File.readlines(config[:headerfile]).each do |line|
368
+ h, v = line.split(':', 2)
369
+ req[h.strip] = v.strip
370
+ end
371
+ end
372
+
373
+ req.body = config[:body] if config[:body]
374
+
375
+ req = apply_v4_signature(http, req, config) if config[:aws_v4]
376
+
377
+ res = http.request(req)
378
+
379
+ body = if config[:whole_response]
380
+ "\n" + res.body.to_s
381
+ else
382
+ body = if config[:response_bytes] # rubocop:disable Lint/UselessAssignment
383
+ "\n" + res.body[0..config[:response_bytes]]
384
+ else
385
+ ''
386
+ end
387
+ end
388
+
389
+ if config[:require_bytes] && res.body.length != config[:require_bytes]
390
+ critical "Response was #{res.body.length} bytes instead of #{config[:require_bytes]}" + body
391
+ end
392
+
393
+ if config[:min_bytes] && res.body.length < config[:min_bytes]
394
+ critical "Response was #{res.body.length} bytes instead of the indicated minimum #{config[:min_bytes]}" + body
395
+ end
396
+
397
+ unless warn_cert_expire.nil?
398
+ warning "Certificate will expire #{warn_cert_expire}"
399
+ end
400
+
401
+ size = res.body.nil? ? '0' : res.body.size
402
+
403
+ handle_response(res, size, body)
404
+ end
405
+
406
+ def handle_response(res, size, body)
407
+ case res.code
408
+ when /^2/
409
+ if config[:redirectto]
410
+ critical "Expected redirect to #{config[:redirectto]} but got #{res.code}" + body
411
+ elsif config[:pattern]
412
+ if res.body =~ /#{config[:pattern]}/
413
+ ok "#{res.code}, found /#{config[:pattern]}/ in #{size} bytes" + body
414
+ else
415
+ critical "#{res.code}, did not find /#{config[:pattern]}/ in #{size} bytes: #{res.body[0...200]}..."
416
+ end
417
+ elsif config[:negpattern]
418
+ if res.body =~ /#{config[:negpattern]}/
419
+ critical "#{res.code}, found /#{config[:negpattern]}/ in #{size} bytes: #{res.body[0...200]}..."
420
+ else
421
+ ok "#{res.code}, did not find /#{config[:negpattern]}/ in #{size} bytes" + body
422
+ end
423
+ elsif config[:sha256checksum]
424
+ if Digest::SHA256.hexdigest(res.body).eql? config[:sha256checksum]
425
+ ok "#{res.code}, checksum match #{config[:sha256checksum]} in #{size} bytes" + body
426
+ else
427
+ critical "#{res.code}, checksum did not match #{config[:sha256checksum]} in #{size} bytes: #{res.body[0...200]}..."
428
+ end
429
+ else
430
+ ok("#{res.code}, #{size} bytes" + body) unless config[:response_code]
431
+ end
432
+ when /^3/
433
+ if config[:redirectok] || config[:redirectto]
434
+ if config[:redirectok]
435
+ # #YELLOW
436
+ ok("#{res.code}, #{size} bytes" + body) unless config[:response_code] # rubocop:disable Metrics/BlockNesting
437
+ elsif config[:redirectto]
438
+ # #YELLOW
439
+ if config[:redirectto] == res['Location'] # rubocop:disable Metrics/BlockNesting
440
+ ok "#{res.code} found redirect to #{res['Location']}" + body
441
+ else
442
+ critical "Expected redirect to #{config[:redirectto]} instead redirected to #{res['Location']}" + body
443
+ end
444
+ end
445
+ else
446
+ warning res.code + body
447
+ end
448
+ when /^4/, /^5/
449
+ critical(res.code + body) unless config[:response_code]
450
+ else
451
+ warning(res.code + body) unless config[:response_code]
452
+ end
453
+
454
+ if config[:response_code] && res.code =~ /#{config[:response_code]}/
455
+ ok "#{res.code}, #{size} bytes" + body
456
+
457
+ else
458
+ critical res.code + body
459
+ end
460
+ end
461
+ end