![]() |
VOOZH | about |
dotnet add package Stardust.Interstellar.Rest --version 5.7.2
NuGet\Install-Package Stardust.Interstellar.Rest -Version 5.7.2
<PackageReference Include="Stardust.Interstellar.Rest" Version="5.7.2" />
<PackageVersion Include="Stardust.Interstellar.Rest" Version="5.7.2" />Directory.Packages.props
<PackageReference Include="Stardust.Interstellar.Rest" />Project file
paket add Stardust.Interstellar.Rest --version 5.7.2
#r "nuget: Stardust.Interstellar.Rest, 5.7.2"
#:package Stardust.Interstellar.Rest@5.7.2
#addin nuget:?package=Stardust.Interstellar.Rest&version=5.7.2Install as a Cake Addin
#tool nuget:?package=Stardust.Interstellar.Rest&version=5.7.2Install as a Cake Tool
Define once. Generate everywhere.
Generate strongly-typed HTTP clients from decorated interfaces.
Stardust.Rest lets you define your REST API as a C# interface�then automatically generates both client proxies and server controllers. No more handwriting HttpClient boilerplate or scaffolding controllers.
[Api("api/users")]
public interface IUserService
{
[Get("{id}")]
Task<User> GetAsync([InPath] string id);
[Post]
Task<User> CreateAsync([InBody] User user);
}
That's it. Share this interface between your client and server projects. The ecosystem handles the rest.
| Package | What it does |
|---|---|
| Annotations | Define your API contract |
| Client | Generate HTTP clients from interfaces ? you are here |
| Server | Generate ASP.NET Core controllers from interfaces |
dotnet add package Stardust.Interstellar.Rest
using Stardust.Interstellar.Rest.Annotations;
[Api("api/users")]
public interface IUserService
{
[Get("{id}")]
Task<User> GetUserAsync([InPath] string id);
[Get]
Task<IEnumerable<User>> GetAllAsync();
[Post]
Task<User> CreateAsync([InBody] User user);
[Put("{id}")]
Task<User> UpdateAsync([InPath] string id, [InBody] User user);
[Delete("{id}")]
Task DeleteAsync([InPath] string id);
}
services.AddInterstellar();
services.AddTransient(sp => sp.CreateRestClient<IUserService>("https://api.example.com"));
public class MyController
{
private readonly IUserService _users;
public MyController(IUserService users) => _users = users;
public async Task<User> GetUser(string id) => await _users.GetUserAsync(id);
}
services.AddTransient(sp => sp.CreateRestClient<IUserService>("https://api.example.com"));
Capture request metadata:
services.AddTransient(sp => sp.CreateRestClient<IUserService>(
"https://api.example.com",
extras => {
var retryCount = extras.ContainsKey("retryCount") ? extras["retryCount"] : 0;
}));
public class MyService
{
private readonly IProxyFactory _factory;
public MyService(IProxyFactory factory) => _factory = factory;
public async Task DoWork()
{
var client = _factory.CreateInstance<IExternalApi>("https://api.external.com");
var result = await client.GetDataAsync();
}
}
By default, the framework uses a static dictionary to cache HttpClient instances per base URL. This prevents socket exhaustion but doesn't handle DNS changes.
For production workloads, use the IHttpClientFactory integration for proper connection lifetime management:
// Program.cs or Startup.cs
services.AddStardustHttpClientFactory()
.SetHandlerLifetime(TimeSpan.FromMinutes(15)); // DNS refresh interval
// Or with custom configuration
services.AddStardustHttpClientFactory(client =>
{
client.Timeout = TimeSpan.FromSeconds(30);
client.DefaultRequestHeaders.Add("User-Agent", "MyApp/1.0");
});
Benefits of IHttpClientFactory:
[Get("search")]
Task<SearchResult> SearchAsync(
[InQuery("q")] string searchQuery, // ?q=laptop
[InQuery("page_size")] int pageSize, // ?page_size=10
[InHeader("X-Api-Key")] string apiKey); // X-Api-Key header
[Get("filter")]
Task<Data> GetFiltered([InQuery] Dictionary<string, string> filters);
// Expands to: ?key1=value1&key2=value2
Prevents cascading failures by stopping calls to failing services:
[CircuitBreaker(
threshold: 5, // Failures before opening
timeoutInMinutes: 1, // Time circuit stays open
resetTimeout: 2)] // Time before half-open
public interface IExternalService { }
Scoped circuit breakers isolate failures by user, client, or both:
[CircuitBreaker(5, 1, 2, CircuitBreakerScope.User)] // Per user
[CircuitBreaker(5, 1, 2, CircuitBreakerScope.Client)] // Per client
[CircuitBreaker(5, 1, 2, CircuitBreakerScope.UserAndClient)] // Multi-tenant
Automatic retry with exponential backoff:
[Retry(numberOfRetries: 3, retryInterval: 1000, incremetalWait: true)]
public interface IResilientService { }
Custom error categorization:
public class TransientErrorCategorizer : IErrorCategorizer
{
public bool IsTransientError(Exception ex) => ex is HttpRequestException
{ StatusCode: HttpStatusCode.ServiceUnavailable or HttpStatusCode.TooManyRequests };
}
[Retry(3, 1000, true, ErrorCategorizer = typeof(TransientErrorCategorizer))]
public interface IService { }
Implement IAuthenticationHandler:
public class BearerTokenHandler : IAuthenticationHandler
{
private readonly string _token;
public BearerTokenHandler(string token) => _token = token;
public void Apply(HttpRequestMessage req)
{
req.Headers.Authorization = new AuthenticationHeaderValue("Bearer", _token);
}
public Task ApplyAsync(HttpRequestMessage req) { Apply(req); return Task.CompletedTask; }
public void BodyData(byte[] body) { } // For signature-based auth (HMAC)
}
// Register
services.AddScoped<IAuthenticationHandler, BearerTokenHandler>();
Custom headers via IHeaderHandler:
public class CorrelationIdHandler : IHeaderHandler
{
public int ProcessingOrder => 0;
public void SetHeader(HttpRequestMessage req)
{
req.Headers.Add("X-Correlation-Id", Activity.Current?.Id ?? Guid.NewGuid().ToString());
}
// ... other interface members
}
services.AddScoped<IHeaderHandler, CorrelationIdHandler>();
Fluent configuration on client instances:
var client = sp.CreateRestClient<IUserService>("https://api.example.com");
client
.AddHeaderValue("X-Custom-Header", "value")
.SetVersion("v2") // Path: /v2/api/users
.SetQueryStringVersion("api-version", "2.0") // Query: ?api-version=2.0
.SetHeaderVersion("X-API-Version", "2.0") // Header version
.SetProxy(new WebProxy("http://proxy:8080"));
All HTTP errors are wrapped in RestWrapperException:
try
{
var user = await userService.GetUserAsync("123");
}
catch (RestWrapperException ex)
{
Console.WriteLine($"Status: {ex.StatusCode}");
Console.WriteLine($"Body: {ex.Value}");
}
Custom error handler:
public class ApiErrorHandler : IErrorHandler
{
public Exception ProduceClientException(
string message, HttpStatusCode statusCode,
Exception innerException, string responseBody)
{
var error = JsonSerializer.Deserialize<ApiError>(responseBody);
return new ApiException(error.Code, error.Message, statusCode);
}
}
[ErrorHandler(typeof(ApiErrorHandler))]
public interface IApiService { }
JSON (default) uses Newtonsoft.Json. XML is also supported:
[UseXml]
public interface IXmlService { }
ClientGlobalSettings.Timeout = 30; // HTTP timeout (seconds)
ClientGlobalSettings.PooledConnectionLifetime = TimeSpan.FromMinutes(15); // DNS refresh
ClientGlobalSettings.MaxConnectionsPerServer = 100; // Connection limit
ProxyFactory.RunAuthProviderBeforeAppendingBody = true; // Auth before body
ProxyFactory.EnableExpectContinue100ForPost = true; // Expect: 100-continue
The client library provides several built-in security features, but some security aspects require developer implementation.
| Feature | Status | Description |
|---|---|---|
| HTTP Header Injection Prevention | ? Built-in | Header names and values are automatically sanitized per RFC 7230 |
| HttpClient Connection Management | ? Built-in | IHttpClientFactory support for proper DNS handling |
| TLS/HTTPS | ? Uses System Default | Inherits .NET's default TLS configuration |
When implementing IAuthenticationHandler, follow these best practices:
public class SecureBearerTokenHandler : IAuthenticationHandler
{
private readonly ITokenProvider _tokenProvider;
public SecureBearerTokenHandler(ITokenProvider tokenProvider)
{
_tokenProvider = tokenProvider ?? throw new ArgumentNullException(nameof(tokenProvider));
}
public async Task ApplyAsync(HttpRequestMessage req)
{
// ? Get token from secure provider (Azure Key Vault, DPAPI, etc.)
var token = await _tokenProvider.GetTokenAsync();
if (!string.IsNullOrEmpty(token))
{
req.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token);
}
}
// ...
}
?? Security Checklist:
When implementing IHeaderHandler, ensure values are sanitized:
public class SecureHeaderHandler : IHeaderHandler
{
public void SetHeader(HttpRequestMessage req)
{
// ? Framework automatically sanitizes header values via SanitizeHttpHeaderValue()
// ? Framework automatically validates header names via SanitizeHttpHeaderName()
// ?? If bypassing framework methods, sanitize manually:
var userInput = GetUserInput();
// Remove CR/LF and other injection characters
var sanitized = userInput?.Replace("\r", "").Replace("\n", "") ?? "";
req.Headers.Add("X-Custom-Header", sanitized);
}
}
The framework uses Newtonsoft.Json for deserialization. For secure deserialization:
// Configure secure JSON settings for a service type
var settings = new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.None, // ?? Prevent type confusion attacks
MaxDepth = 64 // Prevent stack overflow
};
settings.AddClientSerializer<IMyService>();
?? Security Checklist:
TypeNameHandling = TypeNameHandling.None (default)IClientResponseInjector implementationsFor production environments, use IHttpClientFactory with proper TLS configuration:
services.AddStardustHttpClientFactory()
.ConfigurePrimaryHttpMessageHandler(() => new SocketsHttpHandler
{
SslOptions = new SslClientAuthenticationOptions
{
EnabledSslProtocols = SslProtocols.Tls12 | SslProtocols.Tls13,
// Optional: Certificate pinning
RemoteCertificateValidationCallback = ValidateCertificate
},
PooledConnectionLifetime = TimeSpan.FromMinutes(15),
MaxConnectionsPerServer = 100
});
Before deploying to production:
.NET Standard 2.0
Apache-2.0
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 net5.0 was computed. net5.0-windows net5.0-windows was computed. net6.0 net6.0 was computed. net6.0-android net6.0-android was computed. net6.0-ios net6.0-ios was computed. net6.0-maccatalyst net6.0-maccatalyst was computed. net6.0-macos net6.0-macos was computed. net6.0-tvos net6.0-tvos was computed. net6.0-windows net6.0-windows was computed. net7.0 net7.0 was computed. net7.0-android net7.0-android was computed. net7.0-ios net7.0-ios was computed. net7.0-maccatalyst net7.0-maccatalyst was computed. net7.0-macos net7.0-macos was computed. net7.0-tvos net7.0-tvos was computed. net7.0-windows net7.0-windows was computed. net8.0 net8.0 was computed. net8.0-android net8.0-android was computed. net8.0-browser net8.0-browser was computed. net8.0-ios net8.0-ios was computed. net8.0-maccatalyst net8.0-maccatalyst was computed. net8.0-macos net8.0-macos was computed. net8.0-tvos net8.0-tvos was computed. net8.0-windows net8.0-windows was computed. net9.0 net9.0 was computed. net9.0-android net9.0-android was computed. net9.0-browser net9.0-browser was computed. net9.0-ios net9.0-ios was computed. net9.0-maccatalyst net9.0-maccatalyst was computed. net9.0-macos net9.0-macos was computed. net9.0-tvos net9.0-tvos was computed. net9.0-windows net9.0-windows was computed. net10.0 net10.0 was computed. net10.0-android net10.0-android was computed. net10.0-browser net10.0-browser was computed. net10.0-ios net10.0-ios was computed. net10.0-maccatalyst net10.0-maccatalyst was computed. net10.0-macos net10.0-macos was computed. net10.0-tvos net10.0-tvos was computed. net10.0-windows net10.0-windows was computed. |
| .NET Core | netcoreapp2.0 netcoreapp2.0 was computed. netcoreapp2.1 netcoreapp2.1 was computed. netcoreapp2.2 netcoreapp2.2 was computed. netcoreapp3.0 netcoreapp3.0 was computed. netcoreapp3.1 netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.0 netstandard2.0 is compatible. netstandard2.1 netstandard2.1 was computed. |
| .NET Framework | net461 net461 was computed. net462 net462 was computed. net463 net463 was computed. net47 net47 was computed. net471 net471 was computed. net472 net472 was computed. net48 net48 was computed. net481 net481 was computed. |
| MonoAndroid | monoandroid monoandroid was computed. |
| MonoMac | monomac monomac was computed. |
| MonoTouch | monotouch monotouch was computed. |
| Tizen | tizen40 tizen40 was computed. tizen60 tizen60 was computed. |
| Xamarin.iOS | xamarinios xamarinios was computed. |
| Xamarin.Mac | xamarinmac xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos xamarinwatchos was computed. |
Showing the top 5 NuGet packages that depend on Stardust.Interstellar.Rest:
| Package | Downloads |
|---|---|
|
Veracity.Services.Api
SDK for accessing Veracity MyServices and Profile api. Veracity MyServices is your access point for engagement of digital interaction with DNV GL. You will find digital services like “Rules and Standards”, digital tools such as our OnDemand hosted service “Secure File Transfer“, our collaboration solution “Meeting Places” (SharePoint) and many other services. Some of the services are open to all users (like “Rules and Standards” and “Secure File Transfer”), while other services require an invitation from a DNV GL employee |
|
|
Stardust.Interstellar.Rest.Service.AspNetCore
Create webapi controllers based on decorated interfaces. For use with aspnetcore on netcore or .net framework |
|
|
Stardust.Continuum.Client
Client for the continuum live log stream service |
|
|
Stardust.Interstellar
Stardust servicecontainer implementation of the rest api generator. |
|
|
Stardust.Nucleus.Web
mvc and webapi integration of Stardust.Nucleus |
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 5.7.2 | 2,697 | 1/26/2026 |
| 5.7.1 | 137 | 1/21/2026 |
| 5.7.0 | 1,453 | 1/6/2026 |
| 5.6.1 | 6,096 | 8/9/2024 |
| 5.6.0 | 4,909 | 3/5/2024 |
| 5.5.5 | 713 | 11/10/2023 |
| 5.5.3 | 36,994 | 8/24/2022 |
| 5.5.2 | 40,719 | 5/23/2022 |
| 5.5.1 | 1,526 | 5/21/2022 |
| 5.5.0 | 1,944 | 5/16/2022 |
| 5.5.0-rc1 | 3,197 | 9/6/2021 |
| 5.0.1 | 60,768 | 4/6/2021 |
| 5.0.0 | 12,129 | 2/24/2021 |
Bugfix: nullreference when action parameters has null values
Enhancement: set WebProxy for IConfigurableService services
Bugfix: fixed over eager circuit breaker
Enhancement: Added IHttpClientProvider for proper HttpClient management with IHttpClientFactory support