Get it on nuget.
A functional routing library for ASP.NET Core, stolen from inspired by Giraffe and Suave.
ASP.NET Core is a fast, modern web framework.
This library provides a different routing layer over the core.
Instead of a jungle of controllers with a maze of attributes, which get discovered through reflection, you just have one object (the root handler that gets passed to AddKoala()) which itself gets composed from smaller objects.
In most cases, your routing definition is a block less than one page long, which you can read top to bottom, left to right.
- Your api got so big that you have one large block? Just split it into multiple logical units and compose it at the root.
- You have an api that you want to re-use in two projects? Just put it into a lib and reference it.
- You need to parametrize a route based on the customer name?
routeis just a function, so you can pass it a variable instead of a constant. You can't do the same with a[Route("...")]Attribute ;-)
Add the NuGet package Koala to a new Console Application and copy-paste this into your Program.cs:
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore;
using static Koala.Routing;
namespace Koala.HelloWorld
{
public class KoalaHelloWorld
{
private static IWebHost ConfigureWebHostFromKoalaHandler(string[] args, int port, HttpHandler handler)
{
var webHost =
WebHost.CreateDefaultBuilder(args)
.Configure(app =>
{
app.AddKoala(handler);
})
.UseKestrel(c =>
{
c.ListenAnyIP(port);
})
.Build();
return webHost;
}
public static void Main(string[] args)
{
var handler = route("/", text("Hello World!"));
using (var webHost = ConfigureWebHostFromKoalaHandler(args, port: 5000, handler: handler))
{
// .Run() is blocking, to start the webserver non-blocking, call .Start()
webHost.Run();
}
}
}
}The two important parts are:
-
app.AddKoala(handler);in yourConfigurecallback. This integrates Koala into your pipeline. -
The routing definition:
var handler = route("/", text("Hello World!"));
The rest is just standard ASP.NET Core.
// The function to validate credentials.
bool authenticator((string user, string pw) credentials)
{
// Normally you would hash the password and compare it against a database or whatever.
// Here it is just checked against a hardcoded value.
return credentials == ("Bond", "007");
}
var handler =
choose(new[]
{
GET(
choose(new[]
{
route("/", text("Hello World!")),
// show how handlers can be combined, and how easily a new handler can be created from these building blocks.
route("/protected", basicAuth(authenticator, HttpHandler.Wrap(ctx => text($"Welcome Agent {ctx.User.Identity.Name}!"))))
})),
subRoute("/api",
choose(new[]{
GET(route("/time", HttpHandler.Wrap(ctx => text($"{DateTime.Now}")))),
POST(route("/ping", text("pong")))
}))
});(Almost) Everything in Koala is a HttpHandler.
A HttpHandler can
-
filter requests (
GET, which checks the Http Verb, orroute, which checks that the route matches)
=> if the filter doesn't match, it will no-op and (if inside achoose) give the next handler a chance to run. They run in the order they are defined from top to bottom. -
modify and/or reject requests =>
basicAuthwill check the credentials, and either setctx.User(if successfull), or send back 401 UNAUTHORIZED with aWWW-Authenticate: Basicchallenge. -
terminate the request =>
textwill set the headerContent-Type: text/plainand send the specified text back in the response body.