A Web Server that Echoes Requests and Sometimes Faults with a 500 Error
Download full source code.
Last month I wrote a post about building a server that echoes the request it receives. I use it when I want to test HttpClient, HttpClientFactory, or related tools.
I thought it would be fun to build a faulting echo server. This server will return a 500 error for a percentage of the time. This is a great way to test your error handling code. The provided code throws an exception 50% of the time, but you can easily extend the example to take parameters to control the percentage of errors, or the type of error. If you wanted to do this, I suggest doing it via header parameters.
Here are the basics.
The Response
The first thing I need is a model to send as the response. I’ll call it EchoResponse
. I’ve included the properties from the request that I’m interested in, you may want fewer, or more -
public class EchoResponse
{
public string Body { get; set; }
public IHeaderDictionary Headers { get; set; }
public string Method { get; set; }
public PathString Path {get; set; }
public QueryString QueryString { get; set; }
public IQueryCollection Query { get; set; }
}
Then I need an extension method to convert the HttpRequest
to an EchoResponse
-
public static class ExtensionMethods
{
public static async Task<EchoResponse> ToEchoResponseAsync(this HttpRequest request)
{
var echoResponse = new EchoResponse();
using (StreamReader streamReader = new StreamReader(request.Body))
{
echoResponse.Body = await streamReader.ReadToEndAsync();
};
echoResponse.Method = request.Method;
echoResponse.Headers = request.Headers;
echoResponse.Path = request.Path;
echoResponse.QueryString = request.QueryString;
echoResponse.Query = request.Query;
return echoResponse;
}
}
The Simmy NuGet Package
Simmy allows you to inject faults into your code. I’ve written a few posts about it.
Add Simmy to your project -
dotnet add package Polly.Contrib.Simmy
Create the fault policy
Open the Program.cs
file and add two using statements -
using Polly.Contrib.Simmy;
using Polly.Contrib.Simmy.Outcomes;
Below the line where WebApplication.CreateBuilder(args)
is called, add the following -
Exception fault = new Exception("Big problem");
AsyncInjectOutcomePolicy chaosPolicy = MonkeyPolicy.InjectExceptionAsync(with =>
with.Fault(fault)
.InjectionRate(0.5)
.Enabled()
);
builder.Services.AddSingleton<AsyncInjectOutcomePolicy>(chaosPolicy);
The above creates the chaos policy and adds it to the service collection. The policy will inject a fault 50% of the time.
You can now use the policy with API endpoints, or full controllers.
Minimal API Endpoint
This will map all HTTP methods to the same endpoint, for all URLs -
app.Map("{*anyurl}", async (HttpRequest httpRequest, AsyncInjectOutcomePolicy chaosPolicy) =>
{
return await chaosPolicy.ExecuteAsync(() => httpRequest.ToEchoResponseAsync());
});
Now you can use GET/PUT/POST/PATCH/DELETE with any URL and this endpoint will be hit.
That’s it! Simple!
Controller
To use the policy with a controller, add the policy to the constructor -
using Microsoft.AspNetCore.Mvc;
using Polly.Contrib.Simmy.Outcomes;
[ApiController]
[Route("[controller]")]
public class EchoController : ControllerBase
{
private readonly AsyncInjectOutcomePolicy _chaosPolicy;
public EchoController(AsyncInjectOutcomePolicy chaosPolicy)
{
_chaosPolicy = chaosPolicy;
}
public async Task<EchoResponse> All()
{
return await _chaosPolicy.ExecuteAsync(() => Request.ToEchoResponseAsync());
}
}
You should use only the minimal endpoint or the controller at one time.
Testing it out
Use tools such as Fiddler, Postman, or Rest Client for VS Code (I’ve included a sample file in the attached zip) to make requests to the API.
Download full source code.