5using System.Net.Http.Headers;
7using System.Reflection;
8using System.Security.Cryptography.X509Certificates;
10using System.Threading.Tasks;
26 private static bool useProxy =
true;
27 private static bool enforceHttps =
false;
39 public string[]
UriSchemes =>
new string[] {
"http",
"https" };
49 switch (Uri.Scheme.ToLower())
70 public Task<ContentResponse>
GetAsync(Uri Uri, X509Certificate Certificate,
71 EventHandler<RemoteCertificateEventArgs> RemoteCertificateValidator,
72 params KeyValuePair<string, string>[] Headers)
86 public async Task<ContentResponse>
GetAsync(Uri Uri, X509Certificate Certificate,
87 EventHandler<RemoteCertificateEventArgs> RemoteCertificateValidator,
88 int TimeoutMs, params KeyValuePair<string, string>[] Headers)
90 HttpClientHandler Handler =
GetClientHandler(Certificate, RemoteCertificateValidator, Uri);
91 using (HttpClient HttpClient =
new HttpClient(Handler,
true)
93 Timeout = TimeSpan.FromMilliseconds(TimeoutMs)
96 using (HttpRequestMessage Request =
new HttpRequestMessage()
98 Method = HttpMethod.Get
101 Request.RequestUri =
CheckUri(Uri, Request);
104 HttpResponseMessage Response = await HttpClient.SendAsync(Request);
118 if (Uri.Host !=
"localhost")
121 if (Uri.Scheme !=
"https")
131 Type T = Obj.GetType();
132 PropertyInfo PI = T.GetProperty(
"OpenHttpsPorts");
133 if (PI is
null || !PI.CanRead || !PI.GetMethod.IsPublic)
136 Obj = PI.GetValue(Obj);
137 if (!(Obj is
int[] OpenHttpsPorts))
140 foreach (
int OpenPort
in OpenHttpsPorts)
142 if (OpenPort == Port)
175 EventHandler<RemoteCertificateEventArgs> RemoteCertificateValidator)
188 EventHandler<RemoteCertificateEventArgs> RemoteCertificateValidator, Uri Uri)
201 EventHandler<RemoteCertificateEventArgs> RemoteCertificateValidator,
204 RemoteCertificateValidator Validator =
new RemoteCertificateValidator(RemoteCertificateValidator,
TrustServer);
206 HttpClientHandler Handler =
new HttpClientHandler()
208 AllowAutoRedirect =
true,
209 CheckCertificateRevocationList =
true,
210 ClientCertificateOptions = ClientCertificateOption.Automatic,
211 ServerCertificateCustomValidationCallback = Validator.RemoteCertificateValidationCallback,
212 AutomaticDecompression = (DecompressionMethods)(-1),
220 catch (PlatformNotSupportedException)
225 if (!(Certificate is
null))
227 Handler.ClientCertificateOptions = ClientCertificateOption.Manual;
228 Handler.ClientCertificates.Add(Certificate);
241 set => useProxy = value;
251 set => enforceHttps = value;
260 public static Uri
CheckUri(Uri Uri, HttpRequestMessage Request)
264 if (h is
null && !enforceHttps)
267 if (Uri.Scheme.ToLower() !=
"http")
278 else if (!enforceHttps)
282 if (Uri.Authority.IndexOf(
':') >= 0)
285 if (Uri.TryCreate(Uri.OriginalString.Replace(
"http:",
"https:"), UriKind.Absolute, out Uri Uri2))
301 private class RemoteCertificateValidator
303 private readonly EventHandler<RemoteCertificateEventArgs> callback;
304 private readonly
bool trustServer;
310 public RemoteCertificateValidator(EventHandler<RemoteCertificateEventArgs> Callback)
311 :
this(Callback,
false)
320 public RemoteCertificateValidator(EventHandler<RemoteCertificateEventArgs> Callback,
323 this.callback = Callback;
327 public bool RemoteCertificateValidationCallback(
object Sender,
328 X509Certificate Certificate, X509Chain Chain, SslPolicyErrors SslPolicyErrors)
330 if (!(this.callback is
null))
334 this.callback.Raise(Sender, e);
340 if (this.trustServer)
342 else if (SslPolicyErrors == SslPolicyErrors.None)
348 if (SslPolicyErrors.HasFlag(SslPolicyErrors.RemoteCertificateChainErrors) && !(Chain is
null))
350 foreach (X509ChainStatus Status
in Chain.ChainStatus)
354 if (Status.Status == X509ChainStatusFlags.RevocationStatusUnknown ||
355 Status.Status == X509ChainStatusFlags.OfflineRevocation)
360 if (Status.Status != X509ChainStatusFlags.NoError)
362 if (Certificate is X509Certificate2 Certificate2)
363 return Certificate2.Verify();
365 Certificate2 =
new X509Certificate2(Certificate.GetRawCertData());
367 return Certificate2.Verify();
386 public static async Task<ContentResponse>
ProcessResponse(HttpResponseMessage Response, Uri Uri)
388 byte[] Bin = await Response.Content.ReadAsByteArrayAsync();
392 if (Response.Content.Headers.ContentType is
null)
401 ContentType = Response.Content.Headers.ContentType.ToString();
408 await WebServerMetaContent.DecodeMetaInformation(Response);
410 if (!Response.IsSuccessStatusCode)
412 if (!(Decoded.
Decoded is
string Message))
415 Decoded.
Decoded is Dictionary<string, object>)
417 Message = Response.ReasonPhrase;
419 else if (Decoded.
Decoded is
byte[] Bin2)
421 if (Bin2.Length == 0)
422 Message = Response.ReasonPhrase;
428 Message = Decoded.ToString();
429 if (Message == Decoded.GetType().FullName)
430 Message = Response.ReasonPhrase;
447 public static void PrepareHeaders(HttpRequestMessage Request, KeyValuePair<string, string>[] Headers, HttpClientHandler Handler)
449 if (!(Headers is
null))
451 foreach (KeyValuePair<string, string> Header
in Headers)
456 if (!Request.Headers.Accept.TryParseAdd(Header.Value))
457 throw new InvalidOperationException(
"Invalid Accept header value: " + Header.Value);
460 case "Authorization":
461 int i = Header.Value.IndexOf(
' ');
463 Request.Headers.Authorization =
new AuthenticationHeaderValue(Header.Value);
465 Request.Headers.Authorization =
new AuthenticationHeaderValue(Header.Value.Substring(0, i), Header.Value.Substring(i + 1).TrimStart());
470 Handler.CookieContainer.Add(Request.RequestUri,
new Cookie(P.Key, P.Value));
474 Request.Headers.Add(Header.Key, Header.Value);
490 EventHandler<RemoteCertificateEventArgs> RemoteCertificateValidator, params KeyValuePair<string, string>[] Headers)
505 EventHandler<RemoteCertificateEventArgs> RemoteCertificateValidator,
TemporaryStream Destination, params KeyValuePair<string, string>[] Headers)
520 EventHandler<RemoteCertificateEventArgs> RemoteCertificateValidator,
int TimeoutMs, params KeyValuePair<string, string>[] Headers)
522 return this.
GetTempStreamAsync(Uri, Certificate, RemoteCertificateValidator, TimeoutMs,
null, Headers);
536 EventHandler<RemoteCertificateEventArgs> RemoteCertificateValidator,
int TimeoutMs,
TemporaryStream Destination,
537 params KeyValuePair<string, string>[] Headers)
539 HttpClientHandler Handler =
GetClientHandler(Certificate, RemoteCertificateValidator, Uri);
540 using (HttpClient HttpClient =
new HttpClient(Handler,
true)
542 Timeout = TimeSpan.FromMilliseconds(10000)
545 using (HttpRequestMessage Request =
new HttpRequestMessage()
547 Method = HttpMethod.Get
550 Request.RequestUri =
CheckUri(Uri, Request);
553 HttpResponseMessage Response = await HttpClient.SendAsync(Request, HttpCompletionOption.ResponseHeadersRead);
555 if (!Response.IsSuccessStatusCode)
561 string ContentType = Response.Content.Headers.ContentType.ToString();
562 bool TempStreamCreated =
false;
564 if (Destination is
null)
567 TempStreamCreated =
true;
572 await Response.Content.CopyToAsync(Destination);
576 if (TempStreamCreated)
609 public Task<ContentResponse>
HeadAsync(Uri Uri, X509Certificate Certificate,
610 EventHandler<RemoteCertificateEventArgs> RemoteCertificateValidator,
611 params KeyValuePair<string, string>[] Headers)
625 public async Task<ContentResponse>
HeadAsync(Uri Uri, X509Certificate Certificate,
626 EventHandler<RemoteCertificateEventArgs> RemoteCertificateValidator,
627 int TimeoutMs, params KeyValuePair<string, string>[] Headers)
629 HttpClientHandler Handler =
GetClientHandler(Certificate, RemoteCertificateValidator, Uri);
630 using (HttpClient HttpClient =
new HttpClient(Handler,
true)
632 Timeout = TimeSpan.FromMilliseconds(TimeoutMs)
635 using (HttpRequestMessage Request =
new HttpRequestMessage()
637 Method = HttpMethod.Head
640 Request.RequestUri =
CheckUri(Uri, Request);
643 HttpResponseMessage Response = await HttpClient.SendAsync(Request);
644 Dictionary<string, object> Result =
new Dictionary<string, object>()
646 {
"Status", Response.StatusCode },
647 {
"StatusCode", (int)Response.StatusCode },
648 {
"Message", Response.ReasonPhrase },
649 {
"IsSuccessStatusCode", Response.IsSuccessStatusCode },
650 {
"Version", Response.Version.ToString() }
653 foreach (KeyValuePair<
string, IEnumerable<string>> Header
in Response.Headers)
658 foreach (
string Value
in Header.Value)
672 Result[Header.Key] = s;
674 Result[Header.Key] = List.ToArray();
677 return new ContentResponse(Response.Content?.Headers.ContentType?.ToString() ??
string.Empty, Result,
null);
const string DefaultContentType
text/plain
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.
Contains information about a response to a content request.
string ContentType
Internet Content-Type of encoded object.
bool HasError
If an error occurred.
object Decoded
Decoded object.
Exception Error
Error response.
Contains information about a stream response to a content request.
Event arguments for the WebGetter.HttpUriEventHandler event.
Uri Uri
URI being processed
Exception class for web exceptions.
Gets resources from the Web (i.e. using HTTP or HTTPS).
static async Task< ContentResponse > ProcessResponse(HttpResponseMessage Response, Uri Uri)
Decodes a response from the web. If the response is a success, the decoded response is returned....
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).
async Task< ContentResponse > HeadAsync(Uri Uri, X509Certificate Certificate, EventHandler< RemoteCertificateEventArgs > RemoteCertificateValidator, int TimeoutMs, params KeyValuePair< string, string >[] Headers)
Gets the headers of a resource, using a Uniform Resource Identifier (or Locator).
static HttpClientHandler GetClientHandler(X509Certificate Certificate, EventHandler< RemoteCertificateEventArgs > RemoteCertificateValidator, Uri Uri)
Gets a HTTP Client handler
static bool UseProxy
If HTTP proxies should be used when making requests, when available. Default is true.
static HttpClientHandler GetClientHandler(bool TrustServer)
Gets a HTTP Client handler
static void PrepareHeaders(HttpRequestMessage Request, KeyValuePair< string, string >[] Headers, HttpClientHandler Handler)
Prepares headers for a HTTP request.
static EventHandler< HttpUriEventArgs > HttpUriEventHandler
Event raised when a HTTP only URI is being processed. Can be used to alter the URI,...
static bool EnforceHttps
If HTTPS should be enforced, even when accessing unencrypted HTTP resources. Default is false.
static HttpClientHandler GetClientHandler(X509Certificate Certificate, EventHandler< RemoteCertificateEventArgs > RemoteCertificateValidator, bool TrustServer)
Gets a HTTP Client handler
static HttpClientHandler GetClientHandler()
Gets a HTTP Client handler
string[] UriSchemes
Supported URI schemes.
Task< ContentStreamResponse > GetTempStreamAsync(Uri Uri, X509Certificate Certificate, EventHandler< RemoteCertificateEventArgs > RemoteCertificateValidator, int TimeoutMs, params KeyValuePair< string, string >[] Headers)
Gets a (possibly big) resource, using a Uniform Resource Identifier (or Locator).
static bool TrustServer(Uri Uri)
If the server certificate can be trusted.
Task< ContentStreamResponse > GetTempStreamAsync(Uri Uri, X509Certificate Certificate, EventHandler< RemoteCertificateEventArgs > RemoteCertificateValidator, TemporaryStream Destination, params KeyValuePair< string, string >[] Headers)
Gets a (possibly big) resource, using a Uniform Resource Identifier (or Locator).
async Task< ContentResponse > GetAsync(Uri Uri, X509Certificate Certificate, EventHandler< RemoteCertificateEventArgs > RemoteCertificateValidator, int TimeoutMs, params KeyValuePair< string, string >[] Headers)
Gets a 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.
static Uri CheckUri(Uri Uri, HttpRequestMessage Request)
Checks the URI, if it is suitable for processing, or if it needs to be modified.
Task< ContentResponse > HeadAsync(Uri Uri, X509Certificate Certificate, EventHandler< RemoteCertificateEventArgs > RemoteCertificateValidator, params KeyValuePair< string, string >[] Headers)
Gets the headers of a resource, using a Uniform Resource Identifier (or Locator).
Task< ContentStreamResponse > GetTempStreamAsync(Uri Uri, X509Certificate Certificate, EventHandler< RemoteCertificateEventArgs > RemoteCertificateValidator, params KeyValuePair< string, string >[] Headers)
Gets a (possibly big) resource, using a Uniform Resource Identifier (or Locator).
static HttpClientHandler GetClientHandler(X509Certificate Certificate, EventHandler< RemoteCertificateEventArgs > RemoteCertificateValidator)
Gets a HTTP Client handler
async Task< ContentStreamResponse > GetTempStreamAsync(Uri Uri, X509Certificate Certificate, EventHandler< RemoteCertificateEventArgs > RemoteCertificateValidator, int TimeoutMs, TemporaryStream Destination, params KeyValuePair< string, string >[] Headers)
Gets a (possibly big) resource, using a Uniform Resource Identifier (or Locator).
Task< ContentResponse > GetAsync(Uri Uri, X509Certificate Certificate, EventHandler< RemoteCertificateEventArgs > RemoteCertificateValidator, params KeyValuePair< string, string >[] Headers)
Gets a resource, using a Uniform Resource Identifier (or Locator).
Static class managing encoding and decoding of internet content.
static int DefaultTimeout
Default timeout of internet access methods, in milliseconds.
static Task< ContentResponse > 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...
A chunked list is a linked list of chunks of objects of type T .
void Add(T Item)
Adds an item to the collection.
Static class managing binary representations of strings.
static string GetString(byte[] Data, int Offset, int Count, Encoding DefaultEncoding)
Gets a string from its binary representation, taking any Byte Order Mark (BOM) into account.
Static class that dynamically manages types and interfaces available in the runtime environment.
static bool TryGetModuleParameter(string Name, out object Value)
Tries to get a module parameter value.
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...
Helper methods for encrypting and decrypting streams of data.
const SslProtocols TlsOnly
TLS 1.0, 1.1, 1.2 & 1.3
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...