Kayak

Overview

Kayak is a C# HTTP server and request-handling framework. The server component is an intuitive, unobtrusive, no-gimmicks implementation of HTTP, and the framework simply maps HTTP transactions to C# method invocations with minimal syntax and configuration.

Why?

Because C# is awesome but until now had no good web programming enviroments. The old ASP.NET/System.Web classes that tie into IIS via ISAPI (and the hacks used to make it work with Mono and Apache) are awkward to use and difficult to set up, and frameworks built atop this (Monorail, ASP.NET MVC, &c) suffer from certain unnecessary complexities because of it. These frameworks do too much, make questionable assumptions, and are complicated and ugly to customize. For more ranting and raving, see the respective overviews for the server and framework.

Kayak

Kayak is a simple web server. It listens for connections, creates an in-memory representation of requests, and allows you to easily generate responses. It can be used in any C# program. Your code loads Kayak into its process space—not the other way around!

using Kayak; ... public static void Main(string[] args) { var server = new KayakServer(); server.Start(); Console.WriteLine("Kayak is running! Press enter to exit."); Console.ReadLine(); server.Stop(); }

Serve files

Kayak comes with some simple extensions to serve files.

server.MapFile("/favicon.ico", "local/path/to/favicon.ico"); server.MapDirectory("/myfiles", "local/path/to/my/files"); server.MapDirectory("/", "local/path/to/my/webroot", "index.html");

The last method call causes the server to look for index.html if a directory is specified but not a file, much like Apache’s DirectoryIndex directive. So if the server gets a request for “/”, it will serve “local/path/to/my/webroot/index.html”

Kayak Framework

A few more lines and you’re using the Kayak Framework. Import the framework namespace and tell your server to use the framework. This will search your assembly for methods marked with the [Path()] attribute (which you will create next).

using Kayak.Framework; ... server.UseFramework(); ...

Then declare a class to handle requests:

public class MyService : KayakService { [Path("/")] public void Root() { Response.Write("Hello, world."); } [Path("/say/{word}")] public void Say(string word) { Response.Write("Ok. " + word + "."); } }

Request parameters (which can be part of the path, as illustrated above) corresponding to method parameters are passed in as arguments when your method is invoked. Extending from KayakService is optional. It provides convenient access to the current HTTP context via its Request and Response properties.

Make an API

The Kayak Framework is wonderfully suited to making web APIs. API methods can return and accept strongly-typed values converted to and from JSON objects. Arguments are deserialized from the request body, and return values are serialized to the response body.

public class PostAPI { [Path("/widgets")] public Widget[] GetWidgets() { return Widget.GetAll(); } [Verb("POST")] [Path("/widgets")] public void CreateWidget([RequestBody] Widget w) { w.Created = DateTime.UtcNow; w.Create(); } } public class Widget { public string Author; public string Text; public string Created; // (methods would be here...) }

(Notice that in this case we are not extending from KayakService because we are not accessing the Request or Response properties.)

Kayak serializes the return value of GetWidgets() as a JSON array, and when CreateWidget() is invoked, Kayak constructs a Widget instance from the POSTed JSON in the request body and passes it in as an argument to the invocation.

Other Items of Note

The server sports a performance-minded asynchronous architecture which handles multiple connections per thread, and when used properly, allows you to write extremely efficient applications. Currently, IO is done using the BCL NetworkStream class' BeginRead/BeginWrite. Because the performance of Mono's implementation of this is less than ideal, Kayak will likely use libevent or similar for IO in a future version.

The framework contains a modified version of Leonardo Boshell’s excellent LitJSON library.

Next

Check out the documentation; head on over to the Google Code project page.