Skip to content
Simple RESTlike and Subscription API server in C#
C# TSQL
Branch: master
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Type Name Latest commit message Commit time
Failed to load latest commit information.
Butterfly.Web.EmbedIO.Test Changes Oct 15, 2019
Butterfly.Web.EmbedIO Changes Oct 28, 2019
Butterfly.Web.RedHttpServer.Test Changes Oct 15, 2019
Butterfly.Web.RedHttpServer Changes Oct 28, 2019
Butterfly.Web.Test Changes Oct 19, 2019
Butterfly.Web Changes Oct 28, 2019
docfx_project Changes Oct 28, 2019
docs Changes Oct 28, 2019
img
.gitattributes Changes Oct 15, 2019
.gitignore Changes Oct 15, 2019
Butterfly.Web.sln Changes Oct 15, 2019
CODE_OF_CONDUCT.md Changes Oct 15, 2019
LICENSE
README.md Changes Oct 16, 2019

README.md

Butterfly.Web Butterfly Logo

Simple RESTlike and Subscription API server in C#

Getting Started

Install from Nuget

Name Package Install
Butterfly.Web nuget nuget install Butterfly.Web
Butterfly.Web.EmbedIO nuget nuget install Butterfly.Web.EmbedIO
Butterfly.Web.RedHttpServer nuget nuget install Butterfly.Web.RedHttpServer

Install from Source Code

git clone https://github.com/firesharkstudios/butterfly-web

Overview

Butterfly.Web defines an IWebApi interface to define RESTlike APIs and defines an ISubscriptionApi to stream real-time updates to clients.

Butterfly.Web.EmbedIO implements the Butterfly.Web interfaces using the lightweight EmbedIO web server.

Butterfly.Web.RedHttpServer implements the Butterfly.Web interfaces using the Kestral based RedHttpServer.

Using IWebApi

An IWebApi instance allows defining a RESTlike API like this...

// Create an IWebApi instance using EmbedIO or RedHttpServer

webApi.OnPost("/api/todo/insert", async (req, res) => {
    var todo = await req.ParseAsJsonAsync<Dict>();
    // Do something to insert the todo
});

webApi.OnPost("/api/todo/delete", async (req, res) => {
    var id = await req.ParseAsJsonAsync<string>();
    // Do something to delete the todo
});

// Don't forget to compile
webApi.Compile();

Request Handling

There are many ways to receive data from a client...

// Using path params
webApi.OnGet("/api/todo/{id}", (req, res) => {
    // Opening /api/todo/123 would print id=123 below
    Console.WriteLine($"id={req.PathParams["id"]}");
});

// Using query params
webApi.OnGet("/api/todo", (req, res) => {
    // Opening /api/todo?id=123 would print id=123 below
    Console.WriteLine($"id={req.QueryParams["id"]}");
});

// Using post body that is JSON encoded
webApi.OnPost("/api/todo", async(req, res) => {
    // A javascript client posting JSON data with...
    //     $.ajax('/api/todo', {
    //         method: 'POST',
    //         data: JSON.stringify({ id: "123" }),
    //     });
    // would echod id=123 below
    var data = await req.ParseAsJsonAsync<Dictionary<string, string>>();
    Console.WriteLine($"id={data["id"]}");
});

// Using post body that is URL encoded
webApi.OnPost("/api/todo", async(req, res) => {
    // A javascript client posting JSON data with...
    //     var formData = new FormData();
    //     formData.append("id", "123");
    //     $.ajax('/api/todo', {
    //         method: 'POST',
    //         data: formData,
    //     });
    // would echod id=123 below
    var data = await req.ParseAsUrlEncodedAsync();
    Console.WriteLine($"id={data["id"]}");
});

Response Handling

There are many ways to send a response to a client...

// Respond with plain text
webApi.OnPost("/api/todo", async(req, res) => {
    await res.WriteAsTextAsync("OK");
});

// Respond with JSON
webApi.OnPost("/api/todo", async(req, res) => {
    await res.WriteAsJsonAsync(new {
        result = "OK"
    });
});

// Redirect the client
webApi.OnGet("/api/todo/{id}", (req, res) => {
    res.SendRedirect("/api/todo/not-found");
});

Using ISubscriptionApi

An ISubscriptionApi instance allows clients to receive real-time updates like this...

// Create an ISubscriptionApi instance using EmbedIO or RedHttpServer

subscriptionApi.OnSubscribe("echoes", async(vars, channel) => {
    int count = 0;
    return Butterfly.Util.RunEvery(() => {
        channel.Queue("Echo", $"Echo #{++count}");
    }, 2000);
});

A client subscribing to the echoes subscription above would receive messages every two seconds (first message would have type Echo and text Echo #1).

The subscription handler must return an IDisposable instance that is disposed when the client unsubscribes or disconnects.

Using EmbedIO

EmbedIO is a capable low footprint web server that can be used to implement both the IWebApi and ISubscriptionApi interfaces.

The EmbedIOContext class is a convenience class that creates IWebApi and ISubscriptionApi instances using an EmbedIO web server.

In the Package Manager Console...

Install-Package Butterfly.Web.EmbedIO

In your application...

var context = new Butterfly.Web.EmbedIO.EmbedIOContext("http://+:8000/");

// Declare your Web API and Subscription API like...
context.WebApi.OnPost("/api/todo/insert", async (req, res) => {
   // Do something
});
context.WebApi.OnPost("/api/todo/delete", async (req, res) => {
   // Do something
});
context.SubscriptionApi.OnSubscribe("todos", (vars, channel) => {
   // Do something
});

context.Start();

Using RedHttpServer

RedHttpServer is a Kestrel/ASP.NET Core based web server that can be used to implement both the IWebApi and ISubscriptionApi interfaces.

The RedHttpServerContext class is a convenience class that creates IWebApi and ISubscriptionApi instances using RedHttpServer.

In the Package Manager Console...

Install-Package Butterfly.RedHttpServer

In your application...

var context = new Butterfly.Web.RedHttpServer.RedHttpServerContext("http://+:8000/");

// Declare your Web API and Subscription API like...
context.WebApi.OnPost("/api/todo/insert", async (req, res) => {
   // Do something
});
context.WebApi.OnPost("/api/todo/delete", async (req, res) => {
   // Do something
});
context.SubscriptionApi.OnSubscribe("todos", (vars, channel) => {
   // Do something
});

context.Start();

Contributing

If you'd like to contribute, please fork the repository and use a feature branch. Pull requests are warmly welcome.

Licensing

The code is licensed under the Mozilla Public License 2.0.

You can’t perform that action at this time.