2using System.Collections.Generic;
5using System.Net.Http.Headers;
6using System.Net.Security;
7using System.Runtime.ExceptionServices;
8using System.Security.Authentication;
9using System.Security.Cryptography.X509Certificates;
10using System.Threading.Tasks;
31 public string[]
UriSchemes =>
new string[] {
"http",
"https" };
41 switch (Uri.Scheme.ToLower())
62 public Task<object>
GetAsync(Uri Uri, X509Certificate Certificate,
64 params KeyValuePair<string, string>[] Headers)
66 return this.
GetAsync(Uri, Certificate, RemoteCertificateValidator, 60000, Headers);
78 public async Task<object>
GetAsync(Uri Uri, X509Certificate Certificate,
80 int TimeoutMs, params KeyValuePair<string, string>[] Headers)
82 HttpClientHandler Handler =
GetClientHandler(Certificate, RemoteCertificateValidator);
83 using (HttpClient HttpClient =
new HttpClient(Handler,
true)
85 Timeout = TimeSpan.FromMilliseconds(TimeoutMs)
88 using (HttpRequestMessage Request =
new HttpRequestMessage()
91 Method = HttpMethod.Get
94 PrepareHeaders(Request, Headers, Handler);
96 HttpResponseMessage Response = await HttpClient.SendAsync(Request);
121 RemoteCertificateValidator Validator =
new RemoteCertificateValidator(RemoteCertificateValidator);
123 HttpClientHandler Handler =
new HttpClientHandler()
125 AllowAutoRedirect =
true,
126 CheckCertificateRevocationList =
true,
127 ClientCertificateOptions = ClientCertificateOption.Automatic,
128 ServerCertificateCustomValidationCallback = Validator.RemoteCertificateValidationCallback,
129 AutomaticDecompression = (DecompressionMethods)(-1)
134 Handler.SslProtocols = SslProtocols.Tls | SslProtocols.Tls11 | SslProtocols.Tls12;
136 catch (PlatformNotSupportedException)
141 if (!(Certificate is
null))
143 Handler.ClientCertificateOptions = ClientCertificateOption.Manual;
144 Handler.ClientCertificates.Add(Certificate);
153 private class RemoteCertificateValidator
163 this.callback = Callback;
166 public bool RemoteCertificateValidationCallback(
object Sender,
167 X509Certificate Certificate, X509Chain Chain, SslPolicyErrors SslPolicyErrors)
171 if (!(this.callback is
null))
172 this.callback(Sender, e);
177 return SslPolicyErrors == SslPolicyErrors.None;
189 public static async Task<object>
ProcessResponse(HttpResponseMessage Response, Uri Uri)
191 byte[] Bin = await Response.Content.ReadAsByteArrayAsync();
195 if (Bin.Length == 0 || Response.Content.Headers.ContentType is
null)
198 ContentType =
string.Empty;
202 ContentType = Response.Content.Headers.ContentType.ToString();
207 await WebServerMetaContent.DecodeMetaInformation(Response);
209 if (!Response.IsSuccessStatusCode)
211 if (!(Decoded is
string Message))
213 if (Decoded is
null ||
214 (Decoded is
byte[] Bin2 && Bin2.Length == 0) ||
215 Decoded is Dictionary<string, object>)
217 Message = Response.ReasonPhrase;
220 Message = Decoded.ToString();
223 throw new WebException(Message, Response.StatusCode, ContentType, Bin, Decoded, Response.Headers);
229 internal static void PrepareHeaders(HttpRequestMessage Request, KeyValuePair<string, string>[] Headers, HttpClientHandler Handler)
231 if (!(Headers is
null))
233 foreach (KeyValuePair<string, string> Header
in Headers)
238 if (!Request.Headers.Accept.TryParseAdd(Header.Value))
239 throw new InvalidOperationException(
"Invalid Accept header value: " + Header.Value);
242 case "Authorization":
243 int i = Header.Value.IndexOf(
' ');
245 Request.Headers.Authorization =
new AuthenticationHeaderValue(Header.Value);
247 Request.Headers.Authorization =
new AuthenticationHeaderValue(Header.Value.Substring(0, i), Header.Value.Substring(i + 1).TrimStart());
252 Handler.CookieContainer.Add(Request.RequestUri,
new Cookie(P.Key, P.Value));
256 Request.Headers.Add(Header.Key, Header.Value);
271 public Task<KeyValuePair<string, TemporaryStream>>
GetTempStreamAsync(Uri Uri, X509Certificate Certificate,
274 return this.
GetTempStreamAsync(Uri, Certificate, RemoteCertificateValidator, 60000, Headers);
286 public async Task<KeyValuePair<string, TemporaryStream>>
GetTempStreamAsync(Uri Uri, X509Certificate Certificate,
289 HttpClientHandler Handler =
GetClientHandler(Certificate, RemoteCertificateValidator);
290 using (HttpClient HttpClient =
new HttpClient(Handler,
true)
292 Timeout = TimeSpan.FromMilliseconds(10000)
295 using (HttpRequestMessage Request =
new HttpRequestMessage()
298 Method = HttpMethod.Get
301 PrepareHeaders(Request, Headers, Handler);
303 HttpResponseMessage Response = await HttpClient.SendAsync(Request);
305 if (!Response.IsSuccessStatusCode)
308 string ContentType = Response.Content.Headers.ContentType.ToString();
312 await Response.Content.CopyToAsync(File);
319 ExceptionDispatchInfo.Capture(ex).Throw();
322 return new KeyValuePair<string, TemporaryStream>(ContentType, File);
346 public Task<object>
HeadAsync(Uri Uri, X509Certificate Certificate,
348 params KeyValuePair<string, string>[] Headers)
350 return this.
HeadAsync(Uri, Certificate, RemoteCertificateValidator, 60000, Headers);
362 public async Task<object>
HeadAsync(Uri Uri, X509Certificate Certificate,
364 int TimeoutMs, params KeyValuePair<string, string>[] Headers)
366 HttpClientHandler Handler =
GetClientHandler(Certificate, RemoteCertificateValidator);
367 using (HttpClient HttpClient =
new HttpClient(Handler,
true)
369 Timeout = TimeSpan.FromMilliseconds(TimeoutMs)
372 using (HttpRequestMessage Request =
new HttpRequestMessage()
375 Method = HttpMethod.Head
378 PrepareHeaders(Request, Headers, Handler);
380 HttpResponseMessage Response = await HttpClient.SendAsync(Request);
381 Dictionary<string, object> Result =
new Dictionary<string, object>()
383 {
"Status", Response.StatusCode },
384 {
"StatusCode", (int)Response.StatusCode },
385 {
"Message", Response.ReasonPhrase },
386 {
"IsSuccessStatusCode", Response.IsSuccessStatusCode },
387 {
"Version", Response.Version.ToString() }
390 foreach (KeyValuePair<
string, IEnumerable<string>> Header
in Response.Headers)
393 List<string> List =
null;
395 foreach (
string Value
in Header.Value)
402 List =
new List<string>() { s };
409 Result[Header.Key] = s;
411 Result[Header.Key] = List.ToArray();
Helps with parsing of commong data types.
static KeyValuePair< string, string >[] ParseFieldValues(string Value)
Parses a set of comma or semicolon-separated field values, optionaly delimited by ' or " characters.
Exception class for web exceptions.
Gets resources from the Web (i.e. using HTTP or HTTPS).
bool CanGet(Uri Uri, out Grade Grade)
If the getter is able to get a resource, given its URI.
WebGetter()
Gets resources from the Web (i.e. using HTTP or HTTPS).
static HttpClientHandler GetClientHandler(X509Certificate Certificate, RemoteCertificateEventHandler RemoteCertificateValidator)
Gets a HTTP Client handler
Task< object > HeadAsync(Uri Uri, X509Certificate Certificate, RemoteCertificateEventHandler RemoteCertificateValidator, params KeyValuePair< string, string >[] Headers)
Gets the headers of a resource, using a Uniform Resource Identifier (or Locator).
Task< object > GetAsync(Uri Uri, X509Certificate Certificate, RemoteCertificateEventHandler RemoteCertificateValidator, params KeyValuePair< string, string >[] Headers)
Gets a resource, using a Uniform Resource Identifier (or Locator).
async Task< object > GetAsync(Uri Uri, X509Certificate Certificate, RemoteCertificateEventHandler RemoteCertificateValidator, int TimeoutMs, params KeyValuePair< string, string >[] Headers)
Gets a resource, using a Uniform Resource Identifier (or Locator).
static HttpClientHandler GetClientHandler()
Gets a HTTP Client handler
static async Task< object > ProcessResponse(HttpResponseMessage Response, Uri Uri)
Decodes a response from the web. If the response is a success, the decoded response is returned....
string[] UriSchemes
Supported URI schemes.
Task< KeyValuePair< string, TemporaryStream > > GetTempStreamAsync(Uri Uri, X509Certificate Certificate, RemoteCertificateEventHandler RemoteCertificateValidator, params KeyValuePair< string, string >[] Headers)
Gets a (possibly big) resource, using a Uniform Resource Identifier (or Locator).
async Task< KeyValuePair< string, TemporaryStream > > GetTempStreamAsync(Uri Uri, X509Certificate Certificate, RemoteCertificateEventHandler RemoteCertificateValidator, int TimeoutMs, params KeyValuePair< string, string >[] Headers)
Gets a (possibly big) resource, using a Uniform Resource Identifier (or Locator).
bool CanHead(Uri Uri, out Grade Grade)
If the getter is able to get headers of a resource, given its URI.
async Task< object > HeadAsync(Uri Uri, X509Certificate Certificate, RemoteCertificateEventHandler RemoteCertificateValidator, int TimeoutMs, params KeyValuePair< string, string >[] Headers)
Gets the headers of a resource, using a Uniform Resource Identifier (or Locator).
Static class managing encoding and decoding of internet content.
static Task< object > DecodeAsync(string ContentType, byte[] Data, Encoding Encoding, KeyValuePair< string, string >[] Fields, Uri BaseUri)
Decodes an object.
Remove certificate validation event arguments.
bool? IsValid
If remote certificate is considered valid or not. null means default validation rules will be applied...
Manages a temporary stream. Contents is kept in-memory, if below a memory threshold,...
override void Dispose(bool disposing)
Releases the unmanaged resources used by the System.IO.Stream and optionally releases the managed res...
Interface for content classes, that process information available in HTTP headers in the response.
Basic interface for Internet Content getters. A class implementing this interface and having a defaul...
delegate void RemoteCertificateEventHandler(object Sender, RemoteCertificateEventArgs e)
Delegate for remote certificate event handlers.