Arkn.Http
0.3.2
dotnet add package Arkn.Http --version 0.3.2
NuGet\Install-Package Arkn.Http -Version 0.3.2
<PackageReference Include="Arkn.Http" Version="0.3.2" />
<PackageVersion Include="Arkn.Http" Version="0.3.2" />
<PackageReference Include="Arkn.Http" />
paket add Arkn.Http --version 0.3.2
#r "nuget: Arkn.Http, 0.3.2"
#:package Arkn.Http@0.3.2
#addin nuget:?package=Arkn.Http&version=0.3.2
#tool nuget:?package=Arkn.Http&version=0.3.2
Arkn.Http
Conventions you can read. Patterns you can enforce.
Fluent typed HTTP client where every call returns Result<T>. Built-in retry, timeout, and pluggable auth interceptors. No raw HttpClient.
Install
dotnet add package Arkn.Http
Quick example
// Define your typed client — minimal boilerplate
public class UserApiClient(IArknHttp http) : ArknHttpClient(http, "https://api.example.com")
{
public Task<Result<User>> GetAsync(Guid id) => GetAs<User>("/users/{id}", id);
public Task<Result<User>> CreateAsync(CreateUserRequest r) => PostAs<User>("/users", r);
public Task<Result<User>> UpdateAsync(Guid id, UpdateUserRequest r) => PutAs<User>("/users/{id}", r, id);
public Task<Result> DeleteAsync(Guid id) => Delete("/users/{id}", id);
}
// Register
builder.Services.AddArknHttp<UserApiClient>("https://api.example.com")
.WithRetry(maxAttempts: 3)
.WithTimeout(TimeSpan.FromSeconds(15));
Shorthand methods
ArknHttpClient exposes concise protected methods — no more .Request().Verb().As<T>() chains:
GetAs<T>(path, args) // GET → Result<T>
PostAs<T>(path, body) // POST → Result<T>
PutAs<T>(path, body, args) // PUT → Result<T>
PatchAs<T>(path, body, args) // PATCH → Result<T>
Delete(path, args) // DELETE → Result
Get(path, args) // GET → Result (no body)
Post(path, body) // POST → Result (no body)
Put(path, body, args) // PUT → Result (no body)
Auth interceptors
Bearer token (custom factory)
builder.Services.AddArknHttp<UserApiClient>("https://api.example.com")
.WithBearerAuth(async () =>
{
// Called once; token cached in InMemoryTokenStore for 55 min
return await myAuthService.GetAccessTokenAsync();
});
OAuth2 Client Credentials (built-in, zero external deps)
builder.Services.AddArknHttp<UserApiClient>("https://api.example.com")
.WithClientCredentials(opts =>
{
opts.TokenUrl = "https://auth.example.com/oauth/token";
opts.ClientId = "my-client";
opts.ClientSecret = config["Auth:Secret"];
opts.Scope = "api.read api.write";
});
The ClientCredentialsInterceptor fetches a token via POST to TokenUrl, caches it using InMemoryTokenStore (with buffer of 30s before expiry), and attaches it as Authorization: Bearer <token> on every request.
Custom interceptor
public sealed class ApiKeyInterceptor : IArknAuthInterceptor
{
private readonly string _key;
public ApiKeyInterceptor(string key) => _key = key;
public Task ApplyAsync(HttpRequestMessage req, CancellationToken ct = default)
{
req.Headers.Add("X-Api-Key", _key);
return Task.CompletedTask;
}
}
builder.Services.AddArknHttp<UserApiClient>("https://api.example.com")
.WithInterceptor(new ApiKeyInterceptor(config["ApiKey"]));
Debug logging
Loga request e response completos via IArknLogger — flui para todos os sinks configurados (console, arquivo, Application Insights).
// Dev — tudo em Debug
.WithDebugLogging()
// Preset de produção — 2xx em Info (chega no AppInsights), 4xx Warning, 5xx Error
.WithDebugLogging(DebugLoggingOptions.Production)
// Só falhas — 2xx são silenciosas
.WithDebugLogging(DebugLoggingOptions.FailuresOnly)
// Customizado
.WithDebugLogging(opts =>
{
opts.SuccessLevel = ArknLogLevel.Info;
opts.LogResponseBody = false;
opts.LogHeaders = false;
})
Presets
| Preset | 2xx | 4xx | 5xx | Caso de uso |
|---|---|---|---|---|
Development (default) |
Debug | Warning | Error | Dev local |
Production |
Info | Warning | Error | Tracing completo no AppInsights |
FailuresOnly |
Trace (silencioso) | Warning | Error | Só erros em prod |
Output de exemplo
→ GET https://api.example.com/users/123
Authorization: Bearer eyJhbGc*** ← sanitizado
← 200 OK (87ms)
Body: {
"id": "123",
"name": "Alice"
}
Integração com Application Insights
// Program.cs
builder.Services.AddArknLogging(logging =>
{
logging.AddConsoleSink(); // dev
if (!env.IsDevelopment())
logging.AddApplicationInsights(opts =>
{
opts.ConnectionString = config["AI:ConnectionString"];
opts.MinimumLevel = ArknLogLevel.Info; // 2xx chegam se Production preset
});
});
builder.Services.AddArknHttp<UserApiClient>("https://api.example.com")
.WithDebugLogging(env.IsDevelopment()
? DebugLoggingOptions.Development
: DebugLoggingOptions.Production);
- Headers sensíveis (
Authorization,Cookie,X-Api-Key) sanitizados automaticamente - Body de resposta formatado como JSON indentado quando possível
- Requer
IArknLoggerno DI viaAddArknLogging()
Token store
InMemoryTokenStore is registered as a singleton automatically when any auth method is configured. Tokens are cached with a 30-second expiry buffer and can be invalidated manually:
var store = serviceProvider.GetRequiredService<IArknTokenStore>();
await store.InvalidateAsync("my-client_credentials");
mTLS — Client Certificates
Attach a client certificate to every TLS handshake (mutual TLS) with zero boilerplate:
// From X509Certificate2 already loaded
.WithClientCertificate(certificate)
// From PFX/PKCS#12 file
.WithClientCertificate("/certs/client.pfx", password: "secret")
.WithClientCertificate("/certs/client.pfx") // no password
// From PEM files (cert + key separate)
.WithClientCertificatePem("/certs/client.crt", "/certs/client.key")
// From OS certificate store (Windows / macOS)
.WithClientCertificate(StoreName.My, StoreLocation.LocalMachine, thumbprint: "ABC123...")
When a certificate is configured, Arkn.Http creates a dedicated SocketsHttpHandler with SslClientAuthenticationOptions — the certificate is presented on every TLS handshake. Fully compatible with all other interceptors (OAuth2, ApiKey, debug logging, rate limiting, etc.).
Part of the Arkn ecosystem
github.com/fernando-terra/arkn · nuget.org/packages/Arkn.Http
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 is compatible. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- Arkn.Core (>= 0.3.2)
- Arkn.Logging (>= 0.3.2)
- Arkn.Results (>= 0.3.2)
- Microsoft.Extensions.Http (>= 10.0.7)
-
net8.0
- Arkn.Core (>= 0.3.2)
- Arkn.Logging (>= 0.3.2)
- Arkn.Results (>= 0.3.2)
- Microsoft.Extensions.Http (>= 10.0.7)
-
net9.0
- Arkn.Core (>= 0.3.2)
- Arkn.Logging (>= 0.3.2)
- Arkn.Results (>= 0.3.2)
- Microsoft.Extensions.Http (>= 10.0.7)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.