Lyo.Config.Api.Client
1.0.1
dotnet add package Lyo.Config.Api.Client --version 1.0.1
NuGet\Install-Package Lyo.Config.Api.Client -Version 1.0.1
<PackageReference Include="Lyo.Config.Api.Client" Version="1.0.1" />
<PackageVersion Include="Lyo.Config.Api.Client" Version="1.0.1" />
<PackageReference Include="Lyo.Config.Api.Client" />
paket add Lyo.Config.Api.Client --version 1.0.1
#r "nuget: Lyo.Config.Api.Client, 1.0.1"
#:package Lyo.Config.Api.Client@1.0.1
#addin nuget:?package=Lyo.Config.Api.Client&version=1.0.1
#tool nuget:?package=Lyo.Config.Api.Client&version=1.0.1
Lyo.Config.Api.Client
Typed HTTP client for the central Lyo.Config.Api — conditional app-config reads with If-None-Match / ?version polling, an optional X-Api-Key header, and a single DI extension. The client deliberately exposes only the resolve route (/api/config/{appKind}/{appId}); the management API ( /manage/...) is intended for operator tools, not service callers.
References Lyo.Config.Api.Models for ConfigResolveConditionalResult / ConfigResolveOutcome, and Lyo.Config for AppConfigEntity slug validation and ResolvedConfigRecord. For a polling host that publishes config via IOptionsMonitor<T>, see Lyo.Config.Api.Hosting.
Features
- Binds
ConfigApiClientOptionsfrom the section named byconfigSectionName(default"ConfigApi"viaConfigApiClientOptions.SectionName); the section is optional. - Registers
IOptions<ConfigApiClientOptions>(only when not already present). - Calls
services.AddHttpClient<IConfigApiClient, ConfigApiClient>(...)and returns theIHttpClientBuilderso callers can chain.AddHttpMessageHandler<…>()/.AddPolicyHandler(…)or replace the primary handler. - Wires the typed client:
BaseAddress = "{BaseUrl}/"whenBaseUrlis non-empty.- Adds the
X-Api-Key: <ApiKey>default request header whenApiKeyis non-empty. - Appends
gzip/deflate/brtoAccept-Encodingbased onAcceptEncodings. - Enables
HttpClientHandler.AutomaticDecompressionfromAcceptEncodingswhenEnableAutoResponseDecompression == true.
Examples
Register services
using Lyo.Config.Api.Client;
services.AddConfigApiClientFromConfiguration(configuration);
// Optional override:
// services.AddConfigApiClientFromConfiguration(configuration, configSectionName: "MyConfigApi");
appsettings
{
"ConfigApi": {
"BaseUrl": "https://config.internal.example/",
"ApiKey": "optional-shared-secret",
"PollInterval": "00:01:30",
"EnsureStatusCode": true,
"AcceptEncodings": ["gzip", "br"],
"EnableAutoResponseDecompression": true
}
}
Registration
- Binds
ConfigApiClientOptionsfrom the section named byconfigSectionName(default"ConfigApi"viaConfigApiClientOptions.SectionName); the section is optional. - Registers
IOptions<ConfigApiClientOptions>(only when not already present). - Calls
services.AddHttpClient<IConfigApiClient, ConfigApiClient>(...)and returns theIHttpClientBuilderso callers can chain.AddHttpMessageHandler<…>()/.AddPolicyHandler(…)or replace the primary handler. - Wires the typed client:
BaseAddress = "{BaseUrl}/"whenBaseUrlis non-empty.- Adds the
X-Api-Key: <ApiKey>default request header whenApiKeyis non-empty. - Appends
gzip/deflate/brtoAccept-Encodingbased onAcceptEncodings. - Enables
HttpClientHandler.AutomaticDecompressionfromAcceptEncodingswhenEnableAutoResponseDecompression == true.
ConfigApiClientOptions
Section: ConfigApi by default. Inherits from Lyo.Api.Client.ApiClientOptions.
| Property | Default | Purpose |
|---|---|---|
BaseUrl |
null |
Base URL of the Config API host. Trimmed and suffixed with /. |
ApiKey |
null |
When set, forwarded as X-Api-Key. The server only enforces it if ConfigApiSecurity.RequireApiKey == true (see Config.Api README). |
PollInterval (TimeSpan?) |
null |
Advisory only. Not consumed by ConfigApiClient; bring your own scheduler, or pass an explicit TimeSpan to ConfigPolling.PollUntilChangedAsync. |
EnsureStatusCode (bool) |
true |
When true, non-success responses (other than 304 Not Modified) call EnsureSuccessStatusCode() and throw HttpRequestException. When false, ResolveForAppAsync returns a ConfigResolveConditionalResult with Outcome = Failed and a populated Failure so the caller can inspect the status code without an exception. |
AcceptEncodings |
["gzip", "deflate", "br"] |
Advertised encodings; only gzip / deflate / br are honored (and br requires a non-netstandard2.0 target). |
EnableAutoResponseDecompression |
true |
Toggles the matching HttpClientHandler.AutomaticDecompression flags. |
RequestCompression |
ApiRequestCompressionType.None |
Inherited request-body compression — unused by the resolve route (GET / HEAD). |
RequestCompressionMinBytes |
1024 |
Inherited threshold for request-body compression. |
IConfigApiClient
public interface IConfigApiClient : IApiClient
{
Task<ConfigResolveConditionalResult> ResolveForAppAsync(
string appKind,
string appId,
string? ifNoneMatch = null,
string? version = null,
bool headOnly = false,
CancellationToken ct = default);
}
The interface inherits from Lyo.Api.Client.IApiClient, so callers receive the generic CRUD / Query helpers exposed by ApiClient on the same instance. Only the
resolve method is added by this client.
IConfigApiClient — ResolveForAppAsync parameters
| Parameter | Required | Description |
|---|---|---|
appKind |
yes | Process taxonomy slug (e.g. gateway, worker). Must match AppConfigEntity slug rules; otherwise an ArgumentException is thrown before the request is sent. URL-encoded into the path. |
appId |
yes | Instance id slug (e.g. prod-west, a GUID). Same slug rules; URL-encoded. |
ifNoneMatch |
no | Previous ETag (quoted or bare hex — the server normalizes weak prefixes / quotes). Sent verbatim as If-None-Match. When the server replies 304 Not Modified, the returned ConfigResolveConditionalResult.ETag falls back to this value. |
version |
no | Alternate fingerprint comparison sent as ?version=<bare-hex>. Empty / whitespace values are omitted. May be used together with If-None-Match; either match yields 304. |
headOnly |
no | When true, issues HEAD instead of GET and returns Outcome = Ok with Resolved = null on success. The server also responds 200 with no body for HEAD. |
ct |
no | Cancellation. Honored on SendAsync and JSON deserialization on modern targets. |
IConfigApiClient — EnsureStatusCode behavior in detail
HTTP 2xx→ConfigResolveConditionalResult { Outcome = Ok, ETag, Resolved }. If the server returns204 No Contentor the client usedheadOnly = true,Resolvedisnull.HTTP 304 Not Modified→ConfigResolveConditionalResult { Outcome = NotModified, ETag = <server etag or ifNoneMatch fallback>, Resolved = null }. Always returned — even whenEnsureStatusCode == true, because304is the expected polling response.HTTP 4xx/5xx:- When
EnsureStatusCode == true(default):response.EnsureSuccessStatusCode()is called and the resultingHttpRequestExceptionpropagates to the caller. - When
EnsureStatusCode == false: the method returnsConfigResolveConditionalResult { Outcome = Failed, ETag, Resolved = null, Failure = (StatusCode, ReasonPhrase) }so callers can branch on the status code without using exceptions for control flow. Use this mode when, for example, you want to treat409 Conflict(validation failure on the server) as a recoverable signal rather than a crash.
IConfigApiClient — Slug validation
appKind and appId are checked with AppConfigEntity.TryCreate(...) before any HTTP request. Invalid slugs throw ArgumentException with the same message the API would return as 400 Bad Request. There is no separate per-method validation toggle.
ConfigPolling.PollUntilChangedAsync
Helper for long-running pollers that simply want the next changed ResolvedConfigRecord:
var merged = await ConfigPolling.PollUntilChangedAsync(
configClient,
appKind: "api",
appId: "checkout",
ifNoneMatch: null,
delayWhenNotModified: TimeSpan.FromSeconds(15),
cancellationToken: ct);
Loop semantics:
| Server outcome | Action |
|---|---|
Ok with Resolved |
Return the payload immediately. |
NotModified |
Await delayWhenNotModified (cancellation-aware), reuse the latest ETag, and loop. |
Failed |
Throw InvalidOperationException carrying the status code / reason phrase from Failure. |
OperationHelpers.ThrowIfNull guards against a server returning Ok with no body; treat that as a contract bug.
Dependencies
Generated from ProjectReference / PackageReference (same model as docs/Lyo.ProjectGraph.html).
Lyo.Api.Client— (direct, lyo)Lyo.Config.Api.Models— (direct, lyo)Microsoft.Extensions.Http10.0.5— (direct, microsoft)Microsoft.Extensions.Options.ConfigurationExtensions10.0.5— (direct, microsoft)Lyo.Api.Models— (transitive, lyo)Lyo.Common— (transitive, lyo)Lyo.Config— (transitive, lyo)Lyo.DateAndTime— (transitive, lyo)Lyo.Diagnostic— (transitive, lyo)Lyo.EntityReference.Models— (transitive, lyo)Lyo.Exceptions— (transitive, lyo)Lyo.Hashing— (transitive, lyo)Lyo.PackageMetadata— (transitive, lyo)Lyo.Query.Models— (transitive, lyo)Microsoft.Extensions.DependencyInjection.Abstractions10.0.5— (transitive, microsoft)Microsoft.Extensions.Logging.Abstractions10.0.5— (transitive, microsoft)System.IO.Hashing10.0.5— (transitive, microsoft, net10.0)System.Memory4.6.3— (transitive, microsoft, netstandard2.0)System.Text.Json10.0.5— (transitive, microsoft, netstandard2.0)System.Threading.Tasks.Extensions4.6.3— (transitive, microsoft)
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. 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 was computed. 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. |
| .NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.0 is compatible. netstandard2.1 was computed. |
| .NET Framework | net461 was computed. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 was computed. net481 was computed. |
| MonoAndroid | monoandroid was computed. |
| MonoMac | monomac was computed. |
| MonoTouch | monotouch was computed. |
| Tizen | tizen40 was computed. tizen60 was computed. |
| Xamarin.iOS | xamarinios was computed. |
| Xamarin.Mac | xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.0
- Lyo.Api.Client (>= 1.0.1)
- Lyo.Config.Api.Models (>= 1.0.1)
- Microsoft.Extensions.Http (>= 10.0.5)
- Microsoft.Extensions.Options.ConfigurationExtensions (>= 10.0.5)
-
net10.0
- Lyo.Api.Client (>= 1.0.1)
- Lyo.Config.Api.Models (>= 1.0.1)
- Microsoft.Extensions.Http (>= 10.0.5)
- Microsoft.Extensions.Options.ConfigurationExtensions (>= 10.0.5)
NuGet packages (1)
Showing the top 1 NuGet packages that depend on Lyo.Config.Api.Client:
| Package | Downloads |
|---|---|
|
Lyo.Config.Api.Hosting
IHostedService polling + IOptionsMonitor binding from central Lyo Config API. |
GitHub repositories
This package is not used by any popular GitHub repositories.