README Expand

Suri - Web Framework for OCaml

Suri is an experimental, supervised web framework built on Std and Actors for building HTTP servers, WebSocket servers, and real-time web applications.

Suri is not production-ready yet. The core framework shape is usable for experiments, examples, and hardening work, but protocol correctness, cryptography, operational limits, and production guidance are still under active development.

Quick Start

open Std
open Suri

let handler _conn req =
  let open WebServer in
  match Request.path req with
  | "/" -> Response.ok ~body:"Hello from Suri!" ()
  | _ -> Response.not_found ~body:"Not Found" ()

let main () =
  let config = WebServer.Config.make () in
  match WebServer.start_link ~port:8080 ~config ~handler () with
  | Ok supervisor ->
      Log.info "Server running on http://0.0.0.0:8080";
      receive_any ()  (* Keep alive *)
  | Error `Bind_error ->
      Log.error "Failed to bind to port";
      Error (Failure "bind error")

let () = run_with @@ main

Components

SocketPool

Supervised TCP connection pool with concurrent acceptors and protocol switching. Uses Std.Supervisor.Dynamic to manage acceptor processes with automatic restart on failure.

WebServer

HTTP/1.1 server with request parsing, response handling, and keep-alive connection management. Built on SocketPool with full supervision support.

Middleware

Composable middleware framework with routing support for building HTTP request pipelines.

Channel

WebSocket handler abstraction for real-time bidirectional communication. Provides Frame types and Handler interface for building WebSocket servers.

LiveView (Experimental)

Server-rendered components with live DOM updates over WebSocket. LiveView exists, but its token handling, lifecycle cleanup, reconnect behavior, and event authorization are still being hardened.

Architecture

Suri follows a supervised, layered architecture using OTP-style process supervision:

Application Supervisor
    ↓
WebServer (Supervisor.Dynamic)
    ↓
Acceptor Pool (100+ concurrent processes)
    ↓
Connection Handlers (1 per connection)
    ↓
Your Application Logic

Supervision Benefits

  • Fault Tolerance: If an acceptor crashes, it's automatically restarted
  • Resource Management: Bounded number of acceptors with configurable limits
  • Lifecycle Hooks: Handler callbacks for connection close, errors, and shutdown
  • Monitoring: Track acceptor health and restart patterns

Components

  1. SocketPool - Supervised TCP connection management
  2. WebServer - HTTP protocol handling (HTTP/1.1 foundation; HTTP/2 prototype)
  3. Middleware - Request processing pipeline
  4. Channel - WebSocket communication layer
  5. LiveView - Experimental real-time UI components

This design allows you to use just the components you need, from low-level socket handling to high-level web frameworks.

Features

Current

  • HTTP/1.1 server foundation with keep-alive support
  • OTP-style supervision with Std.Supervisor
  • Concurrent connection acceptance with configurable acceptor count
  • WebSocket upgrade and Channel primitives
  • Composable middleware framework
  • Request routing
  • Component rendering with escaped text and attributes

Experimental / Hardening In Progress

  • LiveView server-side rendering and WebSocket updates
  • HTTP/2 protocol handling
  • Session and CSRF middleware
  • Static file serving
  • Request body parsing and upload handling
  • Operational limits, timeouts, graceful shutdown, and production presets

Examples

See packages/suri/examples for examples including:

  • Simple HTTP server
  • JSON API server
  • WebSocket echo server
  • Middleware and routing
  • LiveView components

Performance

Suri is designed for high concurrency:

  • Default 100 concurrent acceptors
  • Each connection handled in its own process
  • Non-blocking I/O
  • Automatic acceptor restart on crash
  • Configurable buffer sizes and limits
Installs
Downloads over the last 30 days, stacked by release.
Total installs
50
Downloads over the last 30 days
v0.0.431
v0.0.420
v0.0.410
v0.0.4016
v0.0.390
Package status
Submission, indexing, and post-publish processing milestones for this release.
Submitted
May 15, 08:09 PM
Indexed
May 15, 08:09 PM
Searchable
May 15, 08:09 PM
Docs ready
May 15, 08:31 PM
Completed
Pending
Dependencies
Dependencies declared for this release.
Show 3 dependencies Expand
Dependents
Packages that currently depend on suri.
Show 2 dependents Expand
Recent activity
Latest publication, indexing, and post-publish pipeline events recorded for this package.
Open full activity
Show 12 recent events Expand
  • Blocked
    suri 0.0.43 attempt 3 · artifact 78a081ccb1d7
    Details
    When
    May 15, 2026, 08:44:54 PM
    Event
    Blocked
    Package
    suri
    Version
    0.0.43
    Facts
    attempt 3 artifact 78a081ccb1d7
    Payload
    {
      "artifact_sha256": "78a081ccb1d7b80b5398ca395c93909dc2fa726c825e8cbbf5f78bacb0ac3c3a",
      "status": "blocked",
      "attempt_count": 3,
      "error": "error: Unknown argument: suri"
    }
  • Build failed
    suri 0.0.43 build · exit 1 · artifact 78a081ccb1d7
    Details
    When
    May 15, 2026, 08:44:52 PM
    Event
    Build failed
    Package
    suri
    Version
    0.0.43
    Summary
    error: Unknown argument: suri
    Facts
    build exit 1 artifact 78a081ccb1d7
    Artifacts
    Result key
    pipelines/builds/suri/0.0.43/78a081ccb1d7b80b5398ca395c93909dc2fa726c825e8cbbf5f78bacb0ac3c3a/result.json
    Logs key
    pipelines/builds/suri/0.0.43/78a081ccb1d7b80b5398ca395c93909dc2fa726c825e8cbbf5f78bacb0ac3c3a/build.log
    Payload
    {
      "artifact_sha256": "78a081ccb1d7b80b5398ca395c93909dc2fa726c825e8cbbf5f78bacb0ac3c3a",
      "run_kind": "build",
      "result_key": "pipelines/builds/suri/0.0.43/78a081ccb1d7b80b5398ca395c93909dc2fa726c825e8cbbf5f78bacb0ac3c3a/result.json",
      "logs_key": "pipelines/builds/suri/0.0.43/78a081ccb1d7b80b5398ca395c93909dc2fa726c825e8cbbf5f78bacb0ac3c3a/build.log",
      "environment_probe": {
        "success": true,
        "exit_code": 0,
        "stdout": "glibc=glibc 2.39\nriot=riot 0.0.43 (build 2a3a2071a5f0)\nPRETTY_NAME=\"Ubuntu 24.04.4 LTS\"\nNAME=\"Ubuntu\"\nVERSION_ID=\"24.04\"\nVERSION=\"24.04.4 LTS (Noble Numbat)\"\nVERSION_CODENAME=noble\nID=ubuntu\nID_LIKE=debian\nHOME_URL=\"https://www.ubuntu.com/\"\nSUPPORT_URL=\"https://help.ubuntu.com/\"\nBUG_REPORT_URL=\"https://bugs.launchpad.net/ubuntu/\"\nPRIVACY_POLICY_URL=\"https://www.ubuntu.com/legal/terms-and-policies/privacy-policy\"\nUBUNTU_CODENAME=noble\nLOGO=ubuntu-logo",
        "stderr": "",
        "duration_ms": 43,
        "command": [
          "sh",
          "-lc",
          "printf 'glibc=%s\\n' \"$(getconf GNU_LIBC_VERSION 2>/dev/null || echo unknown)\" && printf 'riot=%s\\n' \"$(/root/.riot/bin/riot version 2>/dev/null || echo unavailable)\" && cat /etc/os-release"
        ],
        "json_events": [],
        "non_json_stdout_lines": [
          "glibc=glibc 2.39",
          "riot=riot 0.0.43 (build 2a3a2071a5f0)",
          "PRETTY_NAME=\"Ubuntu 24.04.4 LTS\"",
          "NAME=\"Ubuntu\"",
          "VERSION_ID=\"24.04\"",
          "VERSION=\"24.04.4 LTS (Noble Numbat)\"",
          "VERSION_CODENAME=noble",
          "ID=ubuntu",
          "ID_LIKE=debian",
          "HOME_URL=\"https://www.ubuntu.com/\"",
          "SUPPORT_URL=\"https://help.ubuntu.com/\"",
          "BUG_REPORT_URL=\"https://bugs.launchpad.net/ubuntu/\"",
          "PRIVACY_POLICY_URL=\"https://www.ubuntu.com/legal/terms-and-policies/privacy-policy\"",
          "UBUNTU_CODENAME=noble",
          "LOGO=ubuntu-logo"
        ]
      },
      "exit_code": 1,
      "json_event_count": 0,
      "non_json_stdout_count": 1,
      "failure_summary": "error: Unknown argument: suri",
      "stdout_excerpt": "error: Unknown argument: suri"
    }
  • Processing
    suri 0.0.43 attempt 3 · artifact 78a081ccb1d7
    Details
    When
    May 15, 2026, 08:44:47 PM
    Event
    Processing
    Package
    suri
    Version
    0.0.43
    Facts
    attempt 3 artifact 78a081ccb1d7
    Payload
    {
      "artifact_sha256": "78a081ccb1d7b80b5398ca395c93909dc2fa726c825e8cbbf5f78bacb0ac3c3a",
      "status": "processing",
      "attempt_count": 3
    }
  • Requeued
    suri 0.0.43 attempt 2 · artifact 78a081ccb1d7
    Details
    When
    May 15, 2026, 08:39:16 PM
    Event
    Requeued
    Package
    suri
    Version
    0.0.43
    Facts
    attempt 2 artifact 78a081ccb1d7
    Payload
    {
      "artifact_sha256": "78a081ccb1d7b80b5398ca395c93909dc2fa726c825e8cbbf5f78bacb0ac3c3a",
      "status": "pending",
      "attempt_count": 2,
      "next_attempt_at": "2026-05-15T20:44:16.601Z",
      "error": "error: Unknown argument: suri"
    }
  • Build failed
    suri 0.0.43 build · exit 1 · artifact 78a081ccb1d7
    Details
    When
    May 15, 2026, 08:39:15 PM
    Event
    Build failed
    Package
    suri
    Version
    0.0.43
    Summary
    error: Unknown argument: suri
    Facts
    build exit 1 artifact 78a081ccb1d7
    Artifacts
    Result key
    pipelines/builds/suri/0.0.43/78a081ccb1d7b80b5398ca395c93909dc2fa726c825e8cbbf5f78bacb0ac3c3a/result.json
    Logs key
    pipelines/builds/suri/0.0.43/78a081ccb1d7b80b5398ca395c93909dc2fa726c825e8cbbf5f78bacb0ac3c3a/build.log
    Payload
    {
      "artifact_sha256": "78a081ccb1d7b80b5398ca395c93909dc2fa726c825e8cbbf5f78bacb0ac3c3a",
      "run_kind": "build",
      "result_key": "pipelines/builds/suri/0.0.43/78a081ccb1d7b80b5398ca395c93909dc2fa726c825e8cbbf5f78bacb0ac3c3a/result.json",
      "logs_key": "pipelines/builds/suri/0.0.43/78a081ccb1d7b80b5398ca395c93909dc2fa726c825e8cbbf5f78bacb0ac3c3a/build.log",
      "environment_probe": {
        "success": true,
        "exit_code": 0,
        "stdout": "glibc=glibc 2.39\nriot=riot 0.0.43 (build 2a3a2071a5f0)\nPRETTY_NAME=\"Ubuntu 24.04.4 LTS\"\nNAME=\"Ubuntu\"\nVERSION_ID=\"24.04\"\nVERSION=\"24.04.4 LTS (Noble Numbat)\"\nVERSION_CODENAME=noble\nID=ubuntu\nID_LIKE=debian\nHOME_URL=\"https://www.ubuntu.com/\"\nSUPPORT_URL=\"https://help.ubuntu.com/\"\nBUG_REPORT_URL=\"https://bugs.launchpad.net/ubuntu/\"\nPRIVACY_POLICY_URL=\"https://www.ubuntu.com/legal/terms-and-policies/privacy-policy\"\nUBUNTU_CODENAME=noble\nLOGO=ubuntu-logo",
        "stderr": "",
        "duration_ms": 130,
        "command": [
          "sh",
          "-lc",
          "printf 'glibc=%s\\n' \"$(getconf GNU_LIBC_VERSION 2>/dev/null || echo unknown)\" && printf 'riot=%s\\n' \"$(/root/.riot/bin/riot version 2>/dev/null || echo unavailable)\" && cat /etc/os-release"
        ],
        "json_events": [],
        "non_json_stdout_lines": [
          "glibc=glibc 2.39",
          "riot=riot 0.0.43 (build 2a3a2071a5f0)",
          "PRETTY_NAME=\"Ubuntu 24.04.4 LTS\"",
          "NAME=\"Ubuntu\"",
          "VERSION_ID=\"24.04\"",
          "VERSION=\"24.04.4 LTS (Noble Numbat)\"",
          "VERSION_CODENAME=noble",
          "ID=ubuntu",
          "ID_LIKE=debian",
          "HOME_URL=\"https://www.ubuntu.com/\"",
          "SUPPORT_URL=\"https://help.ubuntu.com/\"",
          "BUG_REPORT_URL=\"https://bugs.launchpad.net/ubuntu/\"",
          "PRIVACY_POLICY_URL=\"https://www.ubuntu.com/legal/terms-and-policies/privacy-policy\"",
          "UBUNTU_CODENAME=noble",
          "LOGO=ubuntu-logo"
        ]
      },
      "exit_code": 1,
      "json_event_count": 0,
      "non_json_stdout_count": 1,
      "failure_summary": "error: Unknown argument: suri",
      "stdout_excerpt": "error: Unknown argument: suri"
    }
  • Processing
    suri 0.0.43 attempt 2 · artifact 78a081ccb1d7
    Details
    When
    May 15, 2026, 08:39:07 PM
    Event
    Processing
    Package
    suri
    Version
    0.0.43
    Facts
    attempt 2 artifact 78a081ccb1d7
    Payload
    {
      "artifact_sha256": "78a081ccb1d7b80b5398ca395c93909dc2fa726c825e8cbbf5f78bacb0ac3c3a",
      "status": "processing",
      "attempt_count": 2
    }
  • Requeued
    suri 0.0.43 attempt 1 · artifact 78a081ccb1d7
    Details
    When
    May 15, 2026, 08:32:28 PM
    Event
    Requeued
    Package
    suri
    Version
    0.0.43
    Facts
    attempt 1 artifact 78a081ccb1d7
    Payload
    {
      "artifact_sha256": "78a081ccb1d7b80b5398ca395c93909dc2fa726c825e8cbbf5f78bacb0ac3c3a",
      "status": "pending",
      "attempt_count": 1,
      "next_attempt_at": "2026-05-15T20:37:28.751Z",
      "error": "error: Unknown argument: suri"
    }
  • Docs ready
    suri 0.0.43 docs · 2 json · doc.package_generation_completed · artifact 78a081ccb1d7
    Details
    When
    May 15, 2026, 08:31:27 PM
    Event
    Docs ready
    Package
    suri
    Version
    0.0.43
    Facts
    docs 2 json doc.package_generation_completed artifact 78a081ccb1d7
    Artifacts
    Result key
    pipelines/docs/suri/0.0.43/78a081ccb1d7b80b5398ca395c93909dc2fa726c825e8cbbf5f78bacb0ac3c3a/result.json
    Logs key
    pipelines/docs/suri/0.0.43/78a081ccb1d7b80b5398ca395c93909dc2fa726c825e8cbbf5f78bacb0ac3c3a/command.log
    Payload
    {
      "artifact_sha256": "78a081ccb1d7b80b5398ca395c93909dc2fa726c825e8cbbf5f78bacb0ac3c3a",
      "run_kind": "docs",
      "output_prefix": "docs/suri/0.0.43/",
      "public_docs_url": "https://docs.pkgs.ml/p/suri/0.0.43/",
      "result_key": "pipelines/docs/suri/0.0.43/78a081ccb1d7b80b5398ca395c93909dc2fa726c825e8cbbf5f78bacb0ac3c3a/result.json",
      "logs_key": "pipelines/docs/suri/0.0.43/78a081ccb1d7b80b5398ca395c93909dc2fa726c825e8cbbf5f78bacb0ac3c3a/command.log",
      "json_event_count": 2,
      "non_json_stdout_count": 0,
      "last_json_event_type": "doc.package_generation_completed"
    }
  • Build failed
    suri 0.0.43 build · exit 1 · artifact 78a081ccb1d7
    Details
    When
    May 15, 2026, 08:31:26 PM
    Event
    Build failed
    Package
    suri
    Version
    0.0.43
    Summary
    error: Unknown argument: suri
    Facts
    build exit 1 artifact 78a081ccb1d7
    Artifacts
    Result key
    pipelines/builds/suri/0.0.43/78a081ccb1d7b80b5398ca395c93909dc2fa726c825e8cbbf5f78bacb0ac3c3a/result.json
    Logs key
    pipelines/builds/suri/0.0.43/78a081ccb1d7b80b5398ca395c93909dc2fa726c825e8cbbf5f78bacb0ac3c3a/build.log
    Payload
    {
      "artifact_sha256": "78a081ccb1d7b80b5398ca395c93909dc2fa726c825e8cbbf5f78bacb0ac3c3a",
      "run_kind": "build",
      "result_key": "pipelines/builds/suri/0.0.43/78a081ccb1d7b80b5398ca395c93909dc2fa726c825e8cbbf5f78bacb0ac3c3a/result.json",
      "logs_key": "pipelines/builds/suri/0.0.43/78a081ccb1d7b80b5398ca395c93909dc2fa726c825e8cbbf5f78bacb0ac3c3a/build.log",
      "environment_probe": {
        "success": true,
        "exit_code": 0,
        "stdout": "glibc=glibc 2.39\nriot=riot 0.0.43 (build 2a3a2071a5f0)\nPRETTY_NAME=\"Ubuntu 24.04.4 LTS\"\nNAME=\"Ubuntu\"\nVERSION_ID=\"24.04\"\nVERSION=\"24.04.4 LTS (Noble Numbat)\"\nVERSION_CODENAME=noble\nID=ubuntu\nID_LIKE=debian\nHOME_URL=\"https://www.ubuntu.com/\"\nSUPPORT_URL=\"https://help.ubuntu.com/\"\nBUG_REPORT_URL=\"https://bugs.launchpad.net/ubuntu/\"\nPRIVACY_POLICY_URL=\"https://www.ubuntu.com/legal/terms-and-policies/privacy-policy\"\nUBUNTU_CODENAME=noble\nLOGO=ubuntu-logo",
        "stderr": "",
        "duration_ms": 52,
        "command": [
          "sh",
          "-lc",
          "printf 'glibc=%s\\n' \"$(getconf GNU_LIBC_VERSION 2>/dev/null || echo unknown)\" && printf 'riot=%s\\n' \"$(/root/.riot/bin/riot version 2>/dev/null || echo unavailable)\" && cat /etc/os-release"
        ],
        "json_events": [],
        "non_json_stdout_lines": [
          "glibc=glibc 2.39",
          "riot=riot 0.0.43 (build 2a3a2071a5f0)",
          "PRETTY_NAME=\"Ubuntu 24.04.4 LTS\"",
          "NAME=\"Ubuntu\"",
          "VERSION_ID=\"24.04\"",
          "VERSION=\"24.04.4 LTS (Noble Numbat)\"",
          "VERSION_CODENAME=noble",
          "ID=ubuntu",
          "ID_LIKE=debian",
          "HOME_URL=\"https://www.ubuntu.com/\"",
          "SUPPORT_URL=\"https://help.ubuntu.com/\"",
          "BUG_REPORT_URL=\"https://bugs.launchpad.net/ubuntu/\"",
          "PRIVACY_POLICY_URL=\"https://www.ubuntu.com/legal/terms-and-policies/privacy-policy\"",
          "UBUNTU_CODENAME=noble",
          "LOGO=ubuntu-logo"
        ]
      },
      "exit_code": 1,
      "json_event_count": 0,
      "non_json_stdout_count": 1,
      "failure_summary": "error: Unknown argument: suri",
      "stdout_excerpt": "error: Unknown argument: suri"
    }
  • Processing
    suri 0.0.43 attempt 1 · artifact 78a081ccb1d7
    Details
    When
    May 15, 2026, 08:31:03 PM
    Event
    Processing
    Package
    suri
    Version
    0.0.43
    Facts
    attempt 1 artifact 78a081ccb1d7
    Payload
    {
      "artifact_sha256": "78a081ccb1d7b80b5398ca395c93909dc2fa726c825e8cbbf5f78bacb0ac3c3a",
      "status": "processing",
      "attempt_count": 1
    }
  • Queued
    suri 0.0.43 artifact 78a081ccb1d7
    Details
    When
    May 15, 2026, 08:10:03 PM
    Event
    Queued
    Package
    suri
    Version
    0.0.43
    Facts
    artifact 78a081ccb1d7
    Payload
    {
      "artifact_sha256": "78a081ccb1d7b80b5398ca395c93909dc2fa726c825e8cbbf5f78bacb0ac3c3a",
      "status": "pending"
    }
  • Indexed
    suri 0.0.43 latest 0.0.43 · artifact 78a081ccb1d7
    Details
    When
    May 15, 2026, 08:09:57 PM
    Event
    Indexed
    Package
    suri
    Version
    0.0.43
    Facts
    latest 0.0.43 artifact 78a081ccb1d7
    Payload
    {
      "artifact_sha256": "78a081ccb1d7b80b5398ca395c93909dc2fa726c825e8cbbf5f78bacb0ac3c3a",
      "latest": "0.0.43",
      "package_index_key": "index/v1/su/ri/suri.json",
      "package_index_url": "https://cdn.pkgs.ml/index/v1/su/ri/suri.json",
      "changed": true
    }