Mercurial > servermonitor
annotate ServerMonitor/Objects/Checks/HttpCheck.cs @ 23:3866c19535fd
Fix NullReferenceException when checks are executed on a brand new server.
author | Brad Greco <brad@bgreco.net> |
---|---|
date | Thu, 30 May 2019 21:40:27 -0400 |
parents | b713b9db4c82 |
children | 7645122aa7a9 |
rev | line source |
---|---|
0
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
1 using System; |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
2 using System.Collections.Generic; |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
3 using System.ComponentModel; |
18 | 4 using System.IO; |
0
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
5 using System.Linq; |
18 | 6 using System.Net.Http; |
0
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
7 using System.Text.RegularExpressions; |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
8 using System.Threading; |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
9 using System.Threading.Tasks; |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
10 |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
11 namespace ServerMonitorApp |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
12 { |
18 | 13 /// <summary>Executes an HTTP request and checks the result or status code.</summary> |
0
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
14 [DisplayName("HTTP check"), Description("Check the result of an HTTP request"), DisplayWeight(1)] |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
15 public class HttpCheck : Check |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
16 { |
18 | 17 /// <summary>The URL to request.</summary> |
0
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
18 public string Url { get; set; } |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
19 |
18 | 20 /// <summary>The HTTP method for the request.</summary> |
21 /// <remarks>Only HEAD and GET are supported.</remarks> | |
22 public string Method { get; set; } | |
23 | |
24 /// <summary>Whether the HTTP status code should be checked.</summary> | |
0
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
25 public bool CheckResponseCode { get; set; } |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
26 |
18 | 27 /// <summary>The required response code if CheckResponseCode is true.</summary> |
0
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
28 public int ResponseCode { get; set; } |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
29 |
18 | 30 /// <summary>Whether the response lenth should be checked.</summary> |
0
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
31 public bool CheckResponseLength { get; set; } |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
32 |
18 | 33 /// <summary>The required minimum response length if CheckResponseLength is true.</summary> |
0
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
34 public string ResponseLengthMin { get; set; } |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
35 |
18 | 36 /// <summary>The required maximum response length if CheckResponseLength is true.</summary> |
0
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
37 public string ResponseLengthMax { get; set; } |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
38 |
18 | 39 /// <summary>Whether the response body should be checked.</summary> |
0
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
40 public bool CheckResponseBody { get; set; } |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
41 |
18 | 42 /// <summary>The method to use when checking the response content against the pattern.</summary> |
0
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
43 public MatchType ResponseBodyMatchType { get; set; } |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
44 |
18 | 45 /// <summary>The string or pattern that the response content must match if CheckResponseBody is true.</summary> |
0
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
46 public string ResponseBodyPattern { get; set; } |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
47 |
18 | 48 /// <summary>Whether the ResponseBodyPattern should be interpreted as a regular expression.</summary> |
0
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
49 public bool ResponseBodyUseRegex { get; set; } |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
50 |
18 | 51 /// <summary>Executes the HTTP command on the server.</summary> |
52 protected async override Task<CheckResult> ExecuteCheckAsync(CancellationToken token) | |
0
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
53 { |
18 | 54 try |
55 { | |
56 // Disable auto redirect so we can get the true response code of the request. | |
57 using (HttpClientHandler handler = new HttpClientHandler() { AllowAutoRedirect = false }) | |
58 using (HttpClient client = new HttpClient(handler)) | |
59 using (HttpRequestMessage request = new HttpRequestMessage(new HttpMethod(Method), new Uri(Url))) | |
60 { | |
61 token.Register(client.CancelPendingRequests); | |
62 HttpResponseMessage response = await client.SendAsync(request, token); | |
63 token.ThrowIfCancellationRequested(); | |
64 List<CheckResult> results = await ProcessResponse(response); | |
65 return MergeResults(results.ToArray()); | |
66 } | |
67 } | |
68 catch (Exception e) | |
69 { | |
70 return Fail(e); | |
71 } | |
0
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
72 } |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
73 |
18 | 74 ///// <summary>Processes an HTTP response and checks that it matches the expected values.</summary> |
75 ///// <param name="response">The HTTP response.</param> | |
76 ///// <returns>A list of check results according to user preferences.</returns> | |
77 protected async virtual Task<List<CheckResult>> ProcessResponse(HttpResponseMessage response) | |
78 { | |
79 List<CheckResult> results = new List<CheckResult>(); | |
80 | |
81 // Check the actual response code against the expected response code if response code checking is enabled. | |
82 if (CheckResponseCode) | |
83 results.Add(GetIntResult(ResponseCode, (int)response.StatusCode, "Response code")); | |
84 | |
85 // Check the actual response length against the expected response length if response length checking is enabled. | |
86 if (CheckResponseLength) | |
87 { | |
88 string length = null; | |
89 if (Method == "HEAD") | |
90 { | |
91 // Use the Content-Length header if a HEAD request. | |
92 if (response.Headers.TryGetValues("Content-Length", out IEnumerable<string> values)) | |
93 { | |
94 length = values.First(); | |
95 } | |
96 } | |
97 else | |
98 { | |
99 // For a GET request, read the actual length | |
100 Stream stream = await response.Content.ReadAsStreamAsync(); | |
101 length = stream.Length.ToString(); | |
102 } | |
103 if (length != null) | |
104 { | |
105 results.Add(GetStringResult(MatchType.GreaterThan, (int.Parse(ResponseLengthMin) * 1024).ToString(), false, length, "Response length")); | |
106 results.Add(GetStringResult(MatchType.LessThan, (int.Parse(ResponseLengthMax) * 1024).ToString(), false, length, "Response length")); | |
107 } | |
108 else | |
109 { | |
110 results.Add(Fail("Could not get content length")); | |
111 } | |
112 } | |
113 | |
114 // Check the actual response content against the expected response content if response content checking is enabled. | |
115 if (CheckResponseBody && Method != "HEAD") | |
116 { | |
117 string content = await response.Content.ReadAsStringAsync(); | |
118 results.Add(GetStringResult(ResponseBodyMatchType, ResponseBodyPattern, ResponseBodyUseRegex, content, "Response body")); | |
119 } | |
120 | |
121 return results; | |
122 } | |
123 | |
124 /// <summary>Validates HTTP check options.</summary> | |
0
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
125 public override string Validate(bool saving = true) |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
126 { |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
127 string message = base.Validate(); |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
128 if (Url.IsNullOrEmpty()) |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
129 message += "URL cannot be blank." + Environment.NewLine; |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
130 if (!CheckResponseCode && !CheckResponseLength && !CheckResponseBody) |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
131 message += "At least one check must be enabled." + Environment.NewLine; |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
132 if (CheckResponseBody && ResponseBodyUseRegex) |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
133 { |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
134 try |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
135 { |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
136 Regex re = new Regex(ResponseBodyPattern); |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
137 } |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
138 catch (ArgumentException) |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
139 { |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
140 message += "Invalid regular expression for response body." + Environment.NewLine; |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
141 } |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
142 } |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
143 return message; |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
144 } |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
145 |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
146 } |
3e1a2131f897
Initial commit. Ping check, scheduling, UI working. SSH check mostly working.
Brad Greco <brad@bgreco.net>
parents:
diff
changeset
|
147 } |