Blaztrap.Aspire.Hosting.HttpEcho
0.3.0
dotnet add package Blaztrap.Aspire.Hosting.HttpEcho --version 0.3.0
NuGet\Install-Package Blaztrap.Aspire.Hosting.HttpEcho -Version 0.3.0
<PackageReference Include="Blaztrap.Aspire.Hosting.HttpEcho" Version="0.3.0" />
<PackageVersion Include="Blaztrap.Aspire.Hosting.HttpEcho" Version="0.3.0" />
<PackageReference Include="Blaztrap.Aspire.Hosting.HttpEcho" />
paket add Blaztrap.Aspire.Hosting.HttpEcho --version 0.3.0
#r "nuget: Blaztrap.Aspire.Hosting.HttpEcho, 0.3.0"
#:package Blaztrap.Aspire.Hosting.HttpEcho@0.3.0
#addin nuget:?package=Blaztrap.Aspire.Hosting.HttpEcho&version=0.3.0
#tool nuget:?package=Blaztrap.Aspire.Hosting.HttpEcho&version=0.3.0
Blaztrap.Aspire.Hosting.HttpEcho
In-process, Docker-free HTTP stub server for .NET 10 + Aspire. A WireMock-equivalent that
ships as a single NuGet package and plugs straight into any Aspire AppHost via a clean
builder.AddHttpEcho("echo") call site — no Projects.X metadata reference, no separate
runner project.
The same assembly carries:
- the stub server (an ASP.NET Core app the AppHost relaunches via
dotnet <ownDll>), - the AppHost integration (
AddHttpEcho,WithStub,WithHttpEchoEnvironment), - declarative validations (
RequireJsonField,RequireJsonNumberRange,RequireHeader,RequireQuery), - code-based stubs via the
HttpStubBaseclass for cases that outgrow declarative rules.
Install
dotnet add package Blaztrap.Aspire.Hosting.HttpEcho
Targets net10.0. Requires Aspire.Hosting 13.2+ on the AppHost side.
Quick start
In your Aspire AppHost project:
using Blaztrap.Aspire.Hosting.HttpEcho;
var builder = DistributedApplication.CreateBuilder(args);
var echo = builder.AddHttpEcho("echo")
.WithStub(s => s.OnGet("/hello").RespondWith(200, "Hello"))
.WithStub(s => s.OnGet("/json")
.RespondWith(200,
body: """{"message":"hi"}""",
headers: new() { ["Content-Type"] = "application/json" }))
.WithStub(s => s.OnPost("/orders").RespondWith(202))
.WithStub(s => s.OnPathMatching("^/users/[0-9]+$").RespondWith(200, "user-found"))
.WithStub(s => s.OnGet("/slow").WithFixedDelay(TimeSpan.FromMilliseconds(750))
.RespondWith(200, "ok"))
.WithStub("DELETE", "/items/42", 204);
builder.AddProject<Projects.MyApp>("api")
.WithHttpEchoEnvironment(echo) // injects HttpEcho__BaseUrl
.WaitFor(echo);
await builder.Build().RunAsync();
The consumer reads its endpoint from HttpEcho__BaseUrl (or HttpEcho:BaseUrl via
IConfiguration) and points an HttpClient at it — same shape as any other Aspire resource.
Declarative validations
Stubs match by method / path / query / headers / body-regex like WireMock. Once matched, any declared validation runs against the request — the first failure short-circuits with its own status + body, simulating an API that rejects malformed input.
// POST /people — must carry valid email and phone; otherwise 400.
.WithStub(s => s.OnPost("/people")
.RequireJsonField("email", @"^[^@\s]+@[^@\s]+\.[^@\s]+$",
onFailBody: """{"error":"invalid email"}""")
.RequireJsonField("phone", @"^\+?[0-9]{8,15}$",
onFailBody: """{"error":"invalid phone"}""")
.RespondWith(201, body: """{"id":"person-123"}"""))
// POST /transactions — body.amount must be a number in (0, 10_000].
.WithStub(s => s.OnPost("/transactions")
.RequireJsonNumberRange("amount", min: 0.01m, max: 10_000m,
onFailBody: """{"error":"amount out of allowed range"}""")
.RespondWith(200, body: """{"status":"accepted"}"""))
Other built-in helpers:
| Method | Source | Notes |
|---|---|---|
RequireJsonField(selector, pattern?, ...) |
JSON body, dotted path | required + optional regex |
RequireJsonNumberRange(selector, min?, max?, ...) |
JSON body, dotted path | numeric range |
RequireHeader(name, pattern?, ...) |
request header | required + optional regex |
RequireQuery(name, pattern?, ...) |
query parameter | required + optional regex |
WithValidation(v => …) |
full control of HttpEchoStubValidation |
for anything the helpers don't cover |
Code-based stubs
When a declarative rule won't cut it, derive from HttpStubBase. Un-overridden verbs
answer 405 Method Not Allowed automatically.
public sealed class InventoryStub : HttpStubBase
{
public override Task OnGet(HttpContext ctx, CancellationToken ct)
=> WriteJsonAsync(ctx, 200, """{"sku":"widget","stock":42}""", ct);
public override Task OnDelete(HttpContext ctx, CancellationToken ct)
=> WriteTextAsync(ctx, 204, body: null, ct);
// OnPost / OnPut / OnPatch → 405 by default
}
// AppHost:
.WithStub<InventoryStub>("/inventory/widget");
Constraints:
- The class must have a public parameterless constructor — the stub server constructs
its own instance via
Activator.CreateInstance(the server runs in a separate process; an instance passed at AppHost time would never cross the boundary). - The class must live in an assembly that lands in the AppHost's bin directory (any project the AppHost references satisfies this — the AppHost's own assembly works too).
Admin endpoints
The stub server exposes two diagnostic endpoints (no authentication):
GET /__admin/health→200 OKplain-text liveness probe.GET /__admin/mappings→ JSON dump of every configured stub + code stub, including validations attached to each.
How it works
The AppHost projects each stub as HttpEcho__Stubs__i__* environment variables (and
HttpEcho__CodeStubs__i__* for code stubs). The stub server reads them via
Microsoft.Extensions.Options. The library then relaunches itself as an Aspire
ExecutableResource via dotnet <ownDll> — so the AppHost call site never has to know
that the stub server is a project at all.
For NuGet consumers the package ships a .targets file that copies the lib's
runtimeconfig.json + deps.json next to your consumer's binary so the relaunch works
out of the box.
License & repository
See https://github.com/byteaid/blaztrap for source, issues, and changelog.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | 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
- Aspire.Hosting (>= 13.2.1)
- MessagePack (>= 2.5.302)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 0.3.0 | 55 | 7/13/2026 |