Experimental ClojureCLR port of Ring, built mainly for the purpose of providing an example of what a ClojureCLR project might look like, and — in the spirit of ClojureCLR — to have some fun!
brew install dotnet
(or any other way of installing .NET)dotnet tool install --global --version 1.12.0-alpha10 Clojure.Main
(ns app
(:require [ring-clr.adapter.httplistener :as server]))
(defn handler [request]
{:status 200
:headers {"content-type" "application/json"}
:body "{\"hello\":\"world\"}"})
(defn -main []
(server/run-httplistener handler))
Run the above from a REPL, or run the app.cljr
file provided with the repo:
CLOJURE_LOAD_PATH=src:demo Clojure.Main -m app
Or with the new CLI tool:
dotnet tool install --global --version 0.1.0-alpha4 Clojure.Cljr
cljr -A:demo -m app
Since Ring is essentially an abstraction on top of the Servlet API, and there is no Servlet API in the CLR, the ClojureCLR adapters wrapping the HTTP server implementation will need to be more comprehensive. Currently only the built-in HttpListener server has been provided an adapter, but adding one for e.g. Kestrel should be doable. Other differences should be minimal:
- Serving a "resource" (i.e. from classpath / jar) not applicable here
- Made
ring.util.codec
included in core, and not in a separate project - Nothing marked deprecated in Ring has been included in this port
- No time or effort spent on non-UTF8 encodings — it's 2023
Except for that, things should work pretty much the same, and much of existing middleware should work as-is.
The docs for Ring should be valid for almost everything found here. For the cases where a Java type is expected as input our output, the closest CLR equivalent type is used instead:
File
=>FileInfo
orDirectoryInfo
Date
=>DateTime
InputStream
=>Stream
ByteArrayOutputStream
=>MemoryStream
If you find anything not mentioned above, or not easily understood, please open an issue!
From the project root directory:
CLOJURE_LOAD_PATH=src:test Clojure.Main -m ring-clr.test
- Add implementation for all types of
StreamableResponseBody
- Calculate and set
content-length
header (no Jetty to do it for us) - Most of the stuff around serving static files
- File upload (multipart params) middleware
- Cookie session store middleware
- Datetime parsing of other formats than RFC 1123
- Provide ClojureCLR specific documentation
- Use .cljr extension for all files, ensure tooling understands it
- Publish to Nuget, maybe Clojars