|
Csilk 0.2.1
A lightweight, high-performance C HTTP web framework
|
High-level convenience API — csilk_app_t implementation. More...
#include "csilk/app/app.h"#include <stdio.h>#include <stdlib.h>#include <string.h>#include "csilk/csilk.h"
Data Structures | |
| struct | cached_group_t |
| Internal: cached route group lookup entry for fast prefix-to-group mapping. More... | |
| struct | static_route_t |
| Internal: descriptor for a static file serving route mapping URL prefix to filesystem directory. More... | |
| struct | csilk_app_t |
| Main application structure containing config, router, server, and groups. More... | |
Macros | |
| #define | CSILK_MAX_GROUPS 32 |
| #define | CSILK_MAX_STATIC 32 |
| #define | CSILK_DFL_PORT 8080 |
Functions | |
| static void | init_app_mutex (void) |
| Internal: initialize the application-level mutex (called once via uv_once). | |
| static csilk_router_t * | get_openapi_router (void) |
| Internal: safely retrieve the current OpenAPI router under the app mutex. | |
| static void | set_openapi_router (csilk_router_t *r) |
| Internal: atomically set the global OpenAPI router reference. | |
| static void | openapi_handler (csilk_ctx_t *c) |
| Built-in handler for the /openapi.json endpoint. | |
| static void | docs_handler (csilk_ctx_t *c) |
| Built-in handler for the /docs endpoint — serves the Swagger UI HTML page. | |
| static csilk_group_t * | find_or_create_group (csilk_app_t *app, const char *prefix) |
| Find an existing group by prefix, or create a new one. | |
| static void | static_serve (csilk_ctx_t *c) |
| Internal static file serving handler. | |
| csilk_app_t * | csilk_app_new (const char *config_path) |
| Create a new application instance with optional YAML configuration file. | |
| void | csilk_app_free (csilk_app_t *app) |
| Free all application resources: server, router, groups, config, and logger. | |
| void | csilk_app_log_level (csilk_app_t *app, csilk_log_level_t level) |
| Set the minimum log level for the global logger. | |
| void | csilk_app_log_file (csilk_app_t *app, const char *path, size_t max_sz) |
| Enable logging to a file with an optional rotation threshold. | |
| void | csilk_app_log_json (csilk_app_t *app, int enable) |
| Enable or disable structured JSON log output format. | |
| void | csilk_app_use (csilk_app_t *app, csilk_handler_t h) |
| Register a middleware handler that applies to all routes globally. | |
| void | csilk_app_use_group (csilk_app_t *app, const char *prefix, csilk_handler_t h) |
| Register a middleware handler scoped to a specific URL prefix group. | |
| void | csilk_app_apply_config (csilk_app_t *app) |
| Apply configuration-driven middleware settings. | |
| void | csilk_app_enable_openapi (csilk_app_t *app, int enable) |
| Enable or disable the built-in /openapi.json endpoint. | |
| void | csilk_app_add_route (csilk_app_t *app, const char *method, const char *path, csilk_handler_t handler) |
| Register a route on the root group with a single handler. | |
| void | csilk_app_add_route_extended (csilk_app_t *app, const char *method, const char *path, csilk_handler_t handler, const char *input_type, const char *output_type, const char *summary, const char *description) |
| Register a route on the root group with a single handler and OpenAPI metadata. | |
| void | csilk_app_add_route_extended_perm (csilk_app_t *app, const char *method, const char *path, csilk_handler_t handler, const char *input_type, const char *output_type, const char *summary, const char *description, const char *perm_required, const char *perm_resource) |
| Register a route with OpenAPI metadata (input/output types). | |
| void | csilk_app_add_route_perm (csilk_app_t *app, const char *method, const char *path, csilk_handler_t handler, const char *perm_required, const char *perm_resource) |
| Register a route with permission metadata. | |
| void | csilk_app_add_handlers (csilk_app_t *app, const char *method, const char *path, csilk_handler_t *handlers, size_t n) |
| Register a route with a custom handler chain on the root group. | |
| void | csilk_app_static (csilk_app_t *app, const char *prefix, const char *root_dir) |
| Configure static file serving: map a URL prefix to a local filesystem directory. | |
| void | csilk_app_set_server_config (csilk_app_t *app, csilk_server_config_t c) |
| Apply server-level configuration to the running server. | |
| csilk_config_t * | csilk_app_config (csilk_app_t *app) |
| Get a heap-allocated copy of the current application configuration. | |
| int | csilk_app_run (csilk_app_t *app, int port) |
| Start the server and enter the libuv event loop (blocking). | |
| csilk_router_t * | csilk_app_router (csilk_app_t *app) |
| Get the underlying router handle from the application. | |
| csilk_server_t * | csilk_app_server (csilk_app_t *app) |
| Get the underlying server handle from the application. | |
Variables | |
| static csilk_router_t * | s_openapi_router = NULL |
| Router reference for the built-in OpenAPI handler. | |
| static uv_mutex_t | s_app_mutex |
| static uv_once_t | s_app_mutex_once = UV_ONCE_INIT |
| static static_route_t | g_static [CSILK_MAX_STATIC] |
| static int | g_static_n = 0 |
High-level convenience API — csilk_app_t implementation.
csilk_app_t is the top-level facade. It owns one router, one server, one root route group, and a config struct. Users interact only through the app handle; internal wiring (router -> server, group -> router) is hidden.
csilk_app_new() runs in this order:
Routes are added via the root group (csilk_group_t), which assembles a combined middleware + handler chain and hands it to the router. Static file serving uses a separate global table mapping URL prefixes to local directory roots, dispatched by a single static_serve handler.
The OpenAPI router reference is guarded by a process-level mutex so it can be toggled on/off safely at runtime. Two built-in handlers serve the spec JSON and the Swagger UI HTML page.
| struct cached_group_t |
Internal: cached route group lookup entry for fast prefix-to-group mapping.
Avoids redundant group creation when the same prefix is referenced multiple times (e.g., csilk_app_use_group then csilk_app_add_route). The cache is linear-scanned; CSILK_MAX_GROUPS (32) keeps it cheap.
| Data Fields | ||
|---|---|---|
| csilk_group_t * | group |
Cached group handle — created lazily by find_or_create_group(). Freed once in csilk_app_free(). |
| char | prefix[128] |
URL path prefix — the lookup key. |
| struct static_route_t |
Internal: descriptor for a static file serving route mapping URL prefix to filesystem directory.
Stored in a fixed-size global table (g_static[]). The static_serve handler scans the table on each request to find the matching root_dir for the requested path.
| Data Fields | ||
|---|---|---|
| char | root_dir[256] |
Local filesystem directory path served for this prefix. Passed to csilk_static() at dispatch time. |
| char | url_prefix[128] |
URL path prefix for static files (e.g., "/static"). Used as the lookup key in static_serve(). |
| struct csilk_app_s |
Main application structure containing config, router, server, and groups.
Opaque application handle.
Lifecycle: created in csilk_app_new(), destroyed in csilk_app_free(). Ownership: owns everything except the OpenAPI router pointer (global).

