DEV Community

William Olsen
William Olsen

Posted on

Request Handler Design

This post is a little abstract, not a tutorial or anything. I was rewriting the the class in Impart for the handling of Rest API requests. This led to a a bit of a fork in how I should design the handler.

The idea I previously had was:
(covered in this post)

using Impart;
using Impart.API;

public class Program
{
    static void Main(string[] args)
    {
        Rest r = new Rest();
        r.OnRequest += OnRequest;
        r.Start();
    }
    static void OnRequest(APIEventArgs e, RestContext c)
    {
        Json j = new Json("Impart", ("Developer", "William Olsen"), ("Current Downloads", 519), ("Current Stars", 8));
        c.Respond(j);
    }
}
Enter fullscreen mode Exit fullscreen mode

Obviously this doesn't even begin to account for the URL routing. For example, if I wanted to send a specific JSON response at localhost:8080/test, I am unable. This basically defeats the entire point of creating an API.

The first idea for a fix that comes to mind is to simply include the URL information in the APIEventArgs or RestContext objects. That would however, lead to the developer writing something like this:

static void OnRequest(APIEventArgs e, RestContext c)
{
    switch (c.Url)
    {
        case "/test":
            //the user accessed localhost:8080/test
            break;
        case "":
            //the user accessed localhost:8080
            break;
    }
}
Enter fullscreen mode Exit fullscreen mode

Now me being the kind of person who didn't add slash commands using Discord.Net because they specifically entailed using giant switch statements, this didn't feel right.

Studying popular C# API hosting libraries, it seems like the clearest fix is to separate each request by method.

But how would one go about doing this?

The answer is using System.Reflection and custom attributes. A little warning: the code to analyze these methods is very, very, ugly, so beware.

A quick implementation would look like this to the developer:

[RestRequest("/test")]
public void RequestHandle1(APIEventArgs e, RestContext c)
{
    //the user accessed localhost:8080/test
}

[RestRequest("")]
public void RequestHandle2(APIEventArgs e, RestContext c)
{
    //the user accessed localhost:8080
}
Enter fullscreen mode Exit fullscreen mode

I realize that this is incredibly similar to ASP.NET, but whatever. The invocation of the class inheriting Rest will still be the same though.

Hopefully this improved Rest class will be finished in time for Impart v2.0.2 when I (eventually) release it at the end of March.

Additionally, I will either update the post I mentioned earlier, or create one about how to host a REST API when the update is released.

Discussion (0)