Files
bux-lang/apps/boko-framework
dimgigov 94e6806dda fix(compiler): allow integer coercion in range bounds; use for loops in boko-framework
- sema: range bounds now accept compatible integer types (e.g. int..uint)
  instead of requiring exact type equality.
- hir_lower: derive loop variable type from the common range type.
- boko-framework: replace manual while loops with for loops in Query_Parse,
  Request_Parse, Path_Match and App_Run.
2026-06-17 12:08:36 +03:00
..

Boko Framework

Async web framework for Bux — inspired by FastAPI.

Boko is a lightweight, multi-threaded web framework that brings FastAPI-style routing to the Bux programming language. It handles HTTP parsing, path pattern matching, query parameter extraction, and response building so you can focus on your application logic.

This version (0.2.0) is rewritten with modern Bux: struct methods, generic StringMap<String> for headers/query/path params, for loops, algebraic enums, StringBuilder, and string interpolation.

Quick Start

cd apps/boko-framework
../../buxc build
./build/boko-framework

Open http://localhost:8080 — you'll see the demo landing page.

How It Works

Boko follows a single-dispatch-function pattern. You define one function — Boko_Router — and the framework calls it for every incoming request:

import Boko::{Request, Response, Response_Json, Response_Html, Response_NotFound,
              Path_Match,
              App, App_New, App_Run};

func Boko_Router(req: Request) -> Response {
    // Route: GET /
    if String_Eq(req.path, "/") {
        return Response_Html("<h1>Hello Boko!</h1>");
    }

    // Route: GET /api/health
    if String_Eq(req.path, "/api/health") {
        return Response_Json("{\"status\":\"ok\"}");
    }

    // Route: GET /users/{id} — path parameter
    if Path_Match("/users/{id}", req.path, &req) {
        let id: String = req.GetPathParam("id");
        // Build JSON response with id
        return Response_Json(...);
    }

    // Route: GET /search?q=... — query parameter
    if String_Eq(req.path, "/search") {
        let q: String = req.GetQuery("q");
        return Response_Json(...);
    }

    return Response_NotFound();
}

func Main() -> int {
    let app: App = App_New(8080, 4);  // port, threads
    App_Run(&app);
    return 0;
}

API Reference

Request

Field Type Description
method HttpVerb GET, POST, PUT, DELETE, PATCH, HEAD, OPTIONS
path String Request path (without query string)
body String Request body (for POST/PUT)
headers StringMap<String> Parsed request headers
query StringMap<String> Parsed query parameters
pathParams StringMap<String> Extracted path parameters
Method Returns Description
req.GetHeader(name) String Get header value by name
req.GetQuery(name) String Get query parameter by name
req.HasQuery(name) bool Check if query parameter exists
req.GetPathParam(name) String Get extracted path parameter

Response

Constructor Content-Type Status
Response_Html(html) text/html 200
Response_Json(json) application/json 200
Response_Text(text) text/plain 200
Response_Redirect(url) 302
Response_NotFound() application/json 404
Response_Error(code, msg) application/json custom
Response_NoContent() 204

Path Matching

Path_Match(pattern, actualPath, req) matches a pattern with {param} placeholders:

// Pattern:    /users/{id}/posts/{postId}
// Actual:     /users/42/posts/7
// Extracts:   id=42, postId=7

if Path_Match("/users/{id}/posts/{postId}", req.path, &req) {
    let userId: String = req.GetPathParam("id");      // "42"
    let postId: String = req.GetPathParam("postId");  // "7"
}

The function returns true if the pattern matches and populates req.pathParams.

App

let app: App = App_New(8080, 4);  // port 8080, 4 worker threads
App_Run(&app);                     // blocks, handles requests

Architecture

Incoming connection
    │
    ▼
Net_Accept()  ───  worker thread (1 of N)
    │
    ▼
Net_Recv()  →  raw HTTP bytes
    │
    ▼
Request_Parse()  →  method, path, query, headers, body
    │
    ▼
Boko_Router(req)  ←── YOUR CODE
    │
    ▼
Response_Build()  →  HTTP/1.1 response string
    │
    ▼
Net_Send()  →  bytes to client
    │
    ▼
Net_Close()

Endpoints in Demo App

Method Path Description
GET / Landing page (HTML)
GET /api/health Health check (JSON)
GET /api/info Framework info (JSON)
GET /hello?name=X Query param demo
GET /users/{id} Path param demo
GET /posts/{id}/comments/{cid} Multi path param demo
GET /redirect 302 redirect to /
POST /api/echo Echo request body

Project Structure

apps/boko-framework/
├── bux.toml              # Package manifest
├── README.md             # This file
└── src/
    ├── Boko.bux          # Framework core (~500 lines)
    └── Main.bux          # Example app (~150 lines)

Design Philosophy

Boko is intentionally simple. Instead of complex DSLs or code generation, it gives you:

  • One function to writeBoko_Router(req) -> Response
  • Direct control — you write plain if/else or match for routing
  • No magic — path params, query params, headers are explicit function calls
  • Fast — multi-threaded accept loop, zero allocations where possible

This is the same philosophy as Go's net/http — simple, explicit, composable.

License

Part of the Bux project. See root LICENSE.