Nexar is a lightweight and ergonomic HTTP client for .NET. It offers static helpers, a fluent request builder, typed responses, and first-class support for common web API needs.
- Static Methods:
Nexar.Get<T>(),Nexar.Post<T>(),Nexar.Put<T>(),Nexar.Delete<T>(),Nexar.Patch<T>(),Nexar.Head<T>() - Instance API:
Nexar.Create()plusGetAsync<T>(),PostAsync<TRequest, TResponse>(), and more - Fluent Builder: Chain headers, query parameters, and body configuration
- Typed Responses:
NexarResponse<T>withData,Status,Headers,RawContent - Content Types: JSON, form URL encoded, multipart form data, binary
- Interceptors: Request, response, and error hooks
- Retries: Optional retries with exponential backoff
- Authentication Helpers: Bearer token, Basic auth, API key helpers
dotnet add package BuzzSpire.Nexarusing Nexar;
using Nexar.Configuration;
using Nexar.Models;var response = await Nexar.Get<User>("https://api.example.com/users/1");
if (response.IsSuccess && response.Data != null)
{
Console.WriteLine(response.Data.Name);
Console.WriteLine($"Status: {response.Status}");
}
// Need raw text? Use string as the response type.
var raw = await Nexar.Get<string>("https://api.example.com/users/1");
Console.WriteLine(raw.Data ?? raw.RawContent);var api = Nexar.Create(new NexarConfig
{
BaseUrl = "https://api.example.com",
DefaultHeaders = new Dictionary<string, string>
{
{ "Accept", "application/json" },
{ "User-Agent", "Nexar/1.0" }
},
TimeoutMs = 30_000,
MaxRetryAttempts = 3
});
var user = await api.GetAsync<User>("/users/1");var response = await Nexar.Create()
.Request()
.Url("https://api.example.com/search")
.WithHeader("Accept", "application/json")
.WithQuery("q", "nexar")
.WithQuery("limit", 10)
.GetAsync<SearchResults>();var response = await Nexar.Request<User>(new RequestOptions
{
Method = "POST",
Url = "/users",
BaseURL = "https://api.example.com",
Headers = new Dictionary<string, string>
{
{ "Authorization", "Bearer token" }
},
Data = new { Name = "John" },
ContentType = ContentType.Json,
Timeout = 5_000,
MaxRetries = 2,
ValidateSsl = true
});var response = await Nexar.Get<User>("/users/1");
Console.WriteLine(response.Data); // Deserialized object
Console.WriteLine(response.Status); // HTTP status code
Console.WriteLine(response.StatusText); // Status message
Console.WriteLine(response.Headers); // Response headers
Console.WriteLine(response.IsSuccess); // true/false
Console.WriteLine(response.RawContent); // Raw response bodyvar formData = new Dictionary<string, object>
{
{ "title", "My Document" },
{ "file", fileBytes }
};
var response = await api.PostAsync<Dictionary<string, object>, string>(
"/upload",
null,
formData,
ContentType.FormData);Available Content Types:
ContentType.JsonContentType.FormUrlEncodedContentType.FormDataContentType.Binary
public class LoggingInterceptor : IInterceptor
{
public Task<HttpRequestMessage> OnRequestAsync(HttpRequestMessage request)
{
Console.WriteLine($"-> {request.Method} {request.RequestUri}");
return Task.FromResult(request);
}
public Task<HttpResponseMessage> OnResponseAsync(HttpResponseMessage response)
{
Console.WriteLine($"<- {response.StatusCode}");
return Task.FromResult(response);
}
public Task OnErrorAsync(Exception exception)
{
Console.WriteLine($"Error: {exception.Message}");
return Task.CompletedTask;
}
}
var api = Nexar.Create();
api.Interceptors.Add(new LoggingInterceptor());var response = await Nexar.Create()
.Request()
.Url("/protected")
.WithBearerToken("your-jwt-token")
.GetAsync<Data>();var api = Nexar.Create(new NexarConfig
{
MaxRetryAttempts = 3,
RetryDelayMilliseconds = 1000,
UseExponentialBackoff = true
});- Samples:
samples - Getting Started:
docs/GetStarted.md
Contributions are welcome! Please feel free to submit a Pull Request.
This project is licensed under the MIT License.