- Cross-platform .NET
HttpClientHandlerlibrary with certificate pinning, TLS enforcement, and advanced HTTP security. - Targets Android (OkHttp), iOS (NSUrlSession), and .NET (SocketsHttpHandler).
- See README.md for feature overview and installation.
# Build all projects (Debug)
dotnet build
# Build Release (generates NuGet package)
dotnet build -c Release
# Run .NET tests (Windows/Linux/macOS)
dotnet test SecureHttpClient.Test/SecureHttpClient.Test.csproj
# Run test runner console app
dotnet run --project SecureHttpClient.TestRunner.Net
# SDK pinned in global.json: .NET 10.0.301, rollForward: disabledConfiguration: Package versions managed centrally in
Directory.Packages.props. Shared properties (LangVersion,Nullable, TFMs) inDirectory.Build.props.
| Project | Purpose |
|---|---|
SecureHttpClient/ |
Main library — shared pinning logic + per-platform handlers in Platforms/ |
SecureHttpClient.OkHttp/ |
Android-only Java bindings (OkHttp interceptors, binding metadata) |
SecureHttpClient.Test/ |
xUnit integration tests (net10.0 only) |
SecureHttpClient.TestRunner.Net/ |
Console test runner |
SecureHttpClient.TestRunner.Maui/ |
MAUI GUI test runner (Android/iOS/Windows) |
Platform selection uses #if __ANDROID__ / #if __IOS__ directives, with .csproj conditional item groups filtering Platforms/ subdirectories.
Key abstractions: ISecureHttpClientHandler and IClientCertificateProvider in SecureHttpClient/Abstractions/.
- C# Coding Instructions — applicable sections: Naming Conventions, Formatting, Nullable Reference Types, Testing. Not all sections apply (ASP.NET Core / EF Core / JWT / Azure-specific guidance is not relevant to this library).
- Nullable reference types: Enabled globally (
<Nullable>enable</Nullable>). - C# version: Uses
LangVersion 14.0(C# 14), defined inDirectory.Build.props. - File-scoped namespaces: Used everywhere.
- Collection expressions: Preferred (e.g.,
["val1", "val2"]). - Pattern matching: Use pattern matching and switch expressions where possible.
- Structured logging:
_logger?.LogDebug("msg {Param}", value)— avoid string interpolation in log calls. - ConfigureAwait(false): Used in library code; NOT in test code.
- Internal fields:
_camelCaseprefix. - Null checks: Use
is null/is not nullinstead of== null/!= null. nameof: Prefernameof(...)over string literals when referring to member names.- XML doc comments: Required on all public APIs; include
<example>and<code>where applicable. - Braces: Insert newline before opening curly braces of any code block.
- Comments: Avoid unnecessary descriptive comments — code should be self-documenting. Only comment tricky logic, workarounds, or non-obvious constraints. All comments must be in English.
- Test methods: Naming pattern
{ClassName}_{Scenario}. - HttpRequestException with
AuthenticationExceptionInnerException: Consistent pattern for trust failures across all platforms.
- HTTP engine: Square OkHttp 5.4.0
- Compression via custom
DecompressInterceptor.java(gzip, deflate, brotli) - Certificate pinning delegated to OkHttp's native
CertificatePinner.Builder - Headers ordering supported via
HeadersOrderInterceptor.java - HTTP/3 NOT supported (OkHttp lacks QUIC)
- Extra NuGet deps:
Square.OkHttp3.Android,Square.OkIO,Xamarin.Brotli.Dec
- HTTP engine: NSUrlSession (ephemeral)
- Certificate pinning validated in
DataTaskDelegate.DidReceiveChallenge - HTTP/3: enabled from first request (
AssumesHttp3Capable = true) - Headers ordering NOT supported (logs warning)
- No extra NuGet deps beyond logging
- Complex infrastructure: 11 files under
Platforms/iOS/
- HTTP engine:
SocketsHttpHandler - Simplest platform — good reference for understanding the API surface
- AOT compatible (
IsAotCompatible=true) - Headers ordering NOT supported (logs warning)
- No extra NuGet deps beyond logging
- Reference:
SecureHttpClient/Platforms/Net/SecureHttpClientHandler.cs
SetHeadersOrderis Android-only — iOS and Net silently log a warning and ignore.- HTTP/3 unsupported on Android — OkHttp doesn't support QUIC. Tests use
SkipIfHttp3NotSupported(). - Content-Length mismatch on Android — writing fewer bytes than
HttpContent.ContentLengthcauses OkHttpProtocolException(JNI crash risk). SeeHttpTest_ContentLengthMismatchDoesNotCrashOkHttpThread. - GET with body — allowed on .NET, throws on Android/iOS. Tests use
Skip.Iffor those platforms. - Deflate encoding ambiguity — Android's decompressor distinguishes zlib (RFC 1950) from raw deflate (RFC 1951) by sniffing the first two bytes.
- iOS large uploads —
httpbingo.orgintermittently fails on iOS due to HTTP/2 flow control; usehttpbin.orginstead for large upload tests.
- Framework: xUnit v2.9.3 with
SkippableFact - Target:
net10.0only - External test dependencies:
httpbingo.org,httpbin.org,badssl.com,howsmyssl.com,github.com,cloudflare.com - Debug builds reference
SecureHttpClient.csprojdirectly; Release builds use NuGet package reference - Key test files:
SecureHttpClient.Test/HttpTest.cs— comprehensive HTTP functionality testsSecureHttpClient.Test/SslTest.cs— SSL/TLS and certificate testsSecureHttpClient.Test/CertificatePinnerTest.cs— pinning success/failure, wildcardsSecureHttpClient.Test/CertificateHelperTest.cs— SPKI fingerprint computationSecureHttpClient.Test/TestBase.cs— shared test infrastructure pattern