| Data Fields | ||
|---|---|---|
| csilk_config_t | config |
Application config (port, logger settings, server timeouts, CORS, etc.). Populated from YAML or defaults in csilk_app_new(). |
| int | group_count |
Number of valid entries in groups[] (0..32). |
| cached_group_t | groups[CSILK_MAX_GROUPS] |
Prefix-to-group cache. Linear-scanned array; avoids duplicating groups for the same prefix string. Indexed by group_count. |
| csilk_group_t * | root_group |
Root route group with prefix "". All routes added via csilk_app_add_route*() go through this group. Freed in csilk_app_free(). |
| csilk_router_t * | router |
Central router — all registered routes (including static-file routes) converge here. Created in csilk_app_new(), freed in csilk_app_free(). |
| csilk_server_t * | server |
libuv-based HTTP server. Wired to the router at creation. Built-in middlewares (recovery, logging) are injected via csilk_server_use(). |
| #define CSILK_DFL_PORT 8080 |
| #define CSILK_MAX_GROUPS 32 |
| #define CSILK_MAX_STATIC 32 |
| void csilk_app_add_handlers | ( | csilk_app_t * | app, |
| const char * | method, | ||
| const char * | path, | ||
| csilk_handler_t * | handlers, | ||
| size_t | n | ||
| ) |
Register a route with a custom handler chain on the root group.
Register a route with multiple handlers (middleware + handler).
| app | Application instance. |
| method | HTTP method. |
| path | URL path. |
| handlers | Array of handler functions. |
| n | Number of handlers in the array. |
| void csilk_app_add_route | ( | csilk_app_t * | app, |
| const char * | method, | ||
| const char * | path, | ||
| csilk_handler_t | handler | ||
| ) |
Register a route on the root group with a single handler.
Register a route with a single handler.
| app | Application instance. |
| method | HTTP method (e.g., "GET", "POST"). |
| path | URL path (e.g., "/users"). |
| handler | Handler function. |
| void csilk_app_add_route_extended | ( | csilk_app_t * | app, |
| const char * | method, | ||
| const char * | path, | ||
| csilk_handler_t | handler, | ||
| const char * | input_type, | ||
| const char * | output_type, | ||
| const char * | summary, | ||
| const char * | description | ||
| ) |
Register a route on the root group with a single handler and OpenAPI metadata.
Register a route with OpenAPI metadata (input/output types).
| app | Application instance. |
| method | HTTP method. |
| path | URL path. |
| handler | Handler function. |
| input_type | Registered type name for request body JSON schema. |
| output_type | Registered type name for response body JSON schema. |
| summary | Short description for the OpenAPI operation. |
| description | Detailed description for the OpenAPI operation. |
| void csilk_app_add_route_extended_perm | ( | csilk_app_t * | app, |
| const char * | method, | ||
| const char * | path, | ||
| csilk_handler_t | handler, | ||
| const char * | input_type, | ||
| const char * | output_type, | ||
| const char * | summary, | ||
| const char * | description, | ||
| const char * | perm_required, | ||
| const char * | perm_resource | ||
| ) |
Register a route with OpenAPI metadata (input/output types).
Register a route with full metadata including permissions.
| app | Application handle. |
| method | HTTP method string. |
| path | URL pattern (supports :param and *wildcard). |
| handler | Route handler function. |
| input_type | Registered type name for request body (NULL if none). |
| output_type | Registered type name for response (NULL if none). |
| summary | Short operation summary (NULL if none). |
| description | Detailed operation description (NULL if none). |
Register a route with OpenAPI metadata (input/output types).
| app | Application instance. |
| method | HTTP method. |
| path | URL path. |
| handler | Handler function. |
| input_type | Registered type name for request body JSON schema. |
| output_type | Registered type name for response body JSON schema. |
| summary | Short description for the OpenAPI operation. |
| description | Detailed description for the OpenAPI operation. |
| perm_required | Permission required for this route, or NULL. |
| perm_resource | Resource pattern for permission check, or NULL. |
| void csilk_app_add_route_perm | ( | csilk_app_t * | app, |
| const char * | method, | ||
| const char * | path, | ||
| csilk_handler_t | handler, | ||
| const char * | perm_required, | ||
| const char * | perm_resource | ||
| ) |
Register a route with permission metadata.
| app | Application instance. |
| method | HTTP method. |
| path | URL path. |
| handler | Handler function. |
| perm_required | Permission identifier (e.g., "read"), or NULL. |
| perm_resource | Resource pattern (e.g., "users:*"), or NULL. |
| void csilk_app_apply_config | ( | csilk_app_t * | app | ) |
Apply configuration-driven middleware settings.
Auto-apply built-in middleware based on current config.
Reads the current app config and sets up static file serving if config.static_files.enable is true and root_dir is configured. The prefix defaults to "/static" if not specified in the config.
| app | Application instance. |
| csilk_config_t * csilk_app_config | ( | csilk_app_t * | app | ) |
Get a heap-allocated copy of the current application configuration.
Get a copy of the current application configuration.
| app | Application instance. |
| void csilk_app_enable_openapi | ( | csilk_app_t * | app, |
| int | enable | ||
| ) |
Enable or disable the built-in /openapi.json endpoint.
Enable or disable the built-in /openapi.json endpoint. The endpoint is enabled by default when the app is created.
When enabled, the router's routes are exposed as an OpenAPI 3.0 specification at /openapi.json. When disabled, the endpoint returns 404.
| app | Application instance. |
| enable | 1 to enable, 0 to disable. |
| void csilk_app_free | ( | csilk_app_t * | app | ) |
Free all application resources: server, router, groups, config, and logger.
Deallocate all application resources.
Server must be freed before the router because the server holds a reference to the router internally.
| app | The application instance to free (may be NULL). |
| void csilk_app_log_file | ( | csilk_app_t * | app, |
| const char * | path, | ||
| size_t | max_sz | ||
| ) |
Enable logging to a file with an optional rotation threshold.
Enable file logging with optional rotation.
Sets the log output to the specified file path. If max_sz > 0, the log file is rotated (renamed to .1) when it exceeds this size.
| app | Application instance. |
| path | File path for log output. Pass NULL to disable file logging and revert to stdout. |
| max_sz | Maximum file size in bytes before rotation (0 = no limit). |
| void csilk_app_log_json | ( | csilk_app_t * | app, |
| int | enable | ||
| ) |
Enable or disable structured JSON log output format.
Enable or disable JSON structured log output.
When enabled, log entries are emitted as JSON objects with structured fields (timestamp, level, file, line, message, request_id). When disabled, plain text format is used.
| app | Application instance. |
| enable | 1 for JSON format, 0 for plain text. |
| void csilk_app_log_level | ( | csilk_app_t * | app, |
| csilk_log_level_t | level | ||
| ) |
Set the minimum log level for the global logger.
Set the minimum log level.
Reinitializes the logger with the updated level. Messages below this level are filtered out.
| app | Application instance. |
| level | New minimum log level (e.g., CSILK_LOG_DEBUG). |
| csilk_app_t * csilk_app_new | ( | const char * | config_path | ) |
Create a new application instance with optional YAML configuration file.
Create a new application with optional YAML config.
Phase 1 — Config & Logging
Phase 2 — Core objects
Phase 3 — Built-in endpoints
Register /csdk-docs/ as a static file route pointing to the bundled Swagger UI assets.
| config_path | Path to a YAML configuration file, or NULL to use defaults (port 8080, info-level logging to stdout). |
| csilk_router_t * csilk_app_router | ( | csilk_app_t * | app | ) |
Get the underlying router handle from the application.
Get the underlying router for advanced operations.
| app | Application instance. |
| int csilk_app_run | ( | csilk_app_t * | app, |
| int | port | ||
| ) |
Start the server and enter the libuv event loop (blocking).
Start the server and block until stopped (Ctrl+C).
This is the main entry point into the event-driven I/O loop. It delegates to csilk_server_run() which:
| app | Application instance. |
| port | TCP port to listen on. Pass 0 or negative to use the port from the application config (default 8080). |
| csilk_server_t * csilk_app_server | ( | csilk_app_t * | app | ) |
Get the underlying server handle from the application.
Get the underlying server for advanced operations.
| app | Application instance. |
| void csilk_app_set_server_config | ( | csilk_app_t * | app, |
| csilk_server_config_t | c | ||
| ) |
Apply server-level configuration to the running server.
Apply server-level configuration (timeouts, limits, TCP options).
Updates both the app's stored config and applies it to the server instance. This overrides any previous server config.
| app | Application instance. |
| c | Server configuration struct. |
| void csilk_app_static | ( | csilk_app_t * | app, |
| const char * | prefix, | ||
| const char * | root_dir | ||
| ) |
Configure static file serving: map a URL prefix to a local filesystem directory.
Serve static files from a local directory.
prefix:WILDCARD path — wildcard route that captures everything after the prefix./ — the prefix root (redirects to the index file). Both routes use the same internal static_serve handler, which scans g_static[] at request time to find the correct root_dir.The dual-route pattern means both /static/ and /static/foo/bar.jpg work. The static_prefix context variable lets csilk_static() strip the URL prefix from the filesystem path.
| app | Application instance. |
| prefix | URL path prefix for static files (e.g., "/static"). |
| root_dir | Local filesystem directory to serve files from. |
| void csilk_app_use | ( | csilk_app_t * | app, |
| csilk_handler_t | h | ||
| ) |
Register a middleware handler that applies to all routes globally.
Register a global middleware that runs on every route.
Global middleware runs before route-specific middleware and handlers for every request. Built-in recovery and logger middleware are registered automatically by csilk_app_new().
| app | Application instance. |
| h | Middleware handler function. |
| void csilk_app_use_group | ( | csilk_app_t * | app, |
| const char * | prefix, | ||
| csilk_handler_t | h | ||
| ) |
Register a middleware handler scoped to a specific URL prefix group.
Register a middleware that runs only on a specific prefix group.
Creates (or finds) a route group for the given prefix and adds the middleware to it. The middleware runs for any route whose path starts with the given prefix.
| app | Application instance. |
| prefix | URL prefix (e.g., "/api/admin"). |
| h | Middleware handler function. |
|
static |
Built-in handler for the /docs endpoint — serves the Swagger UI HTML page.
Checks that the OpenAPI router is active, then serves the embedded Swagger UI HTML page which loads /openapi.json at runtime.
| c | The request context. |
|
static |
Find an existing group by prefix, or create a new one.
Nesting under root_group means any middleware registered on root_group automatically applies to all subgroup routes (see group.c: gather_handlers).
| app | Application handle. |
| prefix | URL path prefix. |
|
static |
Internal: safely retrieve the current OpenAPI router under the app mutex.
|
static |
Internal: initialize the application-level mutex (called once via uv_once).
Creates the mutex that protects the shared OpenAPI router reference and the static file route table.
|
static |
Built-in handler for the /openapi.json endpoint.
Retrieves the current OpenAPI router and serves the generated OpenAPI 3.0 specification as a JSON response. If the router is NULL (endpoint disabled), returns 404.
| c | The request context. |
|
static |
Internal: atomically set the global OpenAPI router reference.
| r | Router to set (pass NULL to disable the OpenAPI endpoint). |
|
static |
Internal static file serving handler.
The mutex is released before csilk_static() to avoid holding it during disk I/O. The prefix match is a simple strncmp — the longest prefix configured first wins.
| c | The request context. |
|
static |
|
static |
|
static |
|
static |
|
static |
Router reference for the built-in OpenAPI handler.