Skip to content

sjqtentacles/sml-web

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

2 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

sml-web

CI

The umbrella of the sjqtentacles pure-SML web stack: one request -> response application assembled from a router and a middleware stack, with content negotiation helpers. It adds no protocol logic of its own — it wires the tier-2 libraries into a single pure handler you can test end-to-end over hand-built requests, with no sockets, threads, or OS I/O. Dual-compiler: MLton + Poly/ML.

What it ties together

  • sml-router — method + path routing with params and wildcards.
  • sml-middleware — composable handler -> handler wrappers (logging, error catching, headers, static files).
  • sml-negotiateAccept* content negotiation.
  • sml-html, sml-forms, sml-session — rendering, typed body decoding, sessions, all available to handlers.
  • sml-http — the request/response model underneath everything.

API

type app

val make : { middleware : Middleware.middleware list   (* outermost first *)
           , routes : Router.route list
           , notFound : Http.request -> Http.response } -> app

val run        : app -> Http.request -> Http.response
val runString  : app -> string -> Http.response option   (* parse + run *)

val negotiateMedia    : Http.request -> string list -> string option
val negotiateLanguage : Http.request -> string list -> string option
val negotiateEncoding : Http.request -> string list -> string option

Example

val app =
  Web.make
    { middleware =
        [ Middleware.logTo log fmt
        , Middleware.catchErrors (fn _ => Http.text 500 "Internal Error")
        , Middleware.addHeader "X-Powered-By" "sml-web" ]
    , routes =
        [ Router.get "/" home
        , Router.get "/greet/:name" greet ]
    , notFound = fn _ => Http.text 404 "Not Found" }

val SOME res = Web.runString app "GET /greet/alice HTTP/1.1\r\n\r\n"

Run the bundled end-to-end example (routing + middleware + HTML rendering over hand-built requests):

make example

Build & test

make test        # MLton
make test-poly   # Poly/ML
make all-tests   # both

16 deterministic checks, identical under MLton and Poly/ML.

Note: as the umbrella vendors several libraries that themselves share lower deps (sml-http, sml-uri, sml-parsec, ...), the Poly/ML tools/polybuild wrapper deduplicates source files by canonical path — each opaquely-ascribed module must be elaborated exactly once across the diamond.

Installation

package github.com/sjqtentacles/sml-web
require {
  github.com/sjqtentacles/sml-router
  github.com/sjqtentacles/sml-middleware
  github.com/sjqtentacles/sml-session
  github.com/sjqtentacles/sml-negotiate
  github.com/sjqtentacles/sml-html
  github.com/sjqtentacles/sml-forms
  github.com/sjqtentacles/sml-http
}

Dependencies are also vendored under lib/github.com/sjqtentacles/ and committed, so make needs no network.

Layout

lib/github.com/sjqtentacles/sml-web/
  web.sig  web.sml          app type + run + negotiation helpers
  sources.mlb  sml-web.mlb
examples/app.sml            end-to-end example app
test/                       Harness suite (16 checks)

The wider stack

This repo sits at the top of a layered set of small, pure, dual-compiler sml-* libraries (foundations → protocol → web layer → umbrella). Every repo is Basis-only, deterministic, and built test-first with byte-identical output under MLton and Poly/ML. Browse the whole project by the sjqtentacles-web topic.

Tier 0 — foundations (no sml-* deps)

Repo What it does
sml-buffer Growable byte/char buffer + rope-style concat
sml-codec Base64/Base16, SHA-1, SHA-256, CRC-32
sml-random Splittable deterministic PRNG (SplitMix64)
sml-log Leveled logging with a pluggable sink
sml-config Typed config from a key/value source

Tier 1 — protocol layer

Repo What it does
sml-crypto HMAC-SHA256, constant-time compare, signed tokens
sml-uri RFC 3986 URIs + form-urlencoded
sml-http RFC 9110/9112 message model + framing
sml-mime Media types + multipart/form-data
sml-deflate DEFLATE inflate + zlib/gzip
sml-ws RFC 6455 WebSocket handshake + frames

Tier 2 — web layer

Repo What it does
sml-cookie RFC 6265 cookies + signed cookies
sml-html HTML AST with safe-by-default escaping
sml-negotiate Accept* content negotiation
sml-router Path patterns + method dispatch
sml-forms Typed body decoding (validation applicative)
sml-session In-memory + signed-cookie sessions
sml-middleware Composable handler -> handler combinators

Tier 3 — umbrella & edge

Repo What it does
sml-web (this repo) Wires the above into one request -> response app
sml-serve Documented MLton-only socket adapter (the one impure edge)

The impure edge, sml-serve, is an MLton-only socket adapter that drives an sml-web app against a real TCP listener — kept out of this portable, deterministic core and shipped as a design document only.

License

MIT

About

Umbrella of the pure-SML web stack: one request->response app wiring router + middleware + sessions + negotiation. Pure, deterministic, dual-compiler.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors