Skip to content

Instantly share code, notes, and snippets.

@damianh
Created July 30, 2015 20:06
Show Gist options
  • Save damianh/b47e7a20694ef4d5a312 to your computer and use it in GitHub Desktop.
Save damianh/b47e7a20694ef4d5a312 to your computer and use it in GitHub Desktop.
ChaosMiddleware
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.Owin;
using AppFunc = System.Func<System.Collections.Generic.IDictionary<string, object>, System.Threading.Tasks.Task>;
using MidFunc = System.Func<
System.Func<System.Collections.Generic.IDictionary<string, object>, System.Threading.Tasks.Task>,
System.Func<System.Collections.Generic.IDictionary<string, object>, System.Threading.Tasks.Task>>;
public static class ChaosMiddleware
{
private static readonly List<AppFunc> s_monkeys;
static ChaosMiddleware()
{
s_monkeys = new List<AppFunc>
{
// Bunch of status codes
env => WriteStatus(env, 400, "Bad Request"),
env => WriteStatus(env, 403, "Forbidden"),
env => WriteStatus(env, 404, "Not found"),
env => WriteStatus(env, 408, "Request Timeout"),
env => WriteStatus(env, 429, "Too many requests"),
env => WriteStatus(env, 500, "Internal Server Error"),
env => WriteStatus(env, 502, "Bad Gateway"),
env => WriteStatus(env, 503, "Service Unavailable"),
env => WriteStatus(env, 504, "Gateway Timeout"),
//TODO
// - Malformed Content-MD5 request & response
// - drop properties from Json
// - corrupt encoding
// - change header name casing
};
}
/// <summary>
/// Creates a chaos MidFunc
/// </summary>
/// <param name="errorRatePercent">The percentage of time the request will result in some error.</param>
/// <param name="startWithSegment">The segment the request must start with before an error may be triggered.</param>
/// <returns>A chaos middleware.</returns>
public static MidFunc Create(int errorRatePercent, string startWithSegment)
{
var segment = new PathString(startWithSegment);
return next =>
{
var random = new Random();
return env =>
{
var context = new OwinContext(env);
if (!context.Request.Path.StartsWithSegments(segment) || errorRatePercent == 0)
{
return next(env);
}
var i = random.Next(1, 100);
if(i >= errorRatePercent)
{
return next(env);
}
i = random.Next(0, s_monkeys.Count - 1);
return s_monkeys[i](env);
};
};
}
private static async Task WriteStatus(IDictionary<string, object> env, int statusCode, string reasonPhrase)
{
var context = new OwinContext(env);
lock(Program.ConsoleWriterLock)
{
var foreground = Console.ForegroundColor;
Console.ForegroundColor = ConsoleColor.White;
Console.WriteLine(@"CHAOS MONKEY STRIKES \@(o・___・o)@/ {0} {1}", statusCode, context.Request.Uri.PathAndQuery);
Console.ForegroundColor = foreground;
}
context.Response.StatusCode = statusCode;
context.Response.ReasonPhrase = reasonPhrase;
context.Response.ContentType = "text/plain";
context.Response.Headers.Append("x-devdevserver-info", "chaos triggered");
await context.Response.WriteAsync(reasonPhrase);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment