13
13
// limitations under the License.
14
14
15
15
using System ;
16
+ using System . Collections . Generic ;
16
17
using System . Diagnostics ;
17
18
using System . IO ;
18
19
using System . Net . Http ;
21
22
using System . Threading ;
22
23
using System . Threading . Tasks ;
23
24
using Newtonsoft . Json . Linq ;
25
+ using Seq . Input . HealthCheck . Data ;
24
26
using Seq . Input . HealthCheck . Util ;
25
27
26
28
namespace Seq . Input . HealthCheck
@@ -29,36 +31,38 @@ class HttpHealthCheck
29
31
{
30
32
readonly string _title ;
31
33
readonly string _targetUrl ;
32
- readonly JsonDataExtractor _extractor ;
34
+ readonly List < ( string , string ) > _headers ;
35
+ readonly JsonDataExtractor ? _extractor ;
33
36
readonly bool _bypassHttpCaching ;
34
37
readonly HttpClient _httpClient ;
35
38
readonly byte [ ] _buffer = new byte [ 2048 ] ;
36
39
37
40
public const string ProbeIdParameterName = "__probe" ;
38
41
39
- static readonly UTF8Encoding ForgivingEncoding = new UTF8Encoding ( false , false ) ;
42
+ static readonly UTF8Encoding ForgivingEncoding = new ( false , false ) ;
40
43
const int InitialContentChars = 16 ;
41
44
const string OutcomeSucceeded = "succeeded" , OutcomeFailed = "failed" ;
42
45
43
- public HttpHealthCheck ( HttpClient httpClient , string title , string targetUrl , JsonDataExtractor extractor , bool bypassHttpCaching )
46
+ public HttpHealthCheck ( HttpClient httpClient , string title , string targetUrl , List < ( string , string ) > headers , JsonDataExtractor ? extractor , bool bypassHttpCaching )
44
47
{
45
48
_httpClient = httpClient ?? throw new ArgumentNullException ( nameof ( httpClient ) ) ;
46
49
_title = title ?? throw new ArgumentNullException ( nameof ( title ) ) ;
47
50
_targetUrl = targetUrl ?? throw new ArgumentNullException ( nameof ( targetUrl ) ) ;
51
+ _headers = headers ;
48
52
_extractor = extractor ;
49
53
_bypassHttpCaching = bypassHttpCaching ;
50
54
}
51
-
55
+
52
56
public async Task < HealthCheckResult > CheckNow ( CancellationToken cancel )
53
57
{
54
58
string outcome ;
55
59
56
- Exception exception = null ;
60
+ Exception ? exception = null ;
57
61
int ? statusCode = null ;
58
- string contentType = null ;
62
+ string ? contentType = null ;
59
63
long ? contentLength = null ;
60
- string initialContent = null ;
61
- JToken data = null ;
64
+ string ? initialContent = null ;
65
+ JToken ? data = null ;
62
66
63
67
var probeId = Nonce . Generate ( 12 ) ;
64
68
var probedUrl = _bypassHttpCaching ?
@@ -73,6 +77,12 @@ public async Task<HealthCheckResult> CheckNow(CancellationToken cancel)
73
77
var request = new HttpRequestMessage ( HttpMethod . Get , probedUrl ) ;
74
78
request . Headers . Add ( "X-Correlation-ID" , probeId ) ;
75
79
80
+ foreach ( var ( name , value ) in _headers )
81
+ {
82
+ // This will throw if a header is duplicated (better for the user to detect this configuration problem).
83
+ request . Headers . Add ( name , value ) ;
84
+ }
85
+
76
86
if ( _bypassHttpCaching )
77
87
request . Headers . CacheControl = new CacheControlHeaderValue { NoStore = true } ;
78
88
@@ -82,7 +92,7 @@ public async Task<HealthCheckResult> CheckNow(CancellationToken cancel)
82
92
contentType = response . Content . Headers . ContentType ? . ToString ( ) ;
83
93
contentLength = response . Content . Headers . ContentLength ;
84
94
85
- var content = await response . Content . ReadAsStreamAsync ( ) ;
95
+ var content = await response . Content . ReadAsStreamAsync ( cancel ) ;
86
96
( initialContent , data ) = await DownloadContent ( content , contentType , contentLength ) ;
87
97
88
98
outcome = response . IsSuccessStatusCode ? OutcomeSucceeded : OutcomeFailed ;
@@ -118,18 +128,18 @@ public async Task<HealthCheckResult> CheckNow(CancellationToken cancel)
118
128
}
119
129
120
130
// Either initial content, or extracted data
121
- async Task < ( string initialContent , JToken data ) > DownloadContent ( Stream body , string contentType , long ? contentLength )
131
+ async Task < ( string ? initialContent , JToken ? data ) > DownloadContent ( Stream body , string ? contentType , long ? contentLength )
122
132
{
123
133
if ( _extractor == null ||
124
134
contentLength == 0 ||
125
135
contentType != "application/json; charset=utf-8" && contentType != "application/json" )
126
136
{
127
- var read = await body . ReadAsync ( _buffer , 0 , _buffer . Length ) ;
137
+ var read = await body . ReadAsync ( _buffer ) ;
128
138
var initial = ForgivingEncoding . GetString ( _buffer , 0 , Math . Min ( read , InitialContentChars ) ) ;
129
139
130
140
// Drain the response to avoid dropped connection errors on the server.
131
141
while ( read > 0 )
132
- read = await body . ReadAsync ( _buffer , 0 , _buffer . Length ) ;
142
+ read = await body . ReadAsync ( _buffer ) ;
133
143
134
144
return ( initial , null ) ;
135
145
}
0 commit comments