bbwebservice

Crates.iobbwebservice
lib.rsbbwebservice
version1.0.5
created_at2025-11-08 15:11:21.156469+00
updated_at2025-11-11 21:03:39.741437+00
descriptionRust minimal dependencies port of the bbwebservice microframework
homepage
repository
max_upload_size
id1922974
size160,941
(LukasWalker1)

documentation

README

bbwebservice

Rust-native port of the original Python bbwebservice, built on the Rust standard library with rustls providing native TLS support. This guide shows a minimal app, core concepts, and how to exercise the API.

use bbwebservice::{
    register, start_blocking, MIME_TYPE, STORE_VARS, response, set_logging, LOGGING_OPTIONS,
};

fn main() {
    // Optional: enable request logging
    set_logging(LOGGING_OPTIONS::REQUEST, true, None);

    // Minimal GET handler
    register("::/hello", MIME_TYPE::TEXT, |ctx| {
        let who = ctx.query_string.get("name").cloned().unwrap_or_else(|| "World".into());
        format!("Hello, {who}!").into()
    });

    // Start all listeners defined in config/config.json
    start_blocking();
}

Overview

bbwebservice mirrors the Python framework:

  • Decorator-style routing (register, post_handler, UrlTemplate, scoped selectors)
  • HTTP runtime with incremental header/body parsing (chunked, ranged, cookies, queries)
  • Response helpers (Response, Redirect, PartialContent, Dynamic, response())
  • Global utilities (load_file, urlencoded_to_map, set_cookie, etc.)
  • Configuration via config/config.json with the same schema as the Python original
  • Worker pool & backpressure (bounded stdlib threads, keep-alive control, queue limits)
  • Logging & CORS with the same scope system, callbacks, and automatic OPTIONS replies
  • TLS/HTTPS powered by rustls whenever SSL listeners are enabled (including SNI)

Paths are resolved relative to the executable. On first run the library creates content/ and config/config.json if they are missing (default config matches the Python defaults).


Getting Started

  1. Clone the repository and change into rust-bbwebservice/bbwebservice/.
  2. Use Rust 1.66+ (cargo check / cargo build).
  3. Adjust config/config.json if needed.
  4. Add the crate from crates.io:
[dependencies]
bbwebservice = "<latest version on crates.io>"

Routing & Handlers

Function Description
register(route, mime, handler) Registers GET/HEAD routes.
post_handler, put_handler, patch_handler, delete_handler, options_handler Work like the Python decorators; handlers that need request data accept a RequestContext.
UrlTemplate Uses the familiar syntax ip:port::domain:/path/{var:type} with int, float, bool, str, path.
split_route_scope Parses ip:port::domain:/path strings for custom tooling.
format_ip_port Formats scopes like the Python helper.
error_handler Registers custom pages for status codes.

Routes can be scoped by IP/port/domain; matching priority is the same as in Python (more specific scopes win). Templates populate STORE_VARS.TEMPLATE_VARS automatically.

RequestContext & STORE_VARS

Handlers receive a RequestContext, which mirrors the Python args dict. String constants under STORE_VARS remain available for compatibility. Key fields:

  • ctx.post: raw body (&[u8])
  • ctx.query_string: HashMap<String, String>
  • ctx.flags: e.g. ["urlencoded"], ["partial"]
  • ctx.cookies: parsed cookies
  • ctx.response: ResponseMessage (status, headers, body)
  • ctx.is_cancelled(): cooperative watchdog flag that flips when the handler timeout expires

urlencoded_to_map(ctx.post) converts application/x-www-form-urlencoded payloads just like in Python.


Responses & Helpers

Type / Helper Behavior
String / &'static str Returned as UTF‑8 with mime_type; charset=utf-8.
Vec<u8> / bytes Raw payload with the supplied MIME type.
Dynamic Wraps arbitrary bytes plus MIME type.
PartialContent Supports range responses (bytes=start-end).
Redirect 303/307-style redirects with Location.
Response / response() Full manual control over status, headers, body.

Logic matches Python: HEAD suppresses bodies, PartialContent sets Content-Range, Redirect drops Content-Type, and registered error_handlers are used when set.

Large payloads (including PartialContent) stream directly from disk in ~64 KiB chunks. Whenever the server knows the total length it sends Content-Length; otherwise it automatically upgrades the response to chunked transfer encoding so handlers never need to buffer whole files.


Logging

use bbwebservice::{set_logging, log_to_file, LOGGING_OPTIONS};

set_logging(LOGGING_OPTIONS::DEBUG, true, None); // global
set_logging(LOGGING_OPTIONS::REQUEST, true, Some("127.0.0.1:5000::/api")); // scoped
log_to_file("/logs/server.log", &[LOGGING_OPTIONS::ERROR], None);
  • Scopes use the same ip:port::domain notation as routes.
  • Register additional callbacks via set_logging_callback (signature (msg, timestamp, level)).
  • LOGGING_OPTIONS::TIME prepends timestamps to console output.

CORS

use bbwebservice::{enable_cors, disable_cors};

enable_cors(
    "*",
    &["GET", "POST"],
    &["Content-Type"],
    &["X-Total-Count"],
    false,
    600,
);

When enabled the server injects the CORS headers and auto-responds to OPTIONS with 204 No Content (including Allow). disable_cors() fully disables the feature.


Worker Pool, Backpressure & Keep-Alive

  • Global thread pool sized by max_threads in config/config.json (default 100). The queue size is doubled; if full, new connections get 503 Service Unavailable.
  • Each listener can set max_threads to limit its own concurrency.
  • Keep-alive is governed by keep_alive_timeout and keep_alive_max_requests. Call set_keep_alive_limits() to adjust at runtime.
  • Keep-alive responses include a Keep-Alive: timeout=.., max=.. header so clients know when to re-connect.
  • Chunked bodies, Content-Length, timeouts, and range requests are handled per connection, preventing slow clients from stalling the server.

Configuration (config/config.json)

The schema matches Python:

  • max_threads, max_header_size, max_body_size
  • keep_alive_timeout, keep_alive_max_requests
  • header_timeout, body_min_rate_bytes_per_sec, handler_timeout
  • server: list of listeners (ip, port, queue_size, max_threads, SSL, host, cert_path, https-redirect, https-redirect-escape-paths, update-cert-state)

SSL entries enable in-process TLS termination (via rustls). Provide PEM-encoded cert_path and key_path (absolute or relative to BBWS_MAIN_PATH). Optional host entries let you attach SNI-specific certificates ([{ "host": "app.example.com", "cert_path": "...", "key_path": "..." }]). With https-redirect enabled, HTTP requests are redirected to HTTPS unless they match an escape path.


Timeouts & Metrics

  • header_timeout caps the time between the first byte of a request and the end of the headers. Exceeding it yields a 408 Request Timeout.
  • body_min_rate_bytes_per_sec enforces a minimum upload rate (Slow Loris defense). When the moving average drops below the threshold the server aborts with 408.
  • handler_timeout arms a watchdog per request. When it expires the server sets ctx.is_cancelled() and ultimately responds with 504 Gateway Timeout.

Use /_bbws/metrics for a built-in JSON view of timeouts.header, timeouts.body, and timeouts.handler counters so you can hook the runtime into monitoring without extra instrumentation.


TLS / HTTPS

Native TLS is built in via rustls. To serve HTTPS:

  1. Place your certificate chain and private key in PEM format (e.g., config/cert.pem, config/key.pem).
  2. For each listener, set "SSL": true and point cert_path / key_path at those files:
{
  "ip": "0.0.0.0",
  "port": 443,
  "SSL": true,
  "cert_path": "config/cert.pem",
  "key_path": "config/key.pem"
}
  1. (Optional) Add host entries to supply additional certificates via SNI. When the client SNI matches one of the hosts, that certificate is served; otherwise, the default certificate is used.

TLS listeners and plain HTTP listeners can coexist. Combine them with https-redirect to bounce cleartext traffic over to TLS automatically.

If you enable "update-cert-state": true on a TLS listener the server watches all referenced PEM files (default cert/key plus SNI entries) and hot-reloads them without a restart as soon as they change on disk.


Utilities & Files

  • load_file, load_bin_file, load_file_from_directory (with path clamping)
  • set_cookie(ctx, key, value) adds Set-Cookie if the cookie doesn’t already exist
  • render_page & substitute_vars support simple templating (e.g. {{ ... }})
  • PartialContent::new("/video.mp4", 80_000) and Redirect("/new") behave just like the Python helpers

Project layout:

rust-bbwebservice/ ├── bbwebservice/ │ ├── Cargo.toml │ └── src/ │ ├── config.rs │ ├── logging.rs │ ├── router.rs │ ├── server.rs │ └── utils/ └── testing/ ├── Cargo.toml └── src/

Status & Next Steps

  • The public API remains 1:1 with the Python package, including STORE_VARS, MIME/status constants, and helper functions.
  • server_task() is currently a placeholder that only logs that scheduling is unimplemented.
  • Contributions are welcome (middleware, scheduling, tooling, etc.) - the architecture is intentionally modular.

Use this document as a quick reference to build services that behave exactly like the Python bbwebservice, including configuration, logging, and handler semantics.

Commit count: 0

cargo fmt