Crate mik_sdk

Crate mik_sdk 

Source
Expand description

mik-sdk - Ergonomic SDK for WASI HTTP handlers

§Overview

mik-sdk provides a simple, ergonomic way to build portable WASI HTTP handlers. Write your handler once, run it on Spin, wasmCloud, wasmtime, or any WASI-compliant runtime.

Available on crates.io.

§Architecture

┌─────────────────────────────────────────────────────────┐
│  Your Handler                                           │
│  ┌───────────────────────────────────────────────────┐  │
│  │  use mik_sdk::prelude::*;                         │  │
│  │                                                   │  │
│  │  routes! {                                        │  │
│  │      "/" => home,                                 │  │
│  │      "/users/{id}" => get_user,                   │  │
│  │  }                                                │  │
│  │                                                   │  │
│  │  fn get_user(req: &Request) -> Response {         │  │
│  │      let id = req.param("id").unwrap();           │  │
│  │      ok!({ "id": str(id) })                       │  │
│  │  }                                                │  │
│  └───────────────────────────────────────────────────┘  │
└─────────────────────────────────────────────────────────┘
                          ↓ compose with
┌─────────────────────────────────────────────────────────┐
│  Router Component (provides JSON/HTTP utilities)        │
└─────────────────────────────────────────────────────────┘
                          ↓ compose with
┌─────────────────────────────────────────────────────────┐
│  Bridge Component (WASI HTTP adapter)                   │
└─────────────────────────────────────────────────────────┘
                          ↓ runs on
┌─────────────────────────────────────────────────────────┐
│  Any WASI HTTP Runtime (Spin, wasmCloud, wasmtime)      │
└─────────────────────────────────────────────────────────┘

§Quick Start

use bindings::exports::mik::core::handler::Guest;
use bindings::mik::core::{http, json};
use mik_sdk::prelude::*;

routes! {
    GET "/" => home,
    GET "/hello/{name}" => hello(path: HelloPath),
}

fn home(_req: &Request) -> http::Response {
    ok!({
        "message": "Welcome!",
        "version": "0.1.0"
    })
}

fn hello(req: &Request) -> http::Response {
    let name = req.param("name").unwrap_or("world");
    ok!({
        "greeting": str(format!("Hello, {}!", name))
    })
}

§Configuration

The SDK and bridge can be configured via environment variables:

VariableDefaultDescription
MIK_MAX_JSON_SIZE1 MBMaximum JSON input size for parsing
MIK_MAX_BODY_SIZE10 MBMaximum request body size (bridge)
# Allow 5MB JSON payloads
MIK_MAX_JSON_SIZE=5000000

# Allow 50MB request bodies
MIK_MAX_BODY_SIZE=52428800

§Core Macros

  • ok! - Return 200 OK with JSON body
  • error! - Return RFC 7807 error response
  • json! - Create a JSON value with type hints

§DX Macros

  • guard! - Early return validation
  • created! - 201 Created response with Location header
  • no_content! - 204 No Content response
  • redirect! - Redirect responses (301, 302, 307, etc.)

§Request Helpers

// Path parameters (from route pattern)
let id = req.param("id");              // Option<&str>

// Query parameters
let page = req.query("page");          // Option<&str> - first value
let tags = req.query_all("tag");       // &[String] - all values

// Example: /search?tag=rust&tag=wasm&tag=http
req.query("tag")      // → Some("rust")
req.query_all("tag")  // → &["rust", "wasm", "http"]

// Headers (case-insensitive)
let auth = req.header("Authorization");    // Option<&str>
let cookies = req.header_all("Set-Cookie"); // &[String]

// Body
let bytes = req.body();                // Option<&[u8]>
let text = req.text();                 // Option<&str>
let json = req.json_with(json::try_parse); // Option<JsonValue>

§DX Macro Examples

// Early return validation
fn create_user(req: &Request) -> http::Response {
    let name = body.get("name").str_or("");
    guard!(!name.is_empty(), 400, "Name is required");
    guard!(name.len() <= 100, 400, "Name too long");
    created!("/users/123", { "id": "123", "name": str(name) })
}

// Response shortcuts
fn delete_user(req: &Request) -> http::Response {
    no_content!()
}

fn legacy_endpoint(req: &Request) -> http::Response {
    redirect!("/api/v2/users")  // 302 Found
}

§Type Hints

Use type hints inside ok!, json!, and error! macros:

  • str(expr) - Convert to JSON string
  • int(expr) - Convert to JSON integer
  • float(expr) - Convert to JSON float
  • bool(expr) - Convert to JSON boolean

§RFC 7807 Problem Details

Error responses follow RFC 7807:

// Basic usage (only status is required)
error! { status: 400, title: "Bad Request", detail: "Missing field" }

// Full RFC 7807 with extensions
error! {
    status: status::UNPROCESSABLE_ENTITY,
    title: "Validation Error",
    detail: "Invalid input",
    problem_type: "urn:problem:validation",
    instance: "/users/123",
    meta: { "field": "email" }
}

Re-exports§

pub use mik_sql as query;

Modules§

constants
Centralized constants for the mik-sdk crate.
env
Environment variable access for WASI HTTP handlers.
http_client
HTTP client for making outbound requests from WASI handlers.
json
JSON parsing and building using miniserde.
log
Structured JSON logging to stderr.
prelude
Prelude module for convenient imports.
random
Cryptographically secure random value generation.
status
HTTP status code constants.
time
Time utilities for WASI HTTP handlers.
typed
Typed input infrastructure for type-safe request handling.

Macros§

accepted
Return 202 Accepted.
bad_request
Return 400 Bad Request.
conflict
Return 409 Conflict.
created
Create a 201 Created response.
ensure
Unwrap Option/Result or return error.
error
Return RFC 7807 Problem Details error response.
fetch
Build an HTTP client request.
forbidden
Return 403 Forbidden.
guard
Early return validation guard.
ids
Collect field values from a list.
json
Create a JSON value with clean syntax.
log
Structured logging macro with key-value pairs.
log_debug
Log a debug message to stderr (only in debug builds).
log_error
Log an error message to stderr.
log_info
Log an informational message to stderr.
log_warn
Log a warning message to stderr.
no_content
Create a 204 No Content response.
not_found
Return 404 Not Found.
ok
Return 200 OK with JSON body.
redirect
Create a redirect response.
routes
Define routes with typed inputs and OpenAPI generation.
sql_create
Build an INSERT query using object-like syntax (CRUD: Create).
sql_delete
Build a DELETE query using object-like syntax (CRUD: Delete).
sql_read
Build a SELECT query using the query builder (CRUD: Read).
sql_update
Build an UPDATE query using object-like syntax (CRUD: Update).

Structs§

Request
HTTP Request wrapper providing convenient access to request data.

Enums§

DecodeError
Error returned when URL decoding fails.
Method
HTTP method enum matching the WIT definition.

Functions§

url_decode
Basic URL decoding (handles %XX sequences and + as space).

Derive Macros§

Path
Derive macro for path parameter types.
Query
Derive macro for query parameter types.
Type
Derive macro for JSON body types.