Backburner Month 21: Cube Cotillion
This is an entry from a list of projects I hope to some day finish. Return to the backburnered projects index.
What is it? A “web framework”, but over SSH instead of HTTP.
What are web frameworks about, on a basic level? You're taking a protocol meant originally for serving simple documents in a hierarchical file system, and instead of serving those documents you're doing various computations and responding with dynamic data. Your web framework needn't interpret a GET /foo/bar
as actually looking up a file bar
in a directory foo
: you could have code attached that does whatever you want!
Cube Cotillion follows the same basic idea except with a different protocol: SSH. Usually, when you establish an SSH connection, you get dropped to a shell and the stuff you type gets interpreted as command-like invocations. Cube Cotillion implements an SSH server, but instead of passing strings to a shell, it instead lets you write arbitrary computations keyed on the commands you've written. If someone writes ssh my-cc-server foo bar
, then instead of trying to run the command foo
with the argument bar
, you can do, well, whatever you want!
Cube Cotillion is implemented as a Haskell library that does pattern-matching over the command passed in over SSH and can invoke callbacks as necessary. Here's a simple example: this server understands the command greet
, with or without a parameter, and will respond with a greeting in kind, using the bs
command to respond with a ByteString
:
main :: IO ()
main = do
key <- loadKey "server-keys"
cubeCotillion 8080 key $ do
cmd "greet" $ do
bs "Hello, world!\n"
cmd "greet :name" $ do
name <- param "name"
bs (mconcat ["Hello, ", name, "!\n"])
Like a web framework, we can now do whatever we want in response to these commands: there's no underlying shell we're passing commands to, and greet
isn't dispatching to another executable, it's just a single process figuring out what to do with the strings and responding in kind. We could build applications on top of this that use structured data (e.g. responding with JSON blobs instead of simple lines) or keep various pieces of internal state. Why not?
Why write it? This is far more on the experimental side: I have no idea if this would be useful for anything at all!
The thing that I like about using SSH as a transport mechanism is that it necessarily has a notion of secure client identity. For certain applications, having a built-in mechanism for verifying client identity would be wonderful, since that's something that need to be built on top of HTTP applications again and again.
That said, I have no idea whether applications built on top of this system would be useful in practice or not. That was sort of the point: I wanted to experiment with using it as a tool for building personal server control, but would it be useful for anything else? Who knows!
I also never got around to designing the right API for doing anything with the client identity, or the ability to do interactive sessions at all. There's a whole design space there that might be fun to explore.
Why the name? I wrote this in Haskell, and there are multiple web frameworks in Haskell named after Star Trek characters, including Spock and Scotty. Given that this was an analogous but wrong project, I decided to choose a name from [Neil Cicierega's guide to the alien races in the Star Trek universe.