#nullable enable using System.Net.Security; namespace gehGassiApp.Core.Helper { /// /// Hilfsklasse für das lokale Debugging. /// Ermöglicht den Zugriff auf die lokal REST-API /// public class DevHttpsConnectionHelper { /// /// Erstellt eine Instanz /// /// Port public DevHttpsConnectionHelper(int sslPort) { SslPort = sslPort; DevServerRootUrl = FormattableString.Invariant($"https://{DevServerName}:{SslPort}"); #if WINDOWS LazyHttpClient = new Lazy(() => new HttpClient()); #else LazyHttpClient = new Lazy(() => new HttpClient(GetPlatformMessageHandler())); #endif } public int SslPort { get; } public string DevServerName => #if WINDOWS "localhost"; #elif ANDROID "192.168.0.172"; #elif IOS || MACCATALYST "192.168.0.172"; #else throw new PlatformNotSupportedException("Only Windows and Android currently supported."); #endif public string DevServerRootUrl { get; } private Lazy LazyHttpClient; public HttpClient HttpClient => LazyHttpClient.Value; public HttpMessageHandler? GetPlatformMessageHandler() { #if WINDOWS return null; #elif IOS || MACCATALYST var handler = new NSUrlSessionHandler { TrustOverrideForUrl = IsHttpsLocalhost }; return handler; #elif ANDROID var handler = new CustomAndroidMessageHandler(); handler.ServerCertificateCustomValidationCallback = (message, cert, chain, errors) => { if (cert != null && cert.Issuer.Equals("CN=localhost")) return true; return errors == SslPolicyErrors.None; }; return handler; #else throw new PlatformNotSupportedException("Only Windows and Android currently supported."); #endif } #if ANDROID internal sealed class CustomAndroidMessageHandler : Xamarin.Android.Net.AndroidMessageHandler { protected override Javax.Net.Ssl.IHostnameVerifier GetSSLHostnameVerifier(Javax.Net.Ssl.HttpsURLConnection connection) => new CustomHostnameVerifier(); private sealed class CustomHostnameVerifier : Java.Lang.Object, Javax.Net.Ssl.IHostnameVerifier { public bool Verify(string? hostname, Javax.Net.Ssl.ISSLSession? session) { return Javax.Net.Ssl.HttpsURLConnection.DefaultHostnameVerifier.Verify(hostname, session) || hostname == "192.168.0.172" && session.PeerPrincipal?.Name == "CN=localhost"; } } } #elif IOS || MACCATALYST public bool IsHttpsLocalhost(NSUrlSessionHandler sender, string url, Security.SecTrust trust) { if (url.StartsWith("https://localhost") || url.StartsWith("https://192.168.0.172")) return true; return false; } #endif } public static class DevHttpsConnectionHelperExtensions { public static IServiceCollection AddDevHttpClient(this IServiceCollection services, int sslPort) { var devSslHelper = new DevHttpsConnectionHelper(sslPort); var http = devSslHelper.HttpClient; http.BaseAddress = new Uri(devSslHelper.DevServerRootUrl); services.AddScoped(sp => http); return services; } } }