|
Csilk 0.2.1
A lightweight, high-performance C HTTP web framework
|
High-performance C web framework — main public API header. More...
#include <setjmp.h>#include <stddef.h>#include <stdint.h>#include <uv.h>#include "cJSON.h"#include "csilk/drivers/ai.h"#include "csilk/drivers/cipher.h"#include "csilk/drivers/db.h"#include "csilk/drivers/perm.h"#include "csilk/reflection/reflect.h"

Go to the source code of this file.
Data Structures | |
| struct | csilk_storage_driver_t |
| Pluggable storage driver for context key-value pairs. More... | |
| struct | csilk_header_t |
| A single HTTP header stored as a node in a chained hash table. More... | |
| struct | csilk_header_map_t |
| A fixed-size chained hash table for HTTP headers. More... | |
| struct | csilk_request_t |
| Parsed HTTP request. More... | |
| struct | csilk_response_t |
| Mutable HTTP response. More... | |
| struct | csilk_param_t |
| A single URL path parameter extracted from a route pattern. More... | |
| struct | csilk_log_config_t |
| Logger initialisation configuration. More... | |
| struct | csilk_cors_config_t |
| CORS middleware configuration. More... | |
| struct | csilk_security_stats_t |
| Security layer statistics. More... | |
| struct | csilk_process_stats_t |
| OS-level process statistics. More... | |
| struct | csilk_server_config_t |
| Low-level server configuration options. More... | |
| struct | csilk_config_t |
| Top-level application configuration. More... | |
| struct | csilk_valid_rule_t |
| A single validation rule for request parameter checking. More... | |
| struct | csilk_router_t |
| The main HTTP router. More... | |
| struct | csilk_multipart_part_t |
| A single part parsed from a multipart/form-data request body. More... | |
| struct | csilk_crypto_driver_t |
| Pluggable cryptographic primitive driver. More... | |
| struct | csilk_mq_stats_t |
| Message Queue statistics. More... | |
| struct | csilk_config_t.cors |
| struct | csilk_config_t.rate_limit |
| struct | csilk_config_t.static_files |
| struct | csilk_config_t.middleware |
| struct | csilk_config_t.ai |
| struct | csilk_config_t.cipher |
Macros | |
| #define | CSILK_VERSION "0.2.3" |
| Csilk framework version string (MAJOR.MINOR.PATCH). Used for identification in logs, headers, and the OpenAPI spec. | |
| #define | CSILK_MAX_PARAMS 20 |
| Maximum number of URL path parameters that can be extracted from a single request. Parameters beyond this limit are silently ignored. Tune if your routes contain more than 20 dynamic segments. | |
| #define | CSILK_MAX_STORAGE 64 |
| Maximum number of items that can be stored in the context key-value storage. | |
| #define | CSILK_HEADER_BUCKETS 64 |
| Number of buckets in the header chained hash table. | |
| #define | csilk_bind(c, type, ptr) csilk_bind_reflect(c, #type, ptr) |
| Convenience macro for binding JSON body to a reflected struct. Wraps csilk_bind_reflect, automatically stringifying the type name. | |
| #define | csilk_json_t(c, status, type, ptr) csilk_json_reflect(c, status, #type, ptr) |
| Convenience macro for sending a reflected struct as JSON response. Wraps csilk_json_reflect, automatically stringifying the type name. | |
| #define | CSILK_ROUTE( r, method, path, handlers, handler_count, input_type, output_type, summary, desc) |
| Convenience macro to register a route with metadata. | |
HTTP Status Codes | |
Standardized macros for common HTTP response status codes. Use these instead of raw integer literals for readability. | |
| #define | CSILK_STATUS_CONTINUE 100 |
| #define | CSILK_STATUS_SWITCHING_PROTOCOLS 101 |
| #define | CSILK_STATUS_OK 200 |
| #define | CSILK_STATUS_CREATED 201 |
| #define | CSILK_STATUS_NO_CONTENT 204 |
| #define | CSILK_STATUS_PARTIAL_CONTENT 206 |
| #define | CSILK_STATUS_MOVED_PERMANENTLY 301 |
| #define | CSILK_STATUS_FOUND 302 |
| #define | CSILK_STATUS_NOT_MODIFIED 304 |
| #define | CSILK_STATUS_TEMPORARY_REDIRECT 307 |
| #define | CSILK_STATUS_BAD_REQUEST 400 |
| #define | CSILK_STATUS_UNAUTHORIZED 401 |
| #define | CSILK_STATUS_PAYMENT_REQUIRED 402 |
| #define | CSILK_STATUS_FORBIDDEN 403 |
| #define | CSILK_STATUS_NOT_FOUND 404 |
| #define | CSILK_STATUS_METHOD_NOT_ALLOWED 405 |
| #define | CSILK_STATUS_REQUEST_TIMEOUT 408 |
| #define | CSILK_STATUS_CONFLICT 409 |
| #define | CSILK_STATUS_GONE 410 |
| #define | CSILK_STATUS_PAYLOAD_TOO_LARGE 413 |
| #define | CSILK_STATUS_RANGE_NOT_SATISFIABLE 416 |
| #define | CSILK_STATUS_URI_TOO_LONG 414 |
| #define | CSILK_STATUS_UNSUPPORTED_MEDIA_TYPE 415 |
| #define | CSILK_STATUS_TOO_MANY_REQUESTS 429 |
| #define | CSILK_STATUS_INTERNAL_SERVER_ERROR 500 |
| #define | CSILK_STATUS_NOT_IMPLEMENTED 501 |
| #define | CSILK_STATUS_BAD_GATEWAY 502 |
| #define | CSILK_STATUS_SERVICE_UNAVAILABLE 503 |
| #define | CSILK_STATUS_GATEWAY_TIMEOUT 504 |
Logging Macros | |
Convenience macros that capture source location. | |
| #define | CSILK_LOG_T(...) _csilk_log_internal(CSILK_LOG_TRACE, __FILE__, __LINE__, __func__, __VA_ARGS__) |
| Log a TRACE-level message. | |
| #define | CSILK_LOG_D(...) _csilk_log_internal(CSILK_LOG_DEBUG, __FILE__, __LINE__, __func__, __VA_ARGS__) |
| Log a DEBUG-level message. | |
| #define | CSILK_LOG_I(...) _csilk_log_internal(CSILK_LOG_INFO, __FILE__, __LINE__, __func__, __VA_ARGS__) |
| Log an INFO-level message. | |
| #define | CSILK_LOG_W(...) _csilk_log_internal(CSILK_LOG_WARN, __FILE__, __LINE__, __func__, __VA_ARGS__) |
| Log a WARN-level message. | |
| #define | CSILK_LOG_E(...) _csilk_log_internal(CSILK_LOG_ERROR, __FILE__, __LINE__, __func__, __VA_ARGS__) |
| Log an ERROR-level message. | |
| #define | CSILK_LOG_F(...) _csilk_log_internal(CSILK_LOG_FATAL, __FILE__, __LINE__, __func__, __VA_ARGS__) |
| Log a FATAL-level message. | |
| #define | CSILK_LOG_STRUCT(level, extra, ...) _csilk_log_structured(level, __FILE__, __LINE__, __func__, extra, __VA_ARGS__) |
| Log a structured JSON message (only meaningful when json_format is on). | |
Validation flags | |
Bit flags for use in csilk_valid_rule_t.flags. Combine with |. | |
| #define | CSILK_VALID_REQUIRED (1 << 0) |
| #define | CSILK_VALID_INT (1 << 1) |
| #define | CSILK_VALID_STRING (1 << 2) |
| #define | CSILK_VALID_EMAIL (1 << 3) |
Group Route Macros | |
Convenience macros for adding routes to groups. | |
| #define | csilk_GET(group, path, handler) csilk_group_add_route(group, "GET", path, handler) |
| Register a GET route on the group. | |
| #define | csilk_POST(group, path, handler) csilk_group_add_route(group, "POST", path, handler) |
| Register a POST route on the group. | |
| #define | csilk_PUT(group, path, handler) csilk_group_add_route(group, "PUT", path, handler) |
| Register a PUT route on the group. | |
| #define | csilk_DELETE(group, path, handler) csilk_group_add_route(group, "DELETE", path, handler) |
| Register a DELETE route on the group. | |
| #define | csilk_PATCH(group, path, handler) csilk_group_add_route(group, "PATCH", path, handler) |
| Register a PATCH route on the group. | |
| #define | csilk_OPTIONS(group, path, handler) csilk_group_add_route(group, "OPTIONS", path, handler) |
| Register an OPTIONS route on the group. | |
| #define | csilk_HEAD(group, path, handler) csilk_group_add_route(group, "HEAD", path, handler) |
| Register a HEAD route on the group. | |
Typedefs | |
| typedef struct csilk_db_pool_s | csilk_db_pool_t |
| typedef void(* | csilk_handler_t) (csilk_ctx_t *c) |
| Function pointer for route handlers and middleware. | |
| typedef struct csilk_arena_s | csilk_arena_t |
| Opaque arena allocator type. | |
| typedef int(* | csilk_auth_validator_t) (const char *token) |
| Authentication validator callback. | |
| typedef void(* | csilk_multipart_handler_t) (csilk_multipart_part_t *part) |
| Callback invoked for each part during multipart parsing. | |
| typedef void(* | csilk_server_hook_handler_t) (csilk_server_t *s) |
| Callback signature for server-level hooks. | |
| typedef void(* | csilk_ctx_hook_handler_t) (csilk_ctx_t *c) |
| Callback signature for request/connection-level hooks. | |
| typedef void(* | csilk_mq_handler_t) (csilk_mq_ctx_t *ctx) |
| MQ handler signature for middleware and subscribers. | |
| typedef void(* | csilk_mq_worker_t) (const char *topic, const void *payload, size_t len) |
| Signature for a background MQ worker function. | |
Enumerations | |
| enum | csilk_log_level_t { CSILK_LOG_TRACE , CSILK_LOG_DEBUG , CSILK_LOG_INFO , CSILK_LOG_WARN , CSILK_LOG_ERROR , CSILK_LOG_FATAL } |
| Log severity levels. More... | |
| enum | csilk_hook_type_t { CSILK_HOOK_SERVER_START , CSILK_HOOK_SERVER_STOP , CSILK_HOOK_CONN_OPEN , CSILK_HOOK_CONN_CLOSE , CSILK_HOOK_REQUEST_BEGIN , CSILK_HOOK_REQUEST_END , CSILK_HOOK_COUNT } |
| Lifecycle hook types for the server and individual requests. More... | |
Functions | |
| const char * | csilk_get_method (csilk_ctx_t *c) |
| Get the HTTP method of the current request. | |
| const char * | csilk_get_path (csilk_ctx_t *c) |
| Get the decoded URL path of the current request. | |
| const char * | csilk_get_body (csilk_ctx_t *c, size_t *out_len) |
| Get the raw request body and its length. | |
| size_t | csilk_get_body_len (csilk_ctx_t *c) |
| Get the length of the raw request body. | |
| int | csilk_is_websocket (csilk_ctx_t *c) |
| Check whether the connection has been upgraded to WebSocket. | |
| void | csilk_set_websocket (csilk_ctx_t *c, int is_websocket) |
| Enable or disable WebSocket mode. | |
| int | csilk_is_sse (csilk_ctx_t *c) |
| Check whether the connection is in Server-Sent Events mode. | |
| void | csilk_set_sse (csilk_ctx_t *c, int is_sse) |
| Enable or disable Server-Sent Events (SSE) mode. | |
| int | csilk_is_aborted (csilk_ctx_t *c) |
| Check whether the handler chain has been aborted. | |
| void | csilk_set_on_ws_message (csilk_ctx_t *c, void(*callback)(csilk_ctx_t *c, const uint8_t *payload, size_t len, int opcode)) |
| Register a callback for incoming WebSocket messages. | |
| void | csilk_set_on_ws_send (csilk_ctx_t *c, void(*callback)(csilk_ctx_t *c, const uint8_t *payload, size_t len, int opcode)) |
| Set a callback for outgoing WebSocket frames (for testing). | |
| const char * | csilk_get_request_id (csilk_ctx_t *c) |
| Get the unique identifier for the current request. | |
| csilk_arena_t * | csilk_get_arena (csilk_ctx_t *c) |
| Get the arena allocator associated with the request context. | |
| int | csilk_get_status (csilk_ctx_t *c) |
| Get the current response status code. | |
| void | csilk_set_async (csilk_ctx_t *c, int is_async) |
| Enable or disable asynchronous response mode. | |
| int | csilk_is_async (csilk_ctx_t *c) |
| Check whether asynchronous response mode is enabled. | |
| int | csilk_get_handler_index (csilk_ctx_t *c) |
| Get the index of the currently executing handler in the chain. | |
| void | csilk_set_request_id (csilk_ctx_t *c, const char *id) |
| Set the request unique identifier. | |
| uv_work_t * | csilk_get_work_req (csilk_ctx_t *c) |
| Get the libuv work request associated with the context. | |
| void | csilk_set_file_response (csilk_ctx_t *c, int fd, size_t offset, size_t size) |
| Set the zero-copy file response parameters. | |
| int | csilk_get_file_fd (csilk_ctx_t *c) |
| Get the current zero-copy file descriptor. | |
| const char * | csilk_ctx_get_handler_path (csilk_ctx_t *c) |
| Get the route pattern for the matched handler (e.g., "/users/:id"). | |
| const char * | csilk_ctx_get_handler_perm_required (csilk_ctx_t *c) |
| Get the permission string required by the matched handler. | |
| const char * | csilk_ctx_get_handler_perm_resource (csilk_ctx_t *c) |
| Get the resource pattern for the matched handler's permission check. | |
| void | csilk_set_response_body (csilk_ctx_t *c, const char *body, size_t len, int managed) |
| Overwrite the response body from middleware. | |
| const char * | csilk_get_response_body (csilk_ctx_t *c, size_t *out_len) |
| Get the response body data and optionally its length. | |
| void | csilk_redirect (csilk_ctx_t *c, int status, const char *location) |
| Send an HTTP redirect response with a custom status code. | |
| void | csilk_redirect_simple (csilk_ctx_t *c, const char *url) |
| Send a simple 302 Found redirect. | |
| void | csilk_set (csilk_ctx_t *c, const char *key, void *value) |
| Store an opaque value in the request context. | |
| void * | csilk_get (csilk_ctx_t *c, const char *key) |
| Retrieve an opaque value from the request context. | |
| void | csilk_next (csilk_ctx_t *c) |
| Pass control to the next handler in the middleware/handler chain. | |
| void | csilk_abort (csilk_ctx_t *c) |
| Immediately abort the handler chain. | |
| void | csilk_status (csilk_ctx_t *c, int status) |
| Set the HTTP response status code. | |
| void | csilk_string (csilk_ctx_t *c, int status, const char *msg) |
| Set a plain-text response body and status code. | |
| const char * | csilk_get_param (csilk_ctx_t *c, const char *key) |
| Get a URL path parameter by key. | |
| int | csilk_get_params_count (csilk_ctx_t *c) |
| Get the number of path parameters extracted from the URL. | |
| const char * | csilk_get_param_key (csilk_ctx_t *c, int index) |
| Get the name of a path parameter by its index. | |
| const char * | csilk_get_param_value (csilk_ctx_t *c, int index) |
| Get the value of a path parameter by its index. | |
| const char * | csilk_get_header (csilk_ctx_t *c, const char *key) |
| Get a request header value by name (case-insensitive). | |
| const char * | csilk_get_response_header (csilk_ctx_t *c, const char *key) |
| Get a response header value by name (case-insensitive). | |
| const char * | csilk_get_query (csilk_ctx_t *c, const char *key) |
| Get a query-string parameter by key. | |
| void | csilk_parse_form_urlencoded (csilk_ctx_t *c) |
| Parse the request body as application/x-www-form-urlencoded. | |
| const char * | csilk_get_form_field (csilk_ctx_t *c, const char *key) |
| Get a form-urlencoded field value by key. | |
| void | csilk_set_request_header (csilk_ctx_t *c, const char *key, const char *value) |
| Set (or overwrite) a request header. | |
| void | csilk_set_header (csilk_ctx_t *c, const char *key, const char *value) |
| Set (or overwrite) a response header. | |
| void | csilk_add_header (csilk_ctx_t *c, const char *key, const char *value) |
| Append a response header, preserving any existing value(s). | |
| void | csilk_ctx_cleanup (csilk_ctx_t *c) |
| Release all memory and resources associated with a request context. | |
| csilk_arena_t * | csilk_arena_new (size_t default_chunk_size) |
| Create a new arena allocator. | |
| void * | csilk_arena_alloc (csilk_arena_t *arena, size_t size) |
| Allocate zero-initialised memory from an arena. | |
| char * | csilk_arena_strdup (csilk_arena_t *arena, const char *s) |
| Duplicate a NUL-terminated string using the arena allocator. | |
| char * | csilk_arena_strndup (csilk_arena_t *arena, const char *s, size_t n) |
Duplicate n bytes of a string using the arena allocator. | |
| void | csilk_arena_free (csilk_arena_t *arena) |
| Free all memory chunks owned by the arena. | |
| void | csilk_arena_reset (csilk_arena_t *arena) |
| Reset the arena without freeing its chunks. | |
| void | csilk_arena_get_stats (csilk_arena_t *arena, size_t *total_size, size_t *total_used) |
| Get total allocated size and used bytes in the arena. | |
| void | csilk_recovery_handler (csilk_ctx_t *c) |
| Panic-recovery middleware. | |
| void | csilk_panic (csilk_ctx_t *c) |
| Trigger a panic (caught by recovery middleware). | |
| int | csilk_log_init (csilk_log_config_t config) |
| Initialize the global logger with config. | |
| void | _csilk_log_internal (csilk_log_level_t lv, const char *file, int line, const char *func, const char *fmt,...) |
| Internal log function (use macros instead). | |
| void | csilk_log_close () |
| Close the global logger. | |
| void | _csilk_log_structured (csilk_log_level_t lv, const char *file, int line, const char *func, cJSON *extra, const char *fmt,...) |
| Log a structured JSON message with extra key-value fields. | |
| int | csilk_log_is_json (void) |
| Check whether the logger is in JSON format mode. | |
| void | csilk_log_set_request_id (const char *request_id) |
| Set the Request ID for the current thread (for log correlation). | |
| cJSON * | csilk_log_make_kv (const char *key,...) |
| Create a simple key-value cJSON object for structured logging. | |
| void | csilk_logger_handler (csilk_ctx_t *c) |
| Logging middleware handler. Logs request method, path, and processing time. | |
| void | csilk_request_id_middleware (csilk_ctx_t *c) |
| Request ID middleware. Generates a unique ID for each request and sets X-Request-Id header. | |
| void | csilk_health_check_handler (csilk_ctx_t *c) |
| Built-in Health Check handler. Returns a simple JSON response {"status": "up"}. | |
| void | csilk_ready_check_handler (csilk_ctx_t *c) |
| Built-in Readiness Check handler. Performs deep health check (MQ, connections) and returns 200 or 503. | |
| void | csilk_cors_middleware (csilk_ctx_t *c, const csilk_cors_config_t *config) |
| CORS middleware — handles preflight and adds CORS headers. | |
| void | csilk_rate_limit_middleware (csilk_ctx_t *c, int limit) |
| Simple per-IP rate-limiting middleware. | |
| void | csilk_csrf_middleware (csilk_ctx_t *c) |
| Stateless CSRF protection middleware. | |
| void | csilk_security_get_stats (csilk_security_stats_t *stats) |
| void | csilk_process_get_stats (csilk_process_stats_t *stats) |
| int | csilk_csrf_generate_token (char *buf, size_t buf_size) |
| Generate a cryptographically random CSRF token. | |
| int | csilk_load_config (const char *yaml_path, csilk_config_t *config) |
| Load and parse a YAML configuration file. | |
| int | csilk_config_validate (const csilk_config_t *config, const char **error_msg) |
| Validate configuration values for semantic correctness. | |
| void | csilk_config_free (csilk_config_t *config) |
| Free all heap-allocated strings inside a configuration. | |
| void | csilk_auth_middleware (csilk_ctx_t *c, csilk_auth_validator_t validator) |
| Simple token-based authentication middleware. | |
| void | csilk_static (csilk_ctx_t *c, const char *root_dir) |
| Serve static files from a local directory. | |
| void | csilk_file (csilk_ctx_t *c, const char *file_path) |
| Serve a specific file from the local filesystem. | |
| cJSON * | csilk_bind_json (csilk_ctx_t *c) |
| Bind the request body (JSON) to a cJSON object. | |
| cJSON * | csilk_bind_json_err (csilk_ctx_t *c, const char **error) |
| Bind request body to cJSON with a descriptive error message. | |
| const char * | csilk_get_cookie (csilk_ctx_t *c, const char *name) |
| Get a cookie value by name from the Cookie request header. | |
| void | csilk_set_cookie (csilk_ctx_t *c, const char *name, const char *value, int max_age, const char *path, const char *domain, int secure, int http_only) |
| Set a cookie in the Set-Cookie response header. | |
| void | csilk_session_init (void) |
| Initialise the session subsystem (call once at startup). | |
| void | csilk_session_start (csilk_ctx_t *c) |
| Start or resume a session for the current request. | |
| void | csilk_session_set (csilk_ctx_t *c, const char *key, void *value) |
| Store a value in the session. | |
| void * | csilk_session_get (csilk_ctx_t *c, const char *key) |
| Retrieve a value from the session. | |
| void | csilk_session_destroy (csilk_ctx_t *c) |
| Destroy the session and clear the session cookie. | |
| const char * | csilk_validate (csilk_ctx_t *c, const csilk_valid_rule_t *rules) |
| Validate request parameters against a set of rules. | |
| void | csilk_json (csilk_ctx_t *c, int status, cJSON *json) |
| Send a JSON response (takes ownership of the cJSON object). | |
| void | csilk_json_error (csilk_ctx_t *c, int status, const char *message) |
| Send a JSON-formatted error response. | |
| int | csilk_bind_reflect (csilk_ctx_t *c, const char *type_name, void *ptr) |
| Parse the JSON request body into a struct registered via reflection. | |
| void | csilk_json_reflect (csilk_ctx_t *c, int status, const char *type_name, const void *ptr) |
| Serialise a reflected struct as a JSON response. | |
| const char * | csilk_get_client_ip (csilk_ctx_t *c) |
| Get the client's IP address. | |
| void | csilk_split_url (const char *url, char **path, char **query) |
| Split a URL into path and query-string components. | |
| void | csilk_parse_query (csilk_ctx_t *c, const char *query_string) |
| Parse a raw query string and populate the query_params map. | |
| csilk_router_t * | csilk_router_new (void) |
| Create a new empty router. | |
| void | csilk_router_add (csilk_router_t *r, const char *method, const char *path, csilk_handler_t *handlers, size_t handler_count) |
| Register a route with one or more handlers. | |
| csilk_handler_t * | csilk_router_match (csilk_router_t *r, const char *method, const char *path) |
| Match a raw method+path to handlers (standalone, no context). | |
| int | csilk_router_match_ctx (csilk_router_t *r, csilk_ctx_t *c) |
| Match the current request against the router and update the context. | |
| void | csilk_router_free (csilk_router_t *r) |
| Destroy the router and release all its resources. | |
| cJSON * | csilk_router_collect_routes (csilk_router_t *r) |
| Collect all registered routes from the router tree as a cJSON array. | |
| cJSON * | csilk_generate_openapi_json (csilk_router_t *router, const char *title, const char *version, const char *description) |
| Generate an OpenAPI 3.0 specification JSON from the router. | |
| void | csilk_router_add_extended (csilk_router_t *r, const char *method, const char *path, csilk_handler_t *handlers, size_t handler_count, const char *path_pattern, const char *input_type, const char *output_type, const char *summary, const char *description) |
| Register a route with full OpenAPI/reflection metadata. | |
| void | csilk_router_add_perm (csilk_router_t *r, const char *method, const char *path, csilk_handler_t *handlers, size_t handler_count, const char *perm_required, const char *perm_resource) |
| Register a route with permission metadata. | |
| void | csilk_router_add_extended_perm (csilk_router_t *r, const char *method, const char *path, csilk_handler_t *handlers, size_t handler_count, const char *path_pattern, 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 full metadata including permissions. | |
| void | csilk_serve_openapi (csilk_ctx_t *c, csilk_router_t *r, const char *title, const char *version, const char *description) |
| Serve the OpenAPI JSON specification as the response. | |
| void | csilk_serve_swagger_ui (csilk_ctx_t *c) |
| Serve the embedded Swagger UI page. | |
| csilk_group_t * | csilk_group_new (csilk_router_t *router, const char *prefix) |
| Create a new route group with a URL prefix. | |
| csilk_group_t * | csilk_group_group (csilk_group_t *parent, const char *prefix) |
| Create a nested sub-group within an existing group. | |
| void | csilk_group_use (csilk_group_t *group, csilk_handler_t handler) |
| Add middleware to a group. | |
| void | csilk_group_add_route (csilk_group_t *group, const char *method, const char *path, csilk_handler_t handler) |
| Add a route to the group. | |
| void | csilk_group_add_route_extended (csilk_group_t *group, const char *method, const char *path, csilk_handler_t handler, const char *input_type, const char *output_type, const char *summary, const char *description) |
| Add a route with OpenAPI/reflection metadata to a group. | |
| void | csilk_group_add_route_extended_perm (csilk_group_t *group, 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) |
| Add a route with OpenAPI/reflection metadata to a group. | |
| void | csilk_group_add_handlers (csilk_group_t *group, const char *method, const char *path, csilk_handler_t *handlers, size_t count) |
| Add a route with an explicit array of handlers. | |
| void | csilk_group_free (csilk_group_t *group) |
| Destroy a route group and release its resources. | |
| void | csilk_ws_handshake (csilk_ctx_t *c) |
| Perform the WebSocket upgrade handshake (HTTP Upgrade request). | |
| void | csilk_ws_send (csilk_ctx_t *c, const uint8_t *payload, size_t len, int opcode) |
| Send a WebSocket data frame. | |
| void | csilk_ws_close (csilk_ctx_t *c, uint16_t status_code, const char *reason) |
| Send a WebSocket close frame. | |
| void | csilk_response_write (csilk_ctx_t *c, const uint8_t *data, size_t len) |
| Write a chunk to the response stream (chunked transfer encoding). | |
| void | csilk_response_end (csilk_ctx_t *c) |
| Finalise a chunked streaming response. | |
| void | csilk_sse_init (csilk_ctx_t *c) |
| Initialise a Server-Sent Events connection. | |
| void | csilk_sse_send (csilk_ctx_t *c, const char *event, const char *data) |
| Send an SSE event (or comment) to the client. | |
| void | csilk_sse_close (csilk_ctx_t *c) |
| Close the SSE connection. | |
| char * | csilk_jwt_generate (csilk_ctx_t *c, cJSON *payload, const char *secret) |
| Generate a signed JWT token (HS256). | |
| cJSON * | csilk_jwt_verify (csilk_ctx_t *c, const char *token, const char *secret) |
| Verify a JWT token and extract its payload. | |
| void | csilk_jwt_middleware (csilk_ctx_t *c, const char *secret) |
| JWT authentication middleware. | |
| void | csilk_gzip_middleware (csilk_ctx_t *c) |
| Gzip response compression middleware. | |
| void | csilk_multipart_parse (csilk_ctx_t *c, csilk_multipart_handler_t handler) |
| Parse a multipart/form-data request body. | |
| csilk_server_t * | csilk_ctx_get_server (csilk_ctx_t *c) |
| Get the server instance associated with the current context. | |
| void | csilk_server_add_hook (csilk_server_t *s, csilk_hook_type_t type, void *handler) |
| Register a lifecycle hook callback. | |
| void | csilk_server_set_crypto_driver (csilk_server_t *server, csilk_crypto_driver_t *driver) |
| Set the global crypto driver for the server. | |
| void | csilk_server_set_cipher_driver (csilk_server_t *server, csilk_cipher_driver_t *driver) |
| Set the cipher driver for symmetric/asymmetric encryption. | |
| void | csilk_ctx_set_storage_driver (csilk_ctx_t *c, csilk_storage_driver_t *driver) |
| Set the storage driver for the context. | |
| void | csilk_ctx_set_crypto_driver (csilk_ctx_t *c, csilk_crypto_driver_t *driver) |
| Set the crypto driver for the context. | |
| void | csilk_ctx_set_cipher_driver (csilk_ctx_t *c, csilk_cipher_driver_t *driver) |
| Set the cipher driver for the context. | |
| csilk_server_t * | csilk_server_new (csilk_router_t *router) |
| Create a new server instance. | |
| int | csilk_server_use (csilk_server_t *server, csilk_handler_t handler) |
| Register global middleware. | |
| void | csilk_server_set_not_found_handler (csilk_server_t *server, csilk_handler_t handler) |
| Set a custom handler for 404 (route-not-found) responses. | |
| void | csilk_server_set_spa_fallback (csilk_server_t *server, const char *doc_root) |
| Enable single-page application (SPA) fallback mode. | |
| void | csilk_server_free (csilk_server_t *server) |
| Destroy the server and release all resources. | |
| void | csilk_server_stop (csilk_server_t *server) |
| Request a graceful server shutdown. | |
| void | csilk_server_get_stats (csilk_server_t *server, int *active_conn, int *pooled_conn) |
| void | csilk_server_set_config (csilk_server_t *server, const csilk_server_config_t *config) |
| Apply server configuration options. | |
| int | csilk_server_set_max_connections (csilk_server_t *server, int max) |
| Set the maximum number of concurrent connections and return the previous limit. | |
| void | csilk_server_set_storage_driver (csilk_server_t *server, csilk_storage_driver_t *driver) |
| Replace the context key-value storage driver. | |
| int | csilk_server_run (csilk_server_t *server, int port) |
| Start the server and enter the libuv event loop. | |
| void | csilk_db_init (void) |
| Initialise the database subsystem. | |
| csilk_db_pool_t * | csilk_db_pool_new (const char *driver_name, const char *dsn) |
| Create a new database connection pool. | |
| void | csilk_db_pool_free (csilk_db_pool_t *pool) |
| Free a database pool and disconnect. | |
| cJSON * | csilk_db_query_json (csilk_db_pool_t *pool, const char *sql) |
| Execute a SELECT query and return the result as a JSON array. | |
| int | csilk_db_exec (csilk_db_pool_t *pool, const char *sql) |
| Execute a statement that returns no result rows. | |
| cJSON * | csilk_db_query_param_json (csilk_db_pool_t *pool, const char *sql, const char **params) |
| Execute a parameterised SELECT query with ? placeholders. | |
| void | csilk_metrics_middleware (csilk_ctx_t *c, const char *arg) |
| Prometheus metrics middleware. | |
| void | csilk_metrics_handler (csilk_ctx_t *c) |
| Prometheus /metrics endpoint handler. | |
| uint64_t | csilk_metrics_get_total_requests (void) |
| uint64_t | csilk_metrics_get_total_duration (void) |
| csilk_mq_t * | csilk_ctx_get_mq (csilk_ctx_t *c) |
| Get the internal MQ instance from the context. | |
| csilk_mq_t * | csilk_server_get_mq (csilk_server_t *server) |
| Get the Message Queue instance attached to a server. | |
| csilk_router_t * | csilk_server_get_router (csilk_server_t *server) |
| Get the router instance attached to a server. | |
| void | csilk_mq_next (csilk_mq_ctx_t *ctx) |
| Pass control to the next middleware or subscriber in the MQ chain. | |
| void | csilk_mq_abort (csilk_mq_ctx_t *ctx) |
| Abort the MQ middleware/subscriber chain. | |
| void | csilk_mq_offload (csilk_mq_ctx_t *ctx, csilk_mq_worker_t worker) |
| Offload message processing to a background thread. | |
| const char * | csilk_mq_get_topic (csilk_mq_ctx_t *ctx) |
| Get the topic of the current message. | |
| const void * | csilk_mq_get_payload (csilk_mq_ctx_t *ctx, size_t *len) |
| Get the payload of the current message. | |
| void | csilk_mq_use (csilk_mq_t *mq, const char *topic, csilk_mq_handler_t middleware) |
| Register MQ middleware for a topic. | |
| void | csilk_mq_subscribe (csilk_mq_t *mq, const char *topic, csilk_mq_handler_t subscriber) |
| Register a subscriber for a topic. | |
| int | csilk_mq_publish (csilk_mq_t *mq, const char *topic, const void *payload, size_t len) |
| Publish a message to a topic. | |
| void | csilk_mq_get_stats (csilk_mq_t *mq, csilk_mq_stats_t *stats) |
| Get current MQ statistics. | |
| char * | csilk_mq_stats_to_json (const csilk_mq_stats_t *stats) |
| Convert MQ statistics to a JSON string. | |
| void | csilk_mq_register_monitor (csilk_mq_t *mq, csilk_ctx_t *c) |
| Register a WebSocket monitor for real-time MQ events. | |
| int | csilk_mq_set_persistence (csilk_mq_t *mq, const char *wal_path) |
| Enable Write-Ahead Log (WAL) persistence for the MQ. | |
WebSocket Room Management (MQ-based) | |
High-concurrency room broadcasting system leveraging the Message Queue. | |
| void | csilk_ws_join_room (csilk_ctx_t *c, const char *room_name) |
| Join a WebSocket client to a room. | |
| void | csilk_ws_leave_room (csilk_ctx_t *c, const char *room_name) |
| Remove a WebSocket client from a room. | |
| void | csilk_ws_broadcast_room (csilk_ctx_t *c, const char *room_name, const char *message) |
| Broadcast a message to all WebSockets in a room via MQ. | |
Variables | |
| void(*)(csilk_ctx_t *c, const uint8_t *payload, size_t len, int opcode) | csilk_get_on_ws_message (csilk_ctx_t *c) |
| Get the currently registered WebSocket message callback. | |
High-performance C web framework — main public API header.
Defines all public types, enums, macros, and function declarations for the csilk HTTP web framework, including the request context, router, server, middleware, WebSocket, SSE, and utility APIs. Inspired by Gin (Golang).
| struct csilk_header_t |
A single HTTP header stored as a node in a chained hash table.
Key and value are NUL-terminated strings allocated from the request arena. The next pointer forms a singly-linked list for hash-collision chains.
| struct csilk_header_map_t |
A fixed-size chained hash table for HTTP headers.
Uses CSILK_HEADER_BUCKETS buckets; each bucket holds a singly-linked list of csilk_header_t nodes. Used for both request and response headers, query parameters, and form fields.

| Data Fields | ||
|---|---|---|
| csilk_header_t * | buckets[CSILK_HEADER_BUCKETS] |
Bucket array; each entry points to the head of a collision chain (or NULL). |
| struct csilk_request_t |
Parsed HTTP request.
Populated by the HTTP parser before handlers are invoked. All string fields point into arena-allocated memory that stays valid until csilk_ctx_cleanup.

| Data Fields | ||
|---|---|---|
| char * | body |
Raw request body bytes, or NULL for requests without a body. |
| size_t | body_len |
Number of bytes in |
| csilk_header_map_t | form_params |
Hash map of parsed application/x-www-form-urlencoded fields (populated by csilk_parse_form_urlencoded). |
| csilk_header_map_t | headers |
Hash map of request headers (keys lowercased for case-insensitive lookup). |
| char * | method |
HTTP method verb (e.g., "GET", "POST", "DELETE"). |
| char * | path |
Decoded URL path (percent-encoding removed, query string stripped). |
| csilk_header_map_t | query_params |
Hash map of parsed query-string parameters. |
| struct csilk_response_t |
Mutable HTTP response.
Handlers write their response into this struct. The framework serialises it after the handler chain completes (or when csilk_response_end is called for streaming responses).

| Data Fields | ||
|---|---|---|
| const char * | body |
Response body content. If |
| int | body_is_managed |
Non-zero if |
| size_t | body_len |
Byte length of |
| csilk_header_map_t | headers |
Hash map of response headers to send. |
| int | status |
HTTP status code (e.g., 200, 404, 500). Defaults to 200. |
| struct csilk_param_t |
A single URL path parameter extracted from a route pattern.
For a route like /users/:id/posts/:post_id, two csilk_param_t entries are generated: {"id", actual_id} and {"post_id", actual_post_id}.
| Data Fields | ||
|---|---|---|
| char * | key |
Parameter name as defined in the route pattern (e.g., "id"). |
| char * | value |
Actual decoded value from the request URL. |
| struct csilk_log_config_t |
Logger initialisation configuration.
Controls log output destination, formatting, level filtering, and rotation. Passed by value (not pointer) to csilk_log_init.
| Data Fields | ||
|---|---|---|
| const char * | file_path |
Path to the log file, or NULL to log to stderr. |
| int | json_format |
When non-zero, emit newline-delimited JSON records instead of human-readable lines. |
| csilk_log_level_t | level |
Minimum level to emit (messages below this are filtered out). |
| size_t | max_file_size |
Maximum file size in bytes before rotation (0 = rotation disabled). Requires |
| int | use_colors |
Enable ANSI colour escape codes: 1 = on, 0 = off, -1 = auto-detect (default). |
| struct csilk_cors_config_t |
CORS middleware configuration.
Maps directly to the Access-Control-* response headers. Strings are used as-is — the caller must ensure they remain valid for the lifetime of the middleware.
| struct csilk_security_stats_t |
| struct csilk_process_stats_t |
| struct csilk_server_config_t |
Low-level server configuration options.
Controls timeouts, resource limits, TCP tuning, and TLS settings. A zero-initialised struct provides safe defaults for most fields. Apply via csilk_server_set_config before calling csilk_server_run.
| struct csilk_config_t |
Top-level application configuration.
Unifies server, logger, middleware, and feature-flag settings. Typically populated from a YAML file via csilk_load_config.

| Data Fields | ||
|---|---|---|
| struct csilk_config_t | ai |
AI integration settings. |
| struct csilk_config_t.ai | ai |
AI integration settings. |
| struct csilk_config_t | cipher |
Cipher/cryptography settings. |
| struct csilk_config_t.cipher | cipher |
Cipher/cryptography settings. |
| struct csilk_config_t | cors |
Cross-Origin Resource Sharing settings. |
| struct csilk_config_t.cors | cors |
Cross-Origin Resource Sharing settings. |
| csilk_log_config_t | logger |
Logger initialisation settings. |
| struct csilk_config_t | middleware |
Built-in middleware toggles. |
| struct csilk_config_t.middleware | middleware |
Built-in middleware toggles. |
| int | port |
TCP port the server listens on. |
| struct csilk_config_t | rate_limit |
Per-IP rate limiting settings. |
| struct csilk_config_t.rate_limit | rate_limit |
Per-IP rate limiting settings. |
| csilk_server_config_t | server |
Low-level server/connection settings. |
| struct csilk_config_t | static_files |
Static file server settings. |
| struct csilk_config_t.static_files | static_files |
Static file server settings. |
| struct csilk_valid_rule_t |
A single validation rule for request parameter checking.
Rules are collected into a NULL-terminated array and passed to csilk_validate. Each rule specifies constraints for one field.
| struct csilk_router_t |
The main HTTP router.
Wraps a radix-tree root node and provides methods to register routes, match incoming requests, and generate OpenAPI specs. Routing is based on a compressed radix tree (Patricia trie) for O(k) path matching where k is the URL path length. Dynamic segments (:param) and wildcards (*param) are supported.
Wraps a radix-tree root node and provides methods to register routes, match incoming requests, and generate OpenAPI specs.
| Data Fields | ||
|---|---|---|
| csilk_router_node_t * | root |
Root node of the radix (Patricia) trie. |
| struct csilk_multipart_part_t |
A single part parsed from a multipart/form-data request body.
Contains the field name, optional filename (for file uploads), content type, and the binary data. Strings are NUL-terminated fixed-size buffers; data longer than the buffer is truncated.
| struct csilk_mq_stats_t |
Message Queue statistics.
| struct csilk_config_t.cors |
| Data Fields | ||
|---|---|---|
| csilk_cors_config_t | config |
CORS header values when enabled. |
| csilk_cors_config_t | config |
CORS header values when enabled. |
| int | enable |
Non-zero to install the CORS middleware. |
| int | enable |
Non-zero to install the CORS middleware. |
| struct csilk_config_t.rate_limit |
| struct csilk_config_t.static_files |
| struct csilk_config_t.middleware |
| struct csilk_config_t.ai |
| struct csilk_config_t.cipher |
| #define csilk_bind | ( | c, | |
| type, | |||
| ptr | |||
| ) | csilk_bind_reflect(c, #type, ptr) |
Convenience macro for binding JSON body to a reflected struct. Wraps csilk_bind_reflect, automatically stringifying the type name.
| c | The request context. |
| type | The struct type (used with #type to get the name). |
| ptr | Pointer to the struct instance. |
| #define csilk_DELETE | ( | group, | |
| path, | |||
| handler | |||
| ) | csilk_group_add_route(group, "DELETE", path, handler) |
Register a DELETE route on the group.
| #define csilk_GET | ( | group, | |
| path, | |||
| handler | |||
| ) | csilk_group_add_route(group, "GET", path, handler) |
Register a GET route on the group.
| #define csilk_HEAD | ( | group, | |
| path, | |||
| handler | |||
| ) | csilk_group_add_route(group, "HEAD", path, handler) |
Register a HEAD route on the group.
| #define CSILK_HEADER_BUCKETS 64 |
Number of buckets in the header chained hash table.
Larger values reduce collision chains at the cost of a small amount of per-map memory. Override at compile-time with -DCSILK_HEADER_BUCKETS=N.
| #define csilk_json_t | ( | c, | |
| status, | |||
| type, | |||
| ptr | |||
| ) | csilk_json_reflect(c, status, #type, ptr) |
Convenience macro for sending a reflected struct as JSON response. Wraps csilk_json_reflect, automatically stringifying the type name.
| c | The request context. |
| status | HTTP status code. |
| type | The struct type (used with #type to get the name). |
| ptr | Pointer to the struct instance. |
| #define CSILK_LOG_D | ( | ... | ) | _csilk_log_internal(CSILK_LOG_DEBUG, __FILE__, __LINE__, __func__, __VA_ARGS__) |
Log a DEBUG-level message.
| #define CSILK_LOG_E | ( | ... | ) | _csilk_log_internal(CSILK_LOG_ERROR, __FILE__, __LINE__, __func__, __VA_ARGS__) |
Log an ERROR-level message.
| #define CSILK_LOG_F | ( | ... | ) | _csilk_log_internal(CSILK_LOG_FATAL, __FILE__, __LINE__, __func__, __VA_ARGS__) |
Log a FATAL-level message.
| #define CSILK_LOG_I | ( | ... | ) | _csilk_log_internal(CSILK_LOG_INFO, __FILE__, __LINE__, __func__, __VA_ARGS__) |
Log an INFO-level message.
| #define CSILK_LOG_STRUCT | ( | level, | |
| extra, | |||
| ... | |||
| ) | _csilk_log_structured(level, __FILE__, __LINE__, __func__, extra, __VA_ARGS__) |
Log a structured JSON message (only meaningful when json_format is on).
| level | Log level. |
| extra | cJSON* with extra fields (can be NULL). |
| ... | printf-style format and args for the message string. |
| #define CSILK_LOG_T | ( | ... | ) | _csilk_log_internal(CSILK_LOG_TRACE, __FILE__, __LINE__, __func__, __VA_ARGS__) |
Log a TRACE-level message.
| #define CSILK_LOG_W | ( | ... | ) | _csilk_log_internal(CSILK_LOG_WARN, __FILE__, __LINE__, __func__, __VA_ARGS__) |
Log a WARN-level message.
| #define CSILK_MAX_PARAMS 20 |
Maximum number of URL path parameters that can be extracted from a single request. Parameters beyond this limit are silently ignored. Tune if your routes contain more than 20 dynamic segments.
| #define CSILK_MAX_STORAGE 64 |
Maximum number of items that can be stored in the context key-value storage.
This limit prevents uncontrolled memory consumption in the request arena by preventing a single request from setting an excessive number of keys.
| #define csilk_OPTIONS | ( | group, | |
| path, | |||
| handler | |||
| ) | csilk_group_add_route(group, "OPTIONS", path, handler) |
Register an OPTIONS route on the group.
| #define csilk_PATCH | ( | group, | |
| path, | |||
| handler | |||
| ) | csilk_group_add_route(group, "PATCH", path, handler) |
Register a PATCH route on the group.
| #define csilk_POST | ( | group, | |
| path, | |||
| handler | |||
| ) | csilk_group_add_route(group, "POST", path, handler) |
Register a POST route on the group.
| #define csilk_PUT | ( | group, | |
| path, | |||
| handler | |||
| ) | csilk_group_add_route(group, "PUT", path, handler) |
Register a PUT route on the group.
| #define CSILK_ROUTE | ( | r, | |
| method, | |||
| path, | |||
| handlers, | |||
| handler_count, | |||
| input_type, | |||
| output_type, | |||
| summary, | |||
| desc | |||
| ) |
Convenience macro to register a route with metadata.
Automatically passes path as both the URL pattern and the documentation path pattern. Wraps csilk_router_add_extended.
| #define CSILK_STATUS_BAD_GATEWAY 502 |
| #define CSILK_STATUS_BAD_REQUEST 400 |
| #define CSILK_STATUS_CONFLICT 409 |
| #define CSILK_STATUS_CONTINUE 100 |
| #define CSILK_STATUS_CREATED 201 |
| #define CSILK_STATUS_FORBIDDEN 403 |
| #define CSILK_STATUS_FOUND 302 |
| #define CSILK_STATUS_GATEWAY_TIMEOUT 504 |
| #define CSILK_STATUS_GONE 410 |
| #define CSILK_STATUS_INTERNAL_SERVER_ERROR 500 |
| #define CSILK_STATUS_METHOD_NOT_ALLOWED 405 |
| #define CSILK_STATUS_MOVED_PERMANENTLY 301 |
| #define CSILK_STATUS_NO_CONTENT 204 |
| #define CSILK_STATUS_NOT_FOUND 404 |
| #define CSILK_STATUS_NOT_IMPLEMENTED 501 |
| #define CSILK_STATUS_NOT_MODIFIED 304 |
| #define CSILK_STATUS_OK 200 |
| #define CSILK_STATUS_PARTIAL_CONTENT 206 |
| #define CSILK_STATUS_PAYLOAD_TOO_LARGE 413 |
| #define CSILK_STATUS_PAYMENT_REQUIRED 402 |
| #define CSILK_STATUS_RANGE_NOT_SATISFIABLE 416 |
| #define CSILK_STATUS_REQUEST_TIMEOUT 408 |
| #define CSILK_STATUS_SERVICE_UNAVAILABLE 503 |
| #define CSILK_STATUS_SWITCHING_PROTOCOLS 101 |
| #define CSILK_STATUS_TEMPORARY_REDIRECT 307 |
| #define CSILK_STATUS_TOO_MANY_REQUESTS 429 |
| #define CSILK_STATUS_UNAUTHORIZED 401 |
| #define CSILK_STATUS_UNSUPPORTED_MEDIA_TYPE 415 |
| #define CSILK_STATUS_URI_TOO_LONG 414 |
| #define CSILK_VALID_EMAIL (1 << 3) |
Value must match a basic email format (contains '@' and a \ dot).
| #define CSILK_VALID_INT (1 << 1) |
Value must parse as a valid integer.
| #define CSILK_VALID_REQUIRED (1 << 0) |
Field must be present (non-NULL, non-empty).
| #define CSILK_VALID_STRING (1 << 2) |
Value must be a string (always true for form/query values; \ included for symmetry).
| #define CSILK_VERSION "0.2.3" |
Csilk framework version string (MAJOR.MINOR.PATCH). Used for identification in logs, headers, and the OpenAPI spec.
| typedef struct csilk_arena_s csilk_arena_t |
Opaque arena allocator type.
Provides bump-allocation semantics: memory is allocated in large chunks and individual allocations are never freed — the entire arena is reset or freed at once. Ideal for request-scoped allocations because it is faster than malloc/free and produces zero fragmentation.
| typedef int(* csilk_auth_validator_t) (const char *token) |
Authentication validator callback.
Receives the token extracted from the Authorization header and returns non-zero if the token is valid.
| token | The bearer token string extracted from the request. |
| typedef void(* csilk_ctx_hook_handler_t) (csilk_ctx_t *c) |
Callback signature for request/connection-level hooks.
| c | The request context. |
| typedef struct csilk_db_pool_s csilk_db_pool_t |
| typedef void(* csilk_handler_t) (csilk_ctx_t *c) |
Function pointer for route handlers and middleware.
Every handler receives the per-request context and operates on it (reading request data, setting response data, calling csilk_next to pass control to the next handler in the chain, etc.).
| c | The per-request context. |
| typedef void(* csilk_mq_handler_t) (csilk_mq_ctx_t *ctx) |
MQ handler signature for middleware and subscribers.
| ctx | MQ context providing topic, payload, and chain control. |
| typedef void(* csilk_mq_worker_t) (const char *topic, const void *payload, size_t len) |
Signature for a background MQ worker function.
| topic | The topic string (valid only during the call). |
| payload | Opaque data pointer. |
| len | Byte length of payload. |
| typedef void(* csilk_multipart_handler_t) (csilk_multipart_part_t *part) |
Callback invoked for each part during multipart parsing.
| part | The parsed part. The data pointer is valid only during the callback invocation — do not store the pointer for later use (copy the data if needed). |
| typedef void(* csilk_server_hook_handler_t) (csilk_server_t *s) |
Callback signature for server-level hooks.
| s | The server instance. |
| enum csilk_hook_type_t |
Lifecycle hook types for the server and individual requests.
Hooks allow users to inject custom logic at well-defined points in the server and request lifecycle without modifying the framework code.
| enum csilk_log_level_t |
Log severity levels.
Levels are ordered: messages at or above the configured minimum level are emitted. CSILK_LOG_FATAL terminates the process after logging.
| void _csilk_log_internal | ( | csilk_log_level_t | lv, |
| const char * | file, | ||
| int | line, | ||
| const char * | func, | ||
| const char * | fmt, | ||
| ... | |||
| ) |
Internal log function (use macros instead).
| lv | Log severity level. |
| file | Source file name (FILE). |
| line | Source line number (LINE). |
| func | Function name (func). |
| fmt | Printf-style format string. |
| ... | Format arguments. |
Internal log function (use macros instead).
Formats the variadic message via vsnprintf, acquires the logger mutex, checks file rotation (if file logging and max_file_size exceeded), and writes the entry as either JSON or plain text depending on configuration.
| lv | Log severity level (filtered against g_logger.config.level). |
| file | Source file name (provided by CSILK_LOG_* macro). |
| line | Source line number (provided by CSILK_LOG_* macro). |
| func | Function name (provided by CSILK_LOG_* macro). |
| fmt | printf-style format string. |
| ... | Variadic arguments for the format string. |
| void _csilk_log_structured | ( | csilk_log_level_t | lv, |
| const char * | file, | ||
| int | line, | ||
| const char * | func, | ||
| cJSON * | extra, | ||
| const char * | fmt, | ||
| ... | |||
| ) |
Log a structured JSON message with extra key-value fields.
Produces a JSON log line with the standard fields (time/level/file/line/func/msg) plus any fields in extra. If json_format is off this behaves like a normal log line (extra fields are ignored).
| lv | Log severity level. |
| file | Source file name (FILE). |
| line | Source line number (LINE). |
| func | Function name (func). |
| extra | cJSON object with extra structured fields (can be NULL). Ownership is taken — do not use after the call. |
| fmt | Printf-style format string for the log message. |
| ... | Format arguments. |
Log a structured JSON message with extra key-value fields.
Like _csilk_log_internal() but accepts an additional cJSON object of extra fields. In JSON mode, the extra fields are merged into the output. In text mode, the extra fields are discarded (cJSON_Delete is called).
| lv | Log severity level. |
| file | Source file name. |
| line | Source line number. |
| func | Function name. |
| extra | cJSON object of extra fields to include (ownership taken). |
| fmt | printf-style format string. |
| ... | Variadic arguments. |
| void csilk_abort | ( | csilk_ctx_t * | c | ) |
Immediately abort the handler chain.
No further handlers or middleware run (except code after csilk_next in the current handler that checks csilk_is_aborted). The response accumulated so far is sent to the client.
| c | The request context. |
Immediately abort the handler chain.
Sets the aborted flag on the context. Subsequent calls to csilk_next() are ignored. The response is still sent once the current handler returns.
| c | The request context. |
| void csilk_add_header | ( | csilk_ctx_t * | c, |
| const char * | key, | ||
| const char * | value | ||
| ) |
Append a response header, preserving any existing value(s).
Unlike csilk_set_header, this adds another entry rather than replacing the existing one. Useful for headers like Set-Cookie that may appear multiple times.
| c | The request context. |
| key | The header field name. |
| value | The header field value to append. |
Append a response header, preserving any existing value(s).
Unlike csilk_set_header(), this function prepends a new header node without removing any existing values for the same key. This is useful for headers like Set-Cookie where multiple values are allowed.
| c | The request context. |
| key | Header key. |
| value | Header value. |
| void * csilk_arena_alloc | ( | csilk_arena_t * | arena, |
| size_t | size | ||
| ) |
Allocate zero-initialised memory from an arena.
The returned memory is valid until csilk_arena_free, csilk_arena_reset, or csilk_ctx_cleanup. No individual free() is required.
| arena | The arena allocator. |
| size | Number of bytes to allocate. |
Allocate zero-initialised memory from an arena.
Returns memory from the current chunk if there is room; otherwise allocates a new chunk large enough to satisfy the request. The returned memory is zero-initialized only by virtue of being freshly allocated from the OS.
| arena | The arena allocator (must not be NULL). |
| size | Number of bytes to allocate. The actual allocation is rounded up to the nearest multiple of 8 for alignment. |
| void csilk_arena_free | ( | csilk_arena_t * | arena | ) |
Free all memory chunks owned by the arena.
After this call the arena pointer is invalid and must not be used again.
| arena | The arena allocator to destroy. |
Free all memory chunks owned by the arena.
Walks the linked list of chunks, frees each one, then frees the arena header. After this call the arena pointer is invalid and must not be used.
| arena | The arena to destroy (may be NULL). |
| void csilk_arena_get_stats | ( | csilk_arena_t * | arena, |
| size_t * | total_size, | ||
| size_t * | total_used | ||
| ) |
Get total allocated size and used bytes in the arena.
Walks the chunk list and sums the total allocated size and total used bytes.
| arena | The arena to query (must not be NULL). | |
| [out] | total_size | Pointer to receive the total allocated size in bytes. |
| [out] | total_used | Pointer to receive the total used bytes in the arena. |
| csilk_arena_t * csilk_arena_new | ( | size_t | default_chunk_size | ) |
Create a new arena allocator.
The arena allocates memory in fixed-size chunks and hands out bump-allocated blocks. When the current chunk is exhausted a new one is allocated.
| default_chunk_size | Initial chunk size in bytes. Pass 0 for a sensible default (typically 4–8 KB). |
Allocates and initializes an arena memory manager. The arena allocates memory in chunks of at least default_chunk_size bytes. Individual allocations within the arena are never freed separately; instead, all memory is reclaimed at once by calling csilk_arena_free() or csilk_arena_reset().
| default_chunk_size | Minimum size in bytes for each new chunk. Pass 0 to let the implementation choose a default. |
| void csilk_arena_reset | ( | csilk_arena_t * | arena | ) |
Reset the arena without freeing its chunks.
The arena can be reused after a reset — subsequent allocations reuse the existing chunk memory. Useful for pooling arenas across requests to reduce malloc pressure.
| arena | The arena allocator to reset. |
Reset the arena without freeing its chunks.
Sets the used counter to zero on every chunk in the chain, making all arena memory available for new allocations. No system calls (malloc/free) are performed, making this much cheaper than csilk_arena_free() + _new().
| arena | The arena to reset (may be NULL). |
| char * csilk_arena_strdup | ( | csilk_arena_t * | arena, |
| const char * | s | ||
| ) |
Duplicate a NUL-terminated string using the arena allocator.
| arena | The arena allocator. |
| s | Source string to duplicate. Must be NUL-terminated. |
s allocated from arena, or NULL on allocation failure. If s is NULL the behaviour is undefined.Duplicate a NUL-terminated string using the arena allocator.
Allocates enough arena memory for a copy of s, including the null terminator, and copies the string contents.
| arena | The arena allocator. |
| s | Source string to duplicate. |
s is NULL or on allocation failure. | char * csilk_arena_strndup | ( | csilk_arena_t * | arena, |
| const char * | s, | ||
| size_t | n | ||
| ) |
Duplicate n bytes of a string using the arena allocator.
| arena | The arena allocator. |
| s | Source string to duplicate. |
| n | Number of bytes to copy. |
n bytes of s allocated from arena, or NULL on allocation failure. If s is NULL the behaviour is undefined.Allocates n + 1 bytes of arena memory, copies n bytes from s, and adds a null terminator.
| arena | The arena allocator. |
| s | Source string to duplicate. |
| n | Number of bytes to copy. |
s is NULL or on allocation failure. | void csilk_auth_middleware | ( | csilk_ctx_t * | c, |
| csilk_auth_validator_t | validator | ||
| ) |
Simple token-based authentication middleware.
Extracts the Bearer token from the Authorization header, passes it to validator, and aborts the chain with 401 if validation fails.
| c | The request context. |
| validator | Callback that inspects the token and returns 1 for valid, 0 for invalid. Called synchronously on the event-loop thread. |
Simple token-based authentication middleware.
Extracts the Bearer token from the Authorization header and validates it using the caller-provided validator callback. If validation fails, a 401 Unauthorized response is sent with a WWW-Authenticate header, and the request pipeline is aborted.
| c | The request context. |
| validator | Callback that receives the token string and returns non-zero if the token is valid, zero otherwise. |
| cJSON * csilk_bind_json | ( | csilk_ctx_t * | c | ) |
Bind the request body (JSON) to a cJSON object.
Parses the raw request body as JSON. The returned cJSON object is heap-allocated and must be freed by the caller with cJSON_Delete.
| c | The request context. |
Bind the request body (JSON) to a cJSON object.
| c | The request context. |
| cJSON * csilk_bind_json_err | ( | csilk_ctx_t * | c, |
| const char ** | error | ||
| ) |
Bind request body to cJSON with a descriptive error message.
Like csilk_bind_json, but sets error to a static string describing why parsing failed.
| c | The request context. | |
| [out] | error | Pointer to receive a static error string (do NOT free). Unchanged on success. |
error is set).Bind request body to cJSON with a descriptive error message.
Like csilk_bind_json() but sets error to a descriptive string on failure (e.g., "Null context", "No request body", or the cJSON parse error position).
| c | The request context. |
| error | [out] Optional pointer to receive a static error string. |
error string is a static pointer (do not free). | int csilk_bind_reflect | ( | csilk_ctx_t * | c, |
| const char * | type_name, | ||
| void * | ptr | ||
| ) |
Parse the JSON request body into a struct registered via reflection.
Combines csilk_bind_json_err and csilk_json_unmarshal into one call. The struct at ptr must have been registered with CSILK_REGISTER_REFLECT or csilk_reflect_register.
| c | The request context. | |
| type_name | Registered type name string (must match the name used in csilk_reflect_register). | |
| [out] | ptr | Pointer to the struct instance to populate. |
Parse the JSON request body into a struct registered via reflection.
Deserializes the JSON request body into the provided struct pointer using the csilk reflection engine. If type_name is NULL, the type is inferred from the current handler's input_type metadata (if available).
| c | The request context. |
| type_name | Registered type name (e.g., "my_request_t"), or NULL to infer from the route handler's metadata. |
| ptr | Pointer to the target struct to populate. |
| void csilk_config_free | ( | csilk_config_t * | config | ) |
Free all heap-allocated strings inside a configuration.
Does NOT free the csilk_config_t struct itself (only its members). Safe to call on a zero-initialised struct.
| config | Pointer to the configuration struct whose fields should be freed. |
Free all heap-allocated strings inside a configuration.
Releases memory for logger.file_path, cors allow_origin/methods/headers, static_files root_dir/prefix, and middleware.auth_token. Each pointer is set to NULL after being freed, making repeated calls safe.
| config | Configuration structure whose strings will be freed. |
| int csilk_config_validate | ( | const csilk_config_t * | config, |
| const char ** | error_msg | ||
| ) |
Validate configuration values for semantic correctness.
Checks for out-of-range ports, conflicting settings, missing required paths, etc.
| config | Pointer to the configuration to validate. | |
| [out] | error_msg | Optional pointer to receive a static error string (do NOT free). Unchanged on success. |
error_msg is set).Checks that port is in range [1, 65535], timeouts are non-negative, max_body_size and max_header_size are positive, listen_backlog and worker_threads are >= 1, and that optional features (rate_limit, static_files, auth middleware) have their required sub-fields set when enabled. Returns the first validation error found.
| config | Configuration to validate. |
| error_msg | [out] Optional pointer to receive a human-readable error string. The error string is a static literal; do not free it. |
| void csilk_cors_middleware | ( | csilk_ctx_t * | c, |
| const csilk_cors_config_t * | config | ||
| ) |
CORS middleware — handles preflight and adds CORS headers.
Must be called as a route or group middleware. For preflight OPTIONS requests the middleware sends the appropriate headers and aborts the chain (status 204). For other requests the CORS headers are added and the chain continues.
| c | The request context. |
| config | CORS settings. Must remain valid for the call duration. |
CORS middleware — handles preflight and adds CORS headers.
Applies the configured Access-Control-* headers to every response. When the Vary: Origin header is set for non-wildcard origins. If the incoming request is an OPTIONS preflight (indicated by Access-Control-Request-Method), the middleware short-circuits with a 204 No Content response instead of forwarding to downstream handlers.
| c | The request context. |
| config | Pointer to a CORS configuration struct specifying allowed origins, methods, headers, credentials, and max-age. Must remain valid for the duration of the call. |
| int csilk_csrf_generate_token | ( | char * | buf, |
| size_t | buf_size | ||
| ) |
Generate a cryptographically random CSRF token.
Produces a hex-encoded 32-byte (256-bit) random token.
| [out] | buf | Output buffer. Must be at least 33 bytes for the 64-character hex string plus NUL terminator. |
| buf_size | Size of buf in bytes. |
buf_size is too small or the RNG fails.Reads 16 bytes from /dev/urandom and formats them as a 32-character hex string (plus null terminator). If /dev/urandom cannot be opened, falls back to a weak PRNG seeded with time XOR pid.
| buf | Output buffer to receive the null-terminated hex token. |
| buf_size | Size of the output buffer. Must be at least 33 bytes. |
| void csilk_csrf_middleware | ( | csilk_ctx_t * | c | ) |
Stateless CSRF protection middleware.
Checks for a valid CSRF token in the request (via header or form field) on state-changing methods (POST, PUT, DELETE, PATCH). If the token is missing or invalid the chain is aborted with 403 Forbidden.
| c | The request context. |
Stateless CSRF protection middleware.
On safe HTTP methods (GET, HEAD, OPTIONS), the middleware ensures a CSRF cookie called "csrf_token" is present (generating one if missing) and proceeds to the next handler.
On state-changing methods (POST, PUT, DELETE, etc.), it validates the X-CSRF-Token request header against the csrf_token cookie. If the tokens do not match or the header is absent, a 403 Forbidden response is returned and the pipeline is aborted.
| c | The request context. |
| void csilk_ctx_cleanup | ( | csilk_ctx_t * | c | ) |
Release all memory and resources associated with a request context.
Frees the arena allocator, destroys header hash tables, and resets the context struct. Called automatically by the framework after the response is sent. Not intended for direct use in user code.
| c | The request context to clean up. |
Release all memory and resources associated with a request context.
Resets the arena allocator for reuse, frees URL path parameters, request body, and path strings. Clears all header maps (request, response, query, form). Cleans up storage items and resets all state flags for the next request. Called after each HTTP request is fully processed.
| c | The request context. |
| const char * csilk_ctx_get_handler_path | ( | csilk_ctx_t * | c | ) |
Get the route pattern for the matched handler (e.g., "/users/:id").
| c | The request context. |
Get the route pattern for the matched handler (e.g., "/users/:id").
| c | The request context. |
| const char * csilk_ctx_get_handler_perm_required | ( | csilk_ctx_t * | c | ) |
Get the permission string required by the matched handler.
| c | The request context. |
Get the permission string required by the matched handler.
| c | The request context. |
| const char * csilk_ctx_get_handler_perm_resource | ( | csilk_ctx_t * | c | ) |
Get the resource pattern for the matched handler's permission check.
| c | The request context. |
Get the resource pattern for the matched handler's permission check.
| c | The request context. |
| csilk_mq_t * csilk_ctx_get_mq | ( | csilk_ctx_t * | c | ) |
Get the internal MQ instance from the context.
| c | The request context. |
| csilk_server_t * csilk_ctx_get_server | ( | csilk_ctx_t * | c | ) |
Get the server instance associated with the current context.
| c | The request context. |
Get the server instance associated with the current context.
| c | The request context. |
| void csilk_ctx_set_cipher_driver | ( | csilk_ctx_t * | c, |
| csilk_cipher_driver_t * | driver | ||
| ) |
Set the cipher driver for the context.
| c | The request context. |
| driver | The cipher driver vtable. |
Set the cipher driver for the context.
| c | The request context. |
| driver | Pointer to driver vtable. |
| void csilk_ctx_set_crypto_driver | ( | csilk_ctx_t * | c, |
| csilk_crypto_driver_t * | driver | ||
| ) |
Set the crypto driver for the context.
| c | The request context. |
| driver | The crypto driver vtable. |
Set the crypto driver for the context.
| c | The request context. |
| driver | Pointer to driver vtable. |
| void csilk_ctx_set_storage_driver | ( | csilk_ctx_t * | c, |
| csilk_storage_driver_t * | driver | ||
| ) |
Set the storage driver for the context.
| c | The request context. |
| driver | The storage driver vtable. |
Set the storage driver for the context.
| c | The request context. |
| driver | Pointer to driver vtable. |
| int csilk_db_exec | ( | csilk_db_pool_t * | pool, |
| const char * | sql | ||
| ) |
Execute a statement that returns no result rows.
Suitable for INSERT, UPDATE, DELETE, CREATE TABLE, etc.
| pool | Connection pool. |
| sql | SQL statement. |
Execute a statement that returns no result rows.
| void csilk_db_init | ( | void | ) |
Initialise the database subsystem.
Registers built-in drivers (SQLite3, etc.). Must be called once before any csilk_db_pool_new call. Safe to call multiple times.
Registers all built-in drivers (SQLite3, MySQL, PostgreSQL, etc.). Must be called once before any csilk_db_pool_new call. Safe to call multiple times.
| void csilk_db_pool_free | ( | csilk_db_pool_t * | pool | ) |
Free a database pool and disconnect.
Closes the underlying connection and frees the pool struct.
| pool | The pool to free. Must not be NULL. |
Free a database pool and disconnect.
The driver's free_result is not called here — any outstanding results must have been freed by the caller.
| csilk_db_pool_t * csilk_db_pool_new | ( | const char * | driver_name, |
| const char * | dsn | ||
| ) |
Create a new database connection pool.
The pool maintains a single connection (or opens a new one on demand). All database operations go through the pool, which provides mutex-based thread safety.
| driver_name | Driver identifier (e.g., "sqlite"). Must have been registered via csilk_db_register_driver or the built-in init. |
| dsn | Data source name (driver-specific, e.g., "file:test.db"). |
Create a new database connection pool.
The pool holds exactly ONE connection (mutex-serialized access). This is intentional — the caller is expected to manage a pool of pools if concurrency is needed.
| driver_name | Registered driver name (e.g., "sqlite3"). |
| dsn | Data source name (e.g., "/tmp/test.db" or "host=..."). |
| cJSON * csilk_db_query_json | ( | csilk_db_pool_t * | pool, |
| const char * | sql | ||
| ) |
Execute a SELECT query and return the result as a JSON array.
Each row becomes a JSON object keyed by column name.
| pool | Connection pool. |
| sql | SQL SELECT statement. |
Execute a SELECT query and return the result as a JSON array.
| cJSON * csilk_db_query_param_json | ( | csilk_db_pool_t * | pool, |
| const char * | sql, | ||
| const char ** | params | ||
| ) |
Execute a parameterised SELECT query with ? placeholders.
Each ? in sql is replaced with the corresponding value from params (The driver handles escaping internally). The result is returned as a JSON array.
| pool | Connection pool. |
| sql | SQL with ? placeholders. |
| params | NULL-terminated array of string values for the placeholders. The array must end with a NULL sentinel. |
Execute a parameterised SELECT query with ? placeholders.
This is naive string substitution — NOT prepared-statement binding. Parameter values are NOT escaped for SQL special characters. A parameter containing "' OR '1'='1" will inject into the SQL verbatim.
| pool | Database pool. |
| sql | SQL pattern with ? placeholders. |
| params | NULL-terminated array of string values. |
| void csilk_file | ( | csilk_ctx_t * | c, |
| const char * | file_path | ||
| ) |
Serve a specific file from the local filesystem.
Like csilk_static, this function offloads file I/O to a worker thread and uses zero-copy transmission (sendfile).
| c | The request context. |
| file_path | Absolute or relative path to the file. |
Serve a specific file from the local filesystem.
Offloads file open/stat operations to the libuv thread pool. The response is sent via the normal _csilk_send_response() path using zero-copy.
| c | The request context. |
| file_path | Path to the file to serve. |
| cJSON * csilk_generate_openapi_json | ( | csilk_router_t * | router, |
| const char * | title, | ||
| const char * | version, | ||
| const char * | description | ||
| ) |
Generate an OpenAPI 3.0 specification JSON from the router.
Traverses all registered routes and uses the reflection system to build JSON schemas for request bodies and responses. Produces a complete OpenAPI document suitable for use with Swagger UI, Redoc, etc.
| router | The router instance. |
| title | API title for the OpenAPI info block. |
| version | API version for the OpenAPI info block. |
| description | API description (optional — pass NULL to omit). |
Generate an OpenAPI 3.0 specification JSON from the router.
Builds the full OpenAPI JSON structure including:
Path parameters are extracted from the route patterns and converted to OpenAPI format. Request/response schemas are generated from input_type and output_type metadata using the reflection engine.
| router | The router instance containing registered routes. |
| title | API title for the info section (pass NULL for default). |
| version | API version string (pass NULL for default "1.0.0"). |
| description | API description (may be NULL). |
| void * csilk_get | ( | csilk_ctx_t * | c, |
| const char * | key | ||
| ) |
Retrieve an opaque value from the request context.
| c | The request context. |
| key | NUL-terminated key name. |
key was never set (or was explicitly set to NULL — see the note on csilk_set).Retrieve an opaque value from the request context.
If a storage driver is set on the context, delegates to it. Otherwise, searches the internal linked list for the given key.
| c | The request context. |
| key | Storage key to look up. |
| csilk_arena_t * csilk_get_arena | ( | csilk_ctx_t * | c | ) |
Get the arena allocator associated with the request context.
Use this for all short-lived per-request allocations. Memory is automatically reclaimed in csilk_ctx_cleanup and does not need individual free() calls.
| c | The request context. |
Get the arena allocator associated with the request context.
The arena is request-scoped and created automatically on each new connection. Use it for short-lived allocations that should live for the duration of the request.
| c | The request context. |
| const char * csilk_get_body | ( | csilk_ctx_t * | c, |
| size_t * | out_len | ||
| ) |
Get the raw request body and its length.
Only valid after the full body has been parsed. Returns NULL for methods that have no body (GET, HEAD, etc.) or when the body is empty.
| c | The request context. | |
| [out] | out_len | Optional pointer to receive the body length in bytes. May be NULL if the caller does not need the length. |
Get the raw request body and its length.
| c | The request context. |
| out_len | [out] If non-NULL, receives the body length in bytes. |
| size_t csilk_get_body_len | ( | csilk_ctx_t * | c | ) |
Get the length of the raw request body.
Convenience shortcut for csilk_get_body(c, &len) when only the length is needed.
| c | The request context. |
Get the length of the raw request body.
| c | The request context. |
| const char * csilk_get_client_ip | ( | csilk_ctx_t * | c | ) |
Get the client's IP address.
Checks the X-Forwarded-For / X-Real-IP headers first (if present), then falls back to the socket peer address.
| c | The request context. |
Get the client's IP address.
Resolves the client's IP address (IPv4 or IPv6) from the underlying TCP socket using libuv's getpeername. The result is allocated in arena memory so it is valid for the duration of the request.
| c | The request context. |
| const char * csilk_get_cookie | ( | csilk_ctx_t * | c, |
| const char * | name | ||
| ) |
Get a cookie value by name from the Cookie request header.
Parses the Cookie header on first call and caches the result.
| c | The request context. |
| name | The cookie name. |
Get a cookie value by name from the Cookie request header.
Parses the "Cookie" request header by splitting on "; " and then on "=". Returns the value for the first cookie matching name.
| c | The request context. |
| name | Cookie name to look up. |
| int csilk_get_file_fd | ( | csilk_ctx_t * | c | ) |
Get the current zero-copy file descriptor.
| c | The request context. |
Get the current zero-copy file descriptor.
| c | The request context. |
| const char * csilk_get_form_field | ( | csilk_ctx_t * | c, |
| const char * | key | ||
| ) |
Get a form-urlencoded field value by key.
Only returns meaningful data after csilk_parse_form_urlencoded has been called.
| c | The request context. |
| key | The form field name. |
Get a form-urlencoded field value by key.
Looks up the given key in the request's form_params hash map, populated by a prior call to csilk_parse_form_urlencoded().
| c | The request context. |
| key | Field name to look up. |
| int csilk_get_handler_index | ( | csilk_ctx_t * | c | ) |
Get the index of the currently executing handler in the chain.
| c | The request context. |
Get the index of the currently executing handler in the chain.
| c | The request context. |
| const char * csilk_get_header | ( | csilk_ctx_t * | c, |
| const char * | key | ||
| ) |
Get a request header value by name (case-insensitive).
| c | The request context. |
| key | The header field name (e.g., "Content-Type"). |
Get a request header value by name (case-insensitive).
Searches the request header hash map. Key comparison uses strcasecmp so "Content-Type" and "content-type" are treated as equivalent.
| c | The request context. |
| key | Header key to look up. |
| const char * csilk_get_method | ( | csilk_ctx_t * | c | ) |
Get the HTTP method of the current request.
| c | The request context. |
Returns the method string as parsed by the HTTP parser (e.g., "GET", "POST", "PUT", "DELETE", "PATCH", "HEAD", "OPTIONS").
| c | The request context. |
| const char * csilk_get_param | ( | csilk_ctx_t * | c, |
| const char * | key | ||
| ) |
Get a URL path parameter by key.
Parameters are extracted from the route pattern by the router. For a route /users/:id, csilk_get_param(c, "id") returns the actual value.
| c | The request context. |
| key | The parameter name as defined in the route pattern (e.g., "id"). |
key is not a known parameter. Valid until csilk_ctx_cleanup.Get a URL path parameter by key.
Path parameters are extracted from the URL during routing when the route pattern contains :param segments (e.g., "/users/:id").
| c | The request context. |
| key | Parameter name (as declared in the route pattern without the ':'). |
| const char * csilk_get_param_key | ( | csilk_ctx_t * | c, |
| int | index | ||
| ) |
Get the name of a path parameter by its index.
| c | The request context. |
| index | Index of the parameter (0..count-1). |
Get the name of a path parameter by its index.
| c | The request context. |
| index | Parameter index. |
| const char * csilk_get_param_value | ( | csilk_ctx_t * | c, |
| int | index | ||
| ) |
Get the value of a path parameter by its index.
| c | The request context. |
| index | Index of the parameter (0..count-1). |
Get the value of a path parameter by its index.
| c | The request context. |
| index | Parameter index. |
| int csilk_get_params_count | ( | csilk_ctx_t * | c | ) |
Get the number of path parameters extracted from the URL.
| c | The request context. |
Get the number of path parameters extracted from the URL.
| c | The request context. |
| const char * csilk_get_path | ( | csilk_ctx_t * | c | ) |
Get the decoded URL path of the current request.
The path has percent-encoding removed and the query string stripped.
| c | The request context. |
Get the decoded URL path of the current request.
Returns the decoded URL path (without the query string). For example, a request to "/foo/bar?id=1" yields path "/foo/bar".
| c | The request context. |
| const char * csilk_get_query | ( | csilk_ctx_t * | c, |
| const char * | key | ||
| ) |
Get a query-string parameter by key.
Only works after the request has been fully parsed (always true in handlers). The first value is returned when a key appears multiple times.
| c | The request context. |
| key | The query parameter name. |
Get a query-string parameter by key.
Query parameters are populated by csilk_parse_query() which is called automatically during request finalization. The value is URL-decoded.
| c | The request context. |
| key | Query parameter name. |
| const char * csilk_get_request_id | ( | csilk_ctx_t * | c | ) |
Get the unique identifier for the current request.
The ID is auto-generated (UUID v4) by the csilk_request_id_middleware or by the server if no middleware is installed.
| c | The request context. |
Get the unique identifier for the current request.
Returns the UUID v4 request identifier that was generated when the request was first parsed. The ID is formatted as 8-4-4-4-12 hex digits (37 bytes including null terminator).
| c | The request context. |
| const char * csilk_get_response_body | ( | csilk_ctx_t * | c, |
| size_t * | out_len | ||
| ) |
Get the response body data and optionally its length.
Get the current response body and its length.
| c | The request context. |
| out_len | [out] If non-NULL, receives the response body length. |
| const char * csilk_get_response_header | ( | csilk_ctx_t * | c, |
| const char * | key | ||
| ) |
Get a response header value by name (case-insensitive).
| c | The request context. |
| key | The header field name. |
Get a response header value by name (case-insensitive).
Searches the response header hash map. Header values retrieved here are those that have been set via csilk_set_header() / csilk_add_header().
| c | The request context. |
| key | Header key to look up. |
| int csilk_get_status | ( | csilk_ctx_t * | c | ) |
Get the current response status code.
| c | The request context. |
Get the current response status code.
| c | The request context. |
| uv_work_t * csilk_get_work_req | ( | csilk_ctx_t * | c | ) |
Get the libuv work request associated with the context.
Use this to offload long-running operations to the thread pool while maintaining context state.
| c | The request context. |
Get the libuv work request associated with the context.
| c | The request context. |
| void csilk_group_add_handlers | ( | csilk_group_t * | group, |
| const char * | method, | ||
| const char * | path, | ||
| csilk_handler_t * | handlers, | ||
| size_t | count | ||
| ) |
Add a route with an explicit array of handlers.
Useful when you need to attach multiple middleware + the final handler without calling group_use first.
| group | The route group. |
| method | HTTP method. |
| path | Path relative to the group prefix. |
| handlers | Array of handler function pointers (middleware first, route handler last). Stored by pointer — must outlive the router. |
| count | Number of elements in handlers. |
Add a route with an explicit array of handlers.
The final handler chain stored in the router looks like: [parent_mw..., group_mw..., handler_1, ..., handler_n]
| group | The route group. |
| method | HTTP method. |
| path | Path relative to the group prefix. |
| handlers | Array of handler functions (the chain). |
| count | Number of handlers in the array. |
| void csilk_group_add_route | ( | csilk_group_t * | group, |
| const char * | method, | ||
| const char * | path, | ||
| csilk_handler_t | handler | ||
| ) |
Add a route to the group.
The full URL pattern is the group prefix concatenated with path. The group's middleware is prepended to the handler.
| group | The route group. |
| method | HTTP method. |
| path | Path relative to the group prefix (e.g., "/:id"). |
| handler | The route handler function. |
Add a route to the group.
The route's path is automatically prefixed with the group's prefix. The handler is wrapped in a 1-element array and passed to csilk_group_add_handlers() which combines group middleware.
| group | The route group. |
| method | HTTP method (e.g., "GET", "POST"). |
| path | Path relative to the group prefix (e.g., "/users"). |
| handler | The route handler function. |
| void csilk_group_add_route_extended | ( | csilk_group_t * | group, |
| const char * | method, | ||
| const char * | path, | ||
| csilk_handler_t | handler, | ||
| const char * | input_type, | ||
| const char * | output_type, | ||
| const char * | summary, | ||
| const char * | description | ||
| ) |
Add a route with OpenAPI/reflection metadata to a group.
Extended version that also records input/output types and documentation for automatic OpenAPI spec generation.
| group | The route group. |
| method | HTTP method. |
| path | Path relative to the group prefix. |
| handler | The route handler function. |
| input_type | Registered type name for request-body binding (NULL if none). |
| output_type | Registered type name for response serialisation (NULL if none). |
| summary | Short operation summary for OpenAPI (NULL to omit). |
| description | Detailed operation description for OpenAPI (NULL to omit). |
Add a route with OpenAPI/reflection metadata to a group.
Like csilk_group_add_route() but enriches the route with metadata used by the OpenAPI spec generator. The metadata is stored in the method handler for later retrieval by csilk_generate_openapi_json().
| group | The route group. |
| method | HTTP method. |
| path | Path relative to the group prefix. |
| handler | The route handler function. |
| input_type | Registered reflection type name for the request body (e.g., "CreateUserRequest"), or NULL. |
| output_type | Registered reflection type name for the response body, or NULL. |
| summary | Short description for OpenAPI operation summary. |
| description | Detailed description for OpenAPI operation. |
| void csilk_group_add_route_extended_perm | ( | csilk_group_t * | group, |
| 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 | ||
| ) |
Add a route with OpenAPI/reflection metadata to a group.
Add a route with full OpenAPI metadata and permission requirements to a group.
Extended version that also records input/output types and documentation for automatic OpenAPI spec generation.
| group | The route group. |
| method | HTTP method. |
| path | Path relative to the group prefix. |
| handler | The route handler function. |
| input_type | Registered type name for request-body binding (NULL if none). |
| output_type | Registered type name for response serialisation (NULL if none). |
| summary | Short operation summary for OpenAPI (NULL to omit). |
| description | Detailed operation description for OpenAPI (NULL to omit). |
Add a route with OpenAPI/reflection metadata to a group.
Like csilk_group_add_route() but enriches the route with metadata used by the OpenAPI spec generator. The metadata is stored in the method handler for later retrieval by csilk_generate_openapi_json().
| group | The route group. |
| method | HTTP method. |
| path | Path relative to the group prefix. |
| handler | The route handler function. |
| input_type | Registered reflection type name for the request body (e.g., "CreateUserRequest"), or NULL. |
| output_type | Registered reflection type name for the response body, or NULL. |
| summary | Short description for OpenAPI operation summary. |
| description | Detailed description for OpenAPI operation. |
| perm_required | Permission required for this route, or NULL. |
| perm_resource | Resource pattern for permission check, or NULL. |
Permission metadata is forwarded to the router which stores it alongside the route for authorization middleware to inspect at request time.
| void csilk_group_free | ( | csilk_group_t * | group | ) |
Destroy a route group and release its resources.
Frees the group struct and its prefix string. Does NOT free the associated router or any handler functions.
| group | The group to free. Must not be NULL. |
Destroy a route group and release its resources.
Releases the group's prefix string, middleware handlers array, and the group struct itself. Does NOT free child groups or the router.
| group | The group to free (may be NULL). |
| csilk_group_t * csilk_group_group | ( | csilk_group_t * | parent, |
| const char * | prefix | ||
| ) |
Create a nested sub-group within an existing group.
The sub-group inherits the parent's middleware and its prefix is concatenated.
| parent | The parent group. |
| prefix | Sub-prefix appended to the parent's prefix (e.g., "admin"). |
Create a nested sub-group within an existing group.
The child inherits the parent's router and its prefix is joined with the parent's prefix (e.g., parent="/api", child="/v1" -> combined prefix "/api/v1").
| parent | The parent group (cannot be NULL). |
| prefix | URL prefix for this subgroup (e.g., "/v1"). |
| csilk_group_t * csilk_group_new | ( | csilk_router_t * | router, |
| const char * | prefix | ||
| ) |
Create a new route group with a URL prefix.
Groups allow sharing a common prefix and middleware set across multiple routes (e.g., "/api/v1").
| router | The router to attach the group to. |
| prefix | URL prefix for all routes in this group (e.g., "/api/v1"). |
Create a new route group with a URL prefix.
Root groups are attached directly to a router. All routes added to this group will be prefixed with prefix.
| router | The router instance this group belongs to. |
| prefix | URL prefix for all routes in this group (e.g., "/api/v1"). Pass NULL or "/" for no prefix. |
| void csilk_group_use | ( | csilk_group_t * | group, |
| csilk_handler_t | handler | ||
| ) |
Add middleware to a group.
Middleware is stored in the order it is added and is executed for every route in the group (and any nested sub-groups).
| group | The route group. |
| handler | Middleware function to prepend to all group routes. |
Add middleware to a group.
Middleware handlers are executed before route handlers in the order they are registered. The internal middleware array grows dynamically (doubling capacity) as needed.
| group | The route group. |
| handler | Middleware handler function. Receives the request context and should call csilk_next() to pass control forward. |
| void csilk_gzip_middleware | ( | csilk_ctx_t * | c | ) |
Gzip response compression middleware.
If the client advertises gzip/deflate support (Accept-Encoding header), this middleware compresses the response body transparently. Must be registered as a group-level or server-level middleware that wraps the handler chain.
| c | The request context. |
Gzip response compression middleware.
Calls csilk_next() first, then inspects the response. Compression is skipped if:
When eligible, the response body is made managed (copied if necessary) and compression is offloaded to the libuv thread pool via a work request.
| c | The request context. |
| void csilk_health_check_handler | ( | csilk_ctx_t * | c | ) |
Built-in Health Check handler. Returns a simple JSON response {"status": "up"}.
| c | The request context. |
Built-in Health Check handler. Returns a simple JSON response {"status": "up"}.
Provides a simple "shallow" check to verify that the server's event loop is alive and responsive. Returns a JSON response with status 200 OK.
| c | The request context. If NULL the function returns immediately. |
| int csilk_is_aborted | ( | csilk_ctx_t * | c | ) |
Check whether the handler chain has been aborted.
Handlers can check this after calling csilk_next to see if a downstream handler or middleware called csilk_abort.
| c | The request context. |
Check whether the handler chain has been aborted.
| c | The request context. |
| int csilk_is_async | ( | csilk_ctx_t * | c | ) |
Check whether asynchronous response mode is enabled.
| c | The request context. |
Check whether asynchronous response mode is enabled.
| c | The request context. |
| int csilk_is_sse | ( | csilk_ctx_t * | c | ) |
Check whether the connection is in Server-Sent Events mode.
Returns 1 only after csilk_sse_init has been called successfully.
| c | The request context. |
Check whether the connection is in Server-Sent Events mode.
| c | The request context. |
| int csilk_is_websocket | ( | csilk_ctx_t * | c | ) |
Check whether the connection has been upgraded to WebSocket.
Returns 1 only after a successful csilk_ws_handshake call.
| c | The request context. |
Check whether the connection has been upgraded to WebSocket.
| c | The request context. |
| void csilk_json | ( | csilk_ctx_t * | c, |
| int | status, | ||
| cJSON * | json | ||
| ) |
Send a JSON response (takes ownership of the cJSON object).
Serializes json to a string, sets the Content-Type header to application/json, and sends the response. The cJSON object is freed by this function — the caller must not use it afterward.
| c | The request context. |
| status | HTTP status code. |
| json | cJSON object to serialise and send. Ownership is transferred to the framework (cJSON_Delete is called internally). |
Send a JSON response (takes ownership of the cJSON object).
Sets the Content-Type header to "application/json", serializes the cJSON object to an unformatted JSON string, and sets it as the response body. The cJSON object is deleted (freed) after serialization — the caller must NOT free it.
| c | The request context. |
| status | HTTP status code for the response. |
| json | cJSON object to serialize. Ownership is taken by this call. |
| void csilk_json_error | ( | csilk_ctx_t * | c, |
| int | status, | ||
| const char * | message | ||
| ) |
Send a JSON-formatted error response.
Produces {"error": "<message>"} with the given status code. The message is copied into the request arena.
| c | The request context. |
| status | HTTP status code (e.g., 400, 500). |
| message | Human-readable error description. |
Send a JSON-formatted error response.
Creates a JSON object with a single "error" key containing message and sends it as the response via csilk_json().
| c | The request context. |
| status | HTTP status code. |
| message | Error message string (if NULL, "Unknown error" is used). |
| void csilk_json_reflect | ( | csilk_ctx_t * | c, |
| int | status, | ||
| const char * | type_name, | ||
| const void * | ptr | ||
| ) |
Serialise a reflected struct as a JSON response.
Marshals the struct via csilk_json_marshal and sends the result as a JSON response. The struct must have been registered with the reflection system.
| c | The request context. |
| status | HTTP status code. |
| type_name | Registered type name string. |
| ptr | Pointer to the struct instance to serialise. |
Serialise a reflected struct as a JSON response.
Serializes the provided struct to JSON using the csilk reflection engine and sends it as the HTTP response. If type_name is NULL, the type is inferred from the current handler's output_type metadata.
| c | The request context. |
| status | HTTP status code. |
| type_name | Registered type name, or NULL to infer from route metadata. |
| ptr | Pointer to the struct to serialize. |
| char * csilk_jwt_generate | ( | csilk_ctx_t * | c, |
| cJSON * | payload, | ||
| const char * | secret | ||
| ) |
Generate a signed JWT token (HS256).
Creates a three-part JWT (header.payload.signature) using HMAC-SHA256. The payload is used as-is for the claims.
| c | Request context (for crypto-driver access). |
| payload | cJSON object containing JWT claims (e.g., {"sub":"123"}). Not modified; ownership stays with caller. |
| secret | Secret key string for HMAC signing. |
Generate a signed JWT token (HS256).
Constructs a JWT with the fixed header {"alg":"HS256","typ":"JWT"} and the caller-supplied cJSON payload. The token is signed using HMAC-SHA256 with the provided secret. Every component (header, payload, signature) is base64url-encoded per RFC 4648 §5.
| c | The request context (used for HMAC operations). |
| payload | A cJSON object containing the claims. Must not be NULL. |
| secret | The HMAC-SHA256 signing secret. Must not be NULL. |
header.payload.signature, or NULL on allocation failure or invalid arguments.| void csilk_jwt_middleware | ( | csilk_ctx_t * | c, |
| const char * | secret | ||
| ) |
JWT authentication middleware.
Extracts the Bearer token from the Authorization header, verifies it, and stores the decoded payload in the context under the key "jwt_payload". If the token is missing or invalid, responds with 401 Unauthorized and aborts the chain.
| c | The request context. |
| secret | Secret key for token verification. |
Extracts the Bearer token from the Authorization header, verifies it via csilk_jwt_verify(), and checks the "exp" claim if present. On success the decoded payload is stored in the context under the key "jwt_payload" and the next handler is called. On failure (missing header, invalid token, or expired), a 401 Unauthorized response is sent.
| c | The request context. |
| secret | The HMAC-SHA256 verification secret. |
| cJSON * csilk_jwt_verify | ( | csilk_ctx_t * | c, |
| const char * | token, | ||
| const char * | secret | ||
| ) |
Verify a JWT token and extract its payload.
Validates the signature (HMAC-SHA256), checks the "exp" claim if present, and returns the parsed payload.
| c | Request context (for crypto-driver access). |
| token | The JWT string to verify. |
| secret | Secret key for HMAC verification. |
Verify a JWT token and extract its payload.
Splits the token into its three dot-separated components (header, payload, signature), recomputes the HMAC-SHA256 signature over the signing input, and compares it against the provided signature (constant-time not guaranteed — uses strcmp). On success, the payload is base64url-decoded and parsed into a cJSON object.
| c | The request context (used for HMAC operations). |
| token | The JWT string in the format header.payload.signature. |
| secret | The HMAC-SHA256 verification secret. |
| int csilk_load_config | ( | const char * | yaml_path, |
| csilk_config_t * | config | ||
| ) |
Load and parse a YAML configuration file.
Reads a YAML file at yaml_path and populates config. All string fields in config are heap-allocated and must be freed with csilk_config_free.
| yaml_path | Path to a YAML configuration file. | |
| [out] | config | Pointer to a caller-allocated csilk_config_t to populate. |
Load and parse a YAML configuration file.
Opens the specified YAML file, parses its contents, and populates the provided csilk_config_t structure. The parser recognizes top-level keys ("port") and section keys ("server", "logger", "cors", "rate_limit", "static_files", "middleware"). All fields not present in the YAML retain their default values (initialized at the start of this function).
| yaml_path | Absolute or relative path to the YAML configuration file. |
| config | [out] Pre-allocated config structure to populate. |
| void csilk_log_close | ( | void | ) |
Close the global logger.
Close the global logger.
Closes file handles and destroys mutexes. Safe to call multiple times.
| int csilk_log_init | ( | csilk_log_config_t | config | ) |
Initialize the global logger with config.
| config | Logger configuration. |
Initialize the global logger with config.
Configures the output destination (stdout if no file_path, or a file if set), the minimum log level, coloring (auto-detected for terminals when use_colors is -1), and whether to use structured JSON format. If the logger was previously initialized, csilk_log_close() is called first. A mutex is initialized for thread-safe operation.
| config | Logger configuration struct with desired settings. |
| int csilk_log_is_json | ( | void | ) |
Check whether the logger is in JSON format mode.
Check whether the logger is in JSON format mode.
| cJSON * csilk_log_make_kv | ( | const char * | key, |
| ... | |||
| ) |
Create a simple key-value cJSON object for structured logging.
Convenience helper that builds a cJSON object from alternating key/value string pairs terminated by a NULL key.
| key | First key. |
| ... | Value, then key, value, ... terminated by NULL. |
Create a simple key-value cJSON object for structured logging.
Helper to create a flat JSON object from a NULL-terminated list of strings. Used primarily with CSILK_LOG_KV.
| void csilk_log_set_request_id | ( | const char * | request_id | ) |
Set the Request ID for the current thread (for log correlation).
| request_id | The Request ID string, or NULL to clear. |
Set the Request ID for the current thread (for log correlation).
Stores the request ID in thread-local storage, allowing subsequent log calls on the same thread to automatically include it without passing the context explicitly.
| void csilk_logger_handler | ( | csilk_ctx_t * | c | ) |
Logging middleware handler. Logs request method, path, and processing time.
| c | The request context. |
Logging middleware handler. Logs request method, path, and processing time.
Records the start time of the request using a high-resolution monotonic clock (CLOCK_MONOTONIC), proceeds to the next handler via csilk_next(), and then calculates the total elapsed time. It automatically selects between plain-text logging and structured JSON logging based on the global logger configuration.
In JSON mode, the request details are marshalled into a csilk_req_log_t struct and logged via the reflection-based JSON logger. In text mode, a simple "[HTTP] METHOD PATH STATUS DURATION" line is emitted.
If a request ID is set on the context, it is propagated to the logger's thread-local state for correlating log entries.
| c | The request context. |
| uint64_t csilk_metrics_get_total_duration | ( | void | ) |
| uint64_t csilk_metrics_get_total_requests | ( | void | ) |
| void csilk_metrics_handler | ( | csilk_ctx_t * | c | ) |
Prometheus /metrics endpoint handler.
Exposes collected metrics in the standard Prometheus text exposition format (content-type: text/plain; version=0.0.4).
| c | The request context. |
Prometheus /metrics endpoint handler.
Renders full system telemetry in standard Prometheus text-based format.
| void csilk_metrics_middleware | ( | csilk_ctx_t * | c, |
| const char * | arg | ||
| ) |
Prometheus metrics middleware.
Tracks request-level metrics: QPS, latency distribution histogram, and HTTP status code counters. Should be added early in the middleware chain.
| c | The request context. |
| arg | Optional config string (currently unused, pass NULL). |
Prometheus metrics middleware.
Wraps the request execution to measure latency and update atomic counters.
| void csilk_mq_abort | ( | csilk_mq_ctx_t * | ctx | ) |
Abort the MQ middleware/subscriber chain.
No further handlers execute for the current message.
| ctx | The MQ context. |
Abort the MQ middleware/subscriber chain.
Sets the aborted flag on the context. Subsequent calls to csilk_mq_next() will be ignored.
| ctx | Message queue context (may be NULL). |
| const void * csilk_mq_get_payload | ( | csilk_mq_ctx_t * | ctx, |
| size_t * | len | ||
| ) |
Get the payload of the current message.
| ctx | The MQ context. | |
| [out] | len | Optional pointer to receive the payload byte length (may be NULL). |
Get the payload of the current message.
| ctx | Message queue context. |
| len | [out] If non-NULL, receives the payload length in bytes. |
| void csilk_mq_get_stats | ( | csilk_mq_t * | mq, |
| csilk_mq_stats_t * | stats | ||
| ) |
Get current MQ statistics.
| mq | The MQ instance. |
| stats | [out] Pointer to stats struct to populate. |
| const char * csilk_mq_get_topic | ( | csilk_mq_ctx_t * | ctx | ) |
Get the topic of the current message.
| ctx | The MQ context. |
Get the topic of the current message.
| ctx | Message queue context. |
| void csilk_mq_next | ( | csilk_mq_ctx_t * | ctx | ) |
Pass control to the next middleware or subscriber in the MQ chain.
Must be called exactly once (or zero times if csilk_mq_abort is used) for the chain to advance.
| ctx | The MQ context. |
Pass control to the next middleware or subscriber in the MQ chain.
Handlers form a linear chain: [global_mw..., topic_mw..., subscriber...]. Each handler calls csilk_mq_next() to yield control to the next one. This is a non-recursive, non-reentrant manual trampoline — the chain is driven by the handlers themselves, not by a central loop.
If ctx->aborted is set (by a previous csilk_mq_abort() call), this is a no-op. Out-of-bounds handler_index is also silently ignored (end of chain).
| ctx | Message queue context. |
| void csilk_mq_offload | ( | csilk_mq_ctx_t * | ctx, |
| csilk_mq_worker_t | worker | ||
| ) |
Offload message processing to a background thread.
Hands off the current message to libuv's thread pool for processing. csilk_mq_next is called internally so the chain continues immediately. The worker runs on a separate thread — it must be thread-safe and must NOT call back into the MQ or context APIs.
| ctx | The MQ context. |
| worker | Background worker function that receives the topic and a copy of the payload. |
Offload message processing to a background thread.
The deep copy avoids shared mutable state between the background thread and the event loop. The caller's handler chain continues in parallel with the offloaded work — there is no result channel.
| ctx | Message queue context. |
| worker | Worker function that will receive topic, payload, and length on a background thread. |
| int csilk_mq_publish | ( | csilk_mq_t * | mq, |
| const char * | topic, | ||
| const void * | payload, | ||
| size_t | len | ||
| ) |
Publish a message to a topic.
The payload is copied internally so the caller can reuse the buffer immediately. The message is enqueued and processed asynchronously on the main event loop via a libuv async handle, making this function thread-safe.
| mq | The MQ instance. |
| topic | Target topic name. |
| payload | Pointer to the data to publish (copied internally). |
| len | Byte length of payload. |
Publish a message to a topic.
The two operations are NOT atomic (WAL can succeed, memory enqueue can fail). This is a deliberate trade-off:
Processing is asynchronous — the caller receives no delivery confirmation. The message is deep-copied at both stages.
| mq | The MQ instance. |
| topic | Target topic name (cannot be NULL). |
| payload | Message payload data (may be NULL). |
| len | Payload length in bytes. |
payload immediately after this call returns — the data is copied internally. | void csilk_mq_register_monitor | ( | csilk_mq_t * | mq, |
| csilk_ctx_t * | c | ||
| ) |
Register a WebSocket monitor for real-time MQ events.
| mq | The MQ instance. |
| c | Framework context (WebSocket connection). |
| int csilk_mq_set_persistence | ( | csilk_mq_t * | mq, |
| const char * | wal_path | ||
| ) |
Enable Write-Ahead Log (WAL) persistence for the MQ.
When enabled, every published message is appended to wal_path before being processed. The WAL can be replayed on restart to recover messages.
| mq | The MQ instance. |
| wal_path | File path for the WAL (e.g., "mq.wal"). The string is copied internally. |
Enable Write-Ahead Log (WAL) persistence for the MQ.
After this call, every csilk_mq_publish() appends to the WAL before enqueuing in memory.
| mq | The MQ instance. |
| wal_path | File path for the WAL. The file is created if it does not exist. |
| char * csilk_mq_stats_to_json | ( | const csilk_mq_stats_t * | stats | ) |
Convert MQ statistics to a JSON string.
| stats | Pointer to stats struct. |
| void csilk_mq_subscribe | ( | csilk_mq_t * | mq, |
| const char * | topic, | ||
| csilk_mq_handler_t | subscriber | ||
| ) |
Register a subscriber for a topic.
Subscribers run after all applicable middleware (global + topic-specific) has completed.
| mq | The MQ instance. |
| topic | Topic name to subscribe to. |
| subscriber | Handler function. Must not be NULL. |
Register a subscriber for a topic.
Subscribers are treated as handlers appended to the end of the chain (after global and topic middlewares). This is a convenience wrapper around csilk_mq_use().
| mq | The MQ instance. |
| topic | Topic name to subscribe to. |
| subscriber | Handler function invoked when a message matches. |
| void csilk_mq_use | ( | csilk_mq_t * | mq, |
| const char * | topic, | ||
| csilk_mq_handler_t | middleware | ||
| ) |
Register MQ middleware for a topic.
Middleware runs before subscribers. Pass NULL as topic to register global middleware that intercepts all messages.
| mq | The MQ instance. |
| topic | Topic name to intercept, or NULL for global middleware. |
| middleware | Handler function. Must not be NULL. |
Register MQ middleware for a topic.
Both arrays grow by doubling (initial cap = 4) when full.
| mq | The MQ instance. |
| topic | Topic name (e.g., "user.created"), or NULL for global. |
| middleware | Handler function to invoke during message processing. |
| void csilk_multipart_parse | ( | csilk_ctx_t * | c, |
| csilk_multipart_handler_t | handler | ||
| ) |
Parse a multipart/form-data request body.
Iterates over all parts in the request body (using the Content-Type boundary) and calls handler for each. Files and form fields are treated uniformly — check the filename field to distinguish them.
| c | The request context. |
| handler | Callback invoked once per part. |
Parse a multipart/form-data request body.
Extracts the boundary string from the Content-Type header, then iterates through the request body looking for boundary-delimited parts. For each part, the function parses the Content-Disposition header (extracting name and optional filename), the optional Content-Type header, and the part body. A csilk_multipart_part_t struct is populated and passed to the caller-supplied handler callback.
| c | The request context containing the parsed body. |
| handler | Callback invoked once per parsed part. Receives a pointer to a csilk_multipart_part_t describing the part. Must not be NULL. |
| void csilk_next | ( | csilk_ctx_t * | c | ) |
Pass control to the next handler in the middleware/handler chain.
Implements the "onion" model: handlers before csilk_next run on the way in, handlers after csilk_next run on the way out (after downstream handlers). Call csilk_is_aborted after returning to check whether a downstream handler called csilk_abort.
| c | The request context. |
Pass control to the next handler in the middleware/handler chain.
Increments the internal handler index and calls the next handler function. If the request has been aborted (via csilk_abort()), this is a no-op. The handler chain is a NULL-terminated array; if the next entry is NULL, execution falls through (the response is sent automatically if not async).
| c | The request context. |
| void csilk_panic | ( | csilk_ctx_t * | c | ) |
Trigger a panic (caught by recovery middleware).
Calls longjmp back to the setjmp point established by csilk_recovery_handler. If no recovery middleware is registered the behaviour is undefined (likely a crash).
| c | The request context. |
Trigger a panic (caught by recovery middleware).
If a recovery handler has been installed (c->has_jump_buffer is set), this function performs a longjmp back to the recovery point set by csilk_recovery_handler().
If no recovery handler is registered, it prints a fatal error message to stderr and calls exit(1) to terminate the process.
| c | The request context. May be NULL (will trigger abort path). |
| void csilk_parse_form_urlencoded | ( | csilk_ctx_t * | c | ) |
Parse the request body as application/x-www-form-urlencoded.
Populates the form_params hash map in the request. After calling this, form fields can be retrieved with csilk_get_form_field. Safe to call multiple times — subsequent calls are no-ops.
| c | The request context. |
Checks the Content-Type header for "application/x-www-form-urlencoded" and, if matched, parses the request body into the form_params hash map. Key-value parsing and URL-decoding follow the same logic as csilk_parse_query().
| c | The request context. |
| void csilk_parse_query | ( | csilk_ctx_t * | c, |
| const char * | query_string | ||
| ) |
Parse a raw query string and populate the query_params map.
Internal helper. Parses key=value pairs separated by '&' and URL-decodes both keys and values.
| c | The request context. |
| query_string | Raw query string (the part after '?', may be NULL or empty). |
Parse a raw query string and populate the query_params map.
Splits the query string on '&' and each key-value pair on '=', URL-decodes both keys and values, and adds them to the request's query_params map. Parameters without a '=' get an empty-string value.
| c | The request context. |
| query_string | The raw query string (e.g., "foo=1&bar=baz"). The leading '?' should NOT be included. |
| void csilk_process_get_stats | ( | csilk_process_stats_t * | stats | ) |
| void csilk_rate_limit_middleware | ( | csilk_ctx_t * | c, |
| int | limit | ||
| ) |
Simple per-IP rate-limiting middleware.
Uses a fixed-window counter per client IP. If the limit is exceeded a 429 Too Many Requests response is sent and the handler chain is aborted.
| c | The request context. |
| limit | Maximum number of requests allowed per minute for a single IP. |
Simple per-IP rate-limiting middleware.
Tracks request counts per client IP address within a configurable window. If the number of requests from a given IP exceeds the limit, a 429 Too Many Requests response is sent (with a Retry-After header) and the pipeline is aborted.
The IP table is protected by a libuv mutex for thread safety. Stale entries are periodically evicted to prevent unbounded memory growth.
| c | The request context. |
| limit | Maximum number of requests allowed per IP within the WINDOW_SIZE (60-second) sliding window. |
| void csilk_ready_check_handler | ( | csilk_ctx_t * | c | ) |
Built-in Readiness Check handler. Performs deep health check (MQ, connections) and returns 200 or 503.
| c | The request context. |
Built-in Readiness Check handler. Performs deep health check (MQ, connections) and returns 200 or 503.
Performs a "deep" check of the server's health by inspecting critical subsystems. It checks:
Returns 200 OK if the server is ready to accept more traffic, or 503 Service Unavailable if any check fails.
| c | The request context. If NULL the function returns immediately. |
| void csilk_recovery_handler | ( | csilk_ctx_t * | c | ) |
Panic-recovery middleware.
Wraps the handler chain in a setjmp/longjmp boundary. If a handler calls csilk_panic (or a segfault occurs within the protected scope), this middleware sends a 500 response and logs the error instead of crashing the server.
Should be registered as the outermost middleware.
| c | The request context. |
Panic-recovery middleware.
Installs a setjmp recovery point before calling csilk_next(). If any downstream handler triggers csilk_panic(), execution resumes at the setjmp point and an "Internal Server Error" response (500) is sent instead of crashing the process.
After the normal (non-panic) path completes, the jump buffer flag is cleared.
| c | The request context (must have a valid jump_buffer). |
| void csilk_redirect | ( | csilk_ctx_t * | c, |
| int | status, | ||
| const char * | location | ||
| ) |
Send an HTTP redirect response with a custom status code.
Sets the Location header and the response body to a minimal HTML redirect page. The handler chain is aborted after this call.
| c | The request context. |
| status | HTTP redirect status (e.g., 301 Moved Permanently, 302 Found, 307 Temporary Redirect). |
| location | The destination URL. Must not be NULL. |
Send an HTTP redirect response with a custom status code.
Sets the Location header, updates the response status, and aborts the handler chain. If the provided status is outside the 3xx range, it is coerced to 302 (Found).
| c | The request context. |
| status | HTTP redirect status (typically 301, 302, 303, 307, 308). |
| location | The target URL for the Location header. |
| void csilk_redirect_simple | ( | csilk_ctx_t * | c, |
| const char * | url | ||
| ) |
Send a simple 302 Found redirect.
Convenience wrapper around csilk_redirect with status 302.
| c | The request context. |
| url | The destination URL. |
Send a simple 302 Found redirect.
Convenience wrapper around csilk_redirect().
| c | The request context. |
| url | The target URL for the redirect. |
| void csilk_request_id_middleware | ( | csilk_ctx_t * | c | ) |
Request ID middleware. Generates a unique ID for each request and sets X-Request-Id header.
| c | The request context. |
Request ID middleware. Generates a unique ID for each request and sets X-Request-Id header.
Ensures every request has a unique UUID v4 identifier. If the request context does not already have an ID (c->request_id is empty), a new UUID is generated via _csilk_generate_uuid(). The identifier is then set as the "X-Request-Id" response header and propagated to the thread-local logger state for distributed tracing correlation.
| c | The request context. If NULL the function returns immediately. |
| void csilk_response_end | ( | csilk_ctx_t * | c | ) |
Finalise a chunked streaming response.
Sends the terminal (zero-length) chunk and any trailers. The connection is then kept alive or closed according to the HTTP keep-alive header.
| c | The request context. |
Finalise a chunked streaming response.
If the response has not yet started, sends chunked headers first. Then sends the zero-length terminal chunk ("0\\r\\n\\r\\n") which signals to the client that the stream is complete.
| c | Request context. |
| void csilk_response_write | ( | csilk_ctx_t * | c, |
| const uint8_t * | data, | ||
| size_t | len | ||
| ) |
Write a chunk to the response stream (chunked transfer encoding).
The first call sends the HTTP response headers with Transfer-Encoding: chunked. Subsequent calls append chunked frames. The handler MUST set async mode (csilk_set_async(c, 1)) before calling this and MUST NOT use csilk_string, csilk_json, etc.
| c | The request context. |
| data | Raw data for the chunk. |
| len | Byte length of data. |
Write a chunk to the response stream (chunked transfer encoding).
On the first call, automatically sends chunked headers (status line + Transfer-Encoding: chunked). Subsequent calls append data chunks. Sets the response to async mode so the framework does not auto-send the response after the handler returns.
| c | Request context. |
| data | Payload data to write. |
| len | Length of data in bytes. |
| void csilk_router_add | ( | csilk_router_t * | r, |
| const char * | method, | ||
| const char * | path, | ||
| csilk_handler_t * | handlers, | ||
| size_t | handler_count | ||
| ) |
Register a route with one or more handlers.
The route is inserted into the radix tree. Dynamic segments (:param) and wildcard segments (*wildcard) are supported in path. The handlers are stored by pointer — the caller must ensure they remain valid for the lifetime of the router.
| r | Router instance. |
| method | HTTP method (e.g., "GET", "POST", "DELETE", "*" for any). |
| path | URL pattern (e.g., "/users/:id/posts"). |
| handlers | Array of handler function pointers. |
| handler_count | Number of elements in handlers. |
Register a route with one or more handlers.
Convenience wrapper around csilk_router_add_extended() that passes NULL for all optional metadata fields.
| r | The router instance. |
| method | HTTP method. |
| path | URL path pattern. |
| handlers | Array of handler functions. |
| handler_count | Number of handlers. |
| void csilk_router_add_extended | ( | csilk_router_t * | r, |
| const char * | method, | ||
| const char * | path, | ||
| csilk_handler_t * | handlers, | ||
| size_t | handler_count, | ||
| const char * | path_pattern, | ||
| const char * | input_type, | ||
| const char * | output_type, | ||
| const char * | summary, | ||
| const char * | description | ||
| ) |
Register a route with full OpenAPI/reflection metadata.
Extended version of csilk_router_add that also stores metadata for automatic OpenAPI spec generation and request/response binding.
| r | Router instance. |
| method | HTTP method string. |
| path | URL pattern (e.g., "/users/:id"). |
| handlers | Array of handler functions. |
| handler_count | Number of handlers in handlers. |
| path_pattern | Canonical path pattern string for documentation (may differ from the radix-tree path). |
| input_type | Registered type name for request-body binding (NULL if there is no request body). |
| output_type | Registered type name for response serialisation (NULL if raw response is used). |
| summary | Short summary of the operation (NULL to omit from spec). |
| description | Detailed description of the operation (NULL to omit). |
| void csilk_router_add_extended_perm | ( | csilk_router_t * | r, |
| const char * | method, | ||
| const char * | path, | ||
| csilk_handler_t * | handlers, | ||
| size_t | handler_count, | ||
| const char * | path_pattern, | ||
| 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 full metadata including permissions.
| r | Router instance. |
| method | HTTP method string. |
| path | URL pattern. |
| handlers | Handler function array. |
| handler_count | Number of handlers. |
| path_pattern | Canonical path pattern for docs. |
| 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 to omit). |
| description | Detailed description (NULL to omit). |
| perm_required | Permission identifier (e.g., "read"), or NULL. |
| perm_resource | Resource pattern (e.g., "users:*"), or NULL. |
Combines csilk_router_add_extended with permission metadata in a single call. The permission fields are used by csilk_perm_auto_middleware.
| r | The router instance. |
| method | HTTP method. |
| path | URL path pattern. |
| handlers | Array of handler functions. |
| handler_count | Number of handlers. |
| path_pattern | Original path pattern for OpenAPI metadata. |
| input_type | Registered type name for request body, or NULL. |
| output_type | Registered type name for response body, or NULL. |
| summary | OpenAPI operation summary, or NULL. |
| description | OpenAPI operation description, or NULL. |
| perm_required | Permission identifier (e.g., "read"), or NULL. |
| perm_resource | Resource pattern (e.g., "users:*"), or NULL. |
| void csilk_router_add_perm | ( | csilk_router_t * | r, |
| const char * | method, | ||
| const char * | path, | ||
| csilk_handler_t * | handlers, | ||
| size_t | handler_count, | ||
| const char * | perm_required, | ||
| const char * | perm_resource | ||
| ) |
Register a route with permission metadata.
| r | Router instance. |
| method | HTTP method string. |
| path | URL pattern. |
| handlers | Handler function array. |
| handler_count | Number of handlers. |
| perm_required | Permission identifier (e.g., "read"), or NULL. |
| perm_resource | Resource pattern (e.g., "users:*"), or NULL. |
Same as csilk_router_add but also stores permission requirement for interface-level access control. The auto-check middleware (csilk_perm_auto_middleware) reads these fields at request time.
| r | The router instance. |
| method | HTTP method. |
| path | URL path pattern. |
| handlers | Array of handler functions. |
| handler_count | Number of handlers. |
| perm_required | Permission identifier (e.g., "read", "write"), or NULL. |
| perm_resource | Resource pattern (e.g., "users:*"), or NULL. |
| cJSON * csilk_router_collect_routes | ( | csilk_router_t * | r | ) |
Collect all registered routes from the router tree as a cJSON array.
Collect metadata for all registered routes.
| r | The router instance. |
Traverses the radix tree and returns a cJSON array where each element contains "method", "path", "input_type", "output_type", "summary", and "description" fields.
| r | Router instance. |
Traverses the entire trie and returns a JSON array where each element is an object with method, path, input_type, output_type, summary, and description fields.
| r | The router instance. |
| void csilk_router_free | ( | csilk_router_t * | r | ) |
Destroy the router and release all its resources.
Frees the radix tree nodes and any associated copy of route metadata (OpenAPI annotations).
| r | Router instance to free. Must not be NULL. |
Destroy the router and release all its resources.
Recursively frees the entire trie starting from the root node, then frees the router struct itself.
| r | The router to free (may be NULL). |
| csilk_handler_t * csilk_router_match | ( | csilk_router_t * | r, |
| const char * | method, | ||
| const char * | path | ||
| ) |
Match a raw method+path to handlers (standalone, no context).
Useful for testing or when no csilk_ctx_t is available. The returned array is owned by the router and must NOT be freed.
| r | Router instance. |
| method | HTTP method string. |
| path | Decoded URL path. |
Match a raw method+path to handlers (standalone, no context).
Direct matching without populating path parameters. Useful for checking whether a route exists without processing a full request.
| r | The router instance. |
| method | HTTP method. |
| path | URL path. |
| int csilk_router_match_ctx | ( | csilk_router_t * | r, |
| csilk_ctx_t * | c | ||
| ) |
Match the current request against the router and update the context.
On success the matched handlers are stored in the context and path parameters (csilk_get_param) become available.
| r | Router instance. |
| c | Request context containing the parsed request. |
Match the current request against the router and update the context.
Sets the context's handlers array, handler index (reset to -1), and current_handler metadata on a successful match. Path parameters are captured into the context's params array.
| r | The router instance. |
| c | The request context (must have method and path set). |
| csilk_router_t * csilk_router_new | ( | void | ) |
Create a new empty router.
Allocates and initialises the router structure with a single root node.
Create a new empty router.
| void csilk_security_get_stats | ( | csilk_security_stats_t * | stats | ) |
| void csilk_serve_openapi | ( | csilk_ctx_t * | c, |
| csilk_router_t * | r, | ||
| const char * | title, | ||
| const char * | version, | ||
| const char * | description | ||
| ) |
Serve the OpenAPI JSON specification as the response.
Intended to be called from within a handler to expose the API spec.
| c | The request context. |
| r | The router instance whose routes will be documented. |
| title | API title. |
| version | API version. |
| description | API description (optional, pass NULL to omit). |
Serve the OpenAPI JSON specification as the response.
Intended to be called from within a route handler. Generates the OpenAPI document via csilk_generate_openapi_json() and sends it as a JSON response.
| c | The request context. |
| r | The router instance. |
| title | API title. |
| version | API version. |
| description | API description. |
| void csilk_serve_swagger_ui | ( | csilk_ctx_t * | c | ) |
Serve the embedded Swagger UI page.
The UI loads the OpenAPI spec from /openapi.json (the client fetches it separately). Register a handler for GET /openapi.json that calls csilk_serve_openapi.
| c | The request context. |
Serve the embedded Swagger UI page.
| void csilk_server_add_hook | ( | csilk_server_t * | s, |
| csilk_hook_type_t | type, | ||
| void * | handler | ||
| ) |
Register a lifecycle hook callback.
The handler is cast to the appropriate type internally based on type. Multiple handlers may be registered for the same hook type.
| s | The server instance. |
| type | The hook type (see csilk_hook_type_t). |
| handler | Pointer to the callback function. Must match the expected signature for type (csilk_server_hook_handler_t for SERVER_*, csilk_ctx_hook_handler_t for others). |
Register a lifecycle hook callback.
Hooks are invoked at specific points in the request lifecycle (conn_open, conn_close, request_begin, request_end, server_start, server_stop). Multiple handlers can be registered for the same hook type; they are called in reverse order of registration (LIFO).
| s | The server instance. |
| type | Hook type (CSILK_HOOK_CONN_OPEN, CSILK_HOOK_REQUEST_BEGIN, CSILK_HOOK_CONN_CLOSE, CSILK_HOOK_REQUEST_END, CSILK_HOOK_SERVER_START, CSILK_HOOK_SERVER_STOP). |
| handler | Function pointer. For server hooks (start/stop), the signature is void(*)(csilk_server_t*). For context hooks, the signature is void(*)(csilk_ctx_t*). |
| void csilk_server_free | ( | csilk_server_t * | server | ) |
Destroy the server and release all resources.
Stops the server if running, closes all connections, and frees the router, hooks, and internal structures.
| server | Server instance to free. |
Destroy the server and release all resources.
Should only be called after the event loop has stopped. Joins any worker threads, frees the SPA doc root, drains the client pool, cleans up TLS, frees the message queue, frees all registered hooks, destroys the clients mutex, and frees the server struct.
| server | The server to free (may be NULL). |
| csilk_mq_t * csilk_server_get_mq | ( | csilk_server_t * | server | ) |
Get the Message Queue instance attached to a server.
The MQ is created lazily on first access.
| server | Pointer to the server instance. |
Get the Message Queue instance attached to a server.
The MQ is created automatically during csilk_server_new(). It can be used to register topics, subscribers, and publish messages.
| server | The server instance. |
| csilk_router_t * csilk_server_get_router | ( | csilk_server_t * | server | ) |
Get the router instance attached to a server.
| server | The server instance. |
| void csilk_server_get_stats | ( | csilk_server_t * | server, |
| int * | active_conn, | ||
| int * | pooled_conn | ||
| ) |
| csilk_server_t * csilk_server_new | ( | csilk_router_t * | router | ) |
Create a new server instance.
Allocates and initialises a server bound to the given router. The server takes ownership of the router and frees it in csilk_server_free.
| router | The router to use for request dispatch. Must not be NULL. |
Create a new server instance.
Initializes the reflection system, allocates the server struct, sets up the libuv default loop, configures the llhttp parser callbacks, applies default server configuration (timeouts, buffer limits, backlog), creates a clients mutex, and creates the internal message queue (MQ) instance.
| router | The router instance to use for request matching. |
| int csilk_server_run | ( | csilk_server_t * | server, |
| int | port | ||
| ) |
Start the server and enter the libuv event loop.
This call blocks until the server is stopped (csilk_server_stop) or a fatal error occurs.
| server | Server instance. |
| port | TCP port to listen on. |
Start the server and enter the libuv event loop.
This is the final step in server startup. The full bootstrap sequence:
| server | The server instance. |
| port | TCP port to bind to. |
| void csilk_server_set_cipher_driver | ( | csilk_server_t * | server, |
| csilk_cipher_driver_t * | driver | ||
| ) |
Set the cipher driver for symmetric/asymmetric encryption.
Replaces the default OpenSSL-based AES-256-GCM / RSA-OAEP / RSA-PSS implementations with a user-provided driver. Pass NULL to restore the built-in defaults.
| server | The server instance. |
| driver | Pointer to a csilk_cipher_driver_t, or NULL for defaults. The driver struct must remain valid for the server's lifetime. |
Set the cipher driver for symmetric/asymmetric encryption.
Replaces the built-in AES/RSA routines with a user-provided implementation.
| server | The server instance. |
| driver | Pointer to a csilk_cipher_driver_t. |
| void csilk_server_set_config | ( | csilk_server_t * | server, |
| const csilk_server_config_t * | config | ||
| ) |
Apply server configuration options.
Copies values from config into the server's internal state. Should be called before csilk_server_run. The config struct may be stack-allocated.
| server | Server instance. |
| config | Pointer to the configuration to apply. |
Apply server configuration options.
Copies the provided configuration into the server instance. This should be called before csilk_server_run().
| server | The server instance. |
| config | Pointer to the configuration to apply (copied by value). |
| void csilk_server_set_crypto_driver | ( | csilk_server_t * | server, |
| csilk_crypto_driver_t * | driver | ||
| ) |
Set the global crypto driver for the server.
Replaces the default software crypto routines with a user-provided implementation. Pass NULL to restore the built-in defaults.
| server | The server instance. |
| driver | Pointer to a csilk_crypto_driver_t, or NULL for defaults. The driver struct must remain valid for the server's lifetime. |
Set the global crypto driver for the server.
When set, HMAC and UUID operations on request contexts will delegate to the driver instead of using the built-in software implementations.
| server | The server instance. |
| driver | Pointer to the crypto driver vtable (may be NULL to reset). |
| int csilk_server_set_max_connections | ( | csilk_server_t * | server, |
| int | max | ||
| ) |
Set the maximum number of concurrent connections and return the previous limit.
| server | Server instance. |
| max | New limit (0 = unlimited). |
Set the maximum number of concurrent connections and return the previous limit.
When this limit is reached, new connections are accepted and immediately closed to drain the listen backlog. A value of 0 means unlimited.
| server | The server instance. |
| max | Maximum concurrent connections (0 for unlimited). |
| void csilk_server_set_not_found_handler | ( | csilk_server_t * | server, |
| csilk_handler_t | handler | ||
| ) |
Set a custom handler for 404 (route-not-found) responses.
Replaces the default 404 behaviour. The handler is invoked with the request context (status 404 is NOT pre-set — the handler may set its own). Pass NULL to restore the default 404 handler.
| server | Server instance. |
| handler | Handler function, or NULL for default. |
Set a custom handler for 404 (route-not-found) responses.
Replaces the default "Not Found" plain-text response with a custom handler. Overridden by csilk_server_set_spa_fallback().
| server | The server instance. |
| handler | Handler function invoked for unmatched routes. |
| void csilk_server_set_spa_fallback | ( | csilk_server_t * | server, |
| const char * | doc_root | ||
| ) |
Enable single-page application (SPA) fallback mode.
Unmatched GET requests serve index.html from doc_root instead of returning 404. Overrides any custom 404 handler. Useful for serving React/Vue/Angular SPAs where the router handles URLs client-side.
| server | Server instance. |
| doc_root | Directory containing index.html. The path is copied internally. |
Enable single-page application (SPA) fallback mode.
Sets the SPA document root and replaces the 404 handler with the built-in spa_fallback_handler. Overrides any custom 404 handler set via csilk_server_set_not_found_handler().
| server | The server instance. |
| doc_root | Absolute or relative filesystem path to the directory containing index.html. |
| void csilk_server_set_storage_driver | ( | csilk_server_t * | server, |
| csilk_storage_driver_t * | driver | ||
| ) |
Replace the context key-value storage driver.
| server | Server instance. |
| driver | Pointer to the new driver, or NULL to restore the default in-memory arena-backed driver. The driver struct must remain valid for the server's lifetime. |
Replace the context key-value storage driver.
When set, calls to csilk_set()/csilk_get() on request contexts belonging to this server will delegate to the driver instead of using the default arena-backed linked list.
| server | The server instance. |
| driver | Pointer to the storage driver vtable (may be NULL to reset). |
| void csilk_server_stop | ( | csilk_server_t * | server | ) |
Request a graceful server shutdown.
Signals the event loop to stop after all active requests complete. New connections are refused.
| server | Server instance. |
Request a graceful server shutdown.
Sends an async signal to the event loop which triggers on_stop_async() on the main loop thread. The function returns immediately; the server shuts down asynchronously.
| server | The server instance. |
| int csilk_server_use | ( | csilk_server_t * | server, |
| csilk_handler_t | handler | ||
| ) |
Register global middleware.
Middleware is executed for every request in the order it was added. The handler array has a fixed maximum size (typically 64).
| server | Server instance. |
| handler | Middleware function. |
Register global middleware.
Global middlewares are prepended to the matched route's handler chain. They run before route-specific middleware and the final handler. There is a hard limit of 32 global middlewares.
| server | The server instance. |
| handler | Middleware handler function. |
| void csilk_session_destroy | ( | csilk_ctx_t * | c | ) |
Destroy the session and clear the session cookie.
Removes all stored session data and sets a Set-Cookie header with an expired session ID to instruct the client to delete it.
| c | The request context. |
Destroy the session and clear the session cookie.
Removes the session from the global store, frees all its key-value data items and the session struct itself, clears the "_session" context entry, and sets an empty session cookie with a negative max-age to instruct the client to delete it.
| c | The request context. |
| void * csilk_session_get | ( | csilk_ctx_t * | c, |
| const char * | key | ||
| ) |
Retrieve a value from the session.
| c | The request context. |
| key | Key name. |
Searches the current session's data list for the given key and returns its associated value.
| c | The request context (used to look up the session). |
| key | Null-terminated key string. Must not be NULL. |
| void csilk_session_init | ( | void | ) |
Initialise the session subsystem (call once at startup).
Must be called before any request handling. Sets up the session ID generator and storage backend.
Initialise the session subsystem (call once at startup).
Performs an immediate cleanup of any expired sessions from the store. This should be called once during server startup.
| void csilk_session_set | ( | csilk_ctx_t * | c, |
| const char * | key, | ||
| void * | value | ||
| ) |
Store a value in the session.
| c | The request context. |
| key | Key name (copied internally). |
| value | Opaque value pointer (ownership remains with caller). |
If the key already exists in the current session, its value is replaced. Otherwise, a new key-value pair is prepended to the session's data list.
| c | The request context (used to look up the session via csilk_get(c, "_session")). |
| key | Null-terminated key string. Must not be NULL. |
| value | Opaque pointer to the value to store. May be NULL. |
| void csilk_session_start | ( | csilk_ctx_t * | c | ) |
Start or resume a session for the current request.
If the client sent a session cookie, the existing session is loaded. Otherwise a new session is created and a Set-Cookie header is added.
| c | The request context. |
Looks for an existing session cookie named "csilk_session". If a valid session is found, its expiry is extended by SESSION_TTL seconds. If not, a new session is created with a fresh UUID, stored in the global list, and a session cookie is set on the response. The session pointer is stored in the context under the key "_session".
| c | The request context. |
| void csilk_set | ( | csilk_ctx_t * | c, |
| const char * | key, | ||
| void * | value | ||
| ) |
Store an opaque value in the request context.
The key string is duplicated into the request arena. The value pointer is stored as-is — the context does NOT take ownership. The caller must ensure the pointed-to data remains valid at least until csilk_ctx_cleanup.
| c | The request context. |
| key | NUL-terminated key name (a copy is made internally). |
| value | Opaque pointer to store. May be NULL (which will be returned by csilk_get, so storing NULL is indistinguishable from "not set" — avoid it). |
Store an opaque value in the request context.
If a storage driver is set on the context, delegates to it. Otherwise, uses a simple linked list allocated from the arena. If the key already exists, its value is replaced. There is a hard limit of 64 storage items per request to prevent excessive arena consumption.
| c | The request context. |
| key | Storage key (null-terminated string). |
| value | Opaque pointer to store (may be NULL to clear a previous value). |
| void csilk_set_async | ( | csilk_ctx_t * | c, |
| int | is_async | ||
| ) |
Enable or disable asynchronous response mode.
When async mode is enabled the framework will NOT automatically flush the response after the handler chain returns. The handler is responsible for calling csilk_response_write / csilk_response_end at a later time (e.g., after an async I/O operation completes).
| c | The request context. |
| is_async | 1 to enable async mode, 0 to disable (default). |
Enable or disable asynchronous response mode.
When a response is asynchronous, the framework will NOT automatically send the response after the handler chain completes. The handler is responsible for calling _csilk_send_response() or _csilk_send_data() explicitly after the async operation finishes.
| c | The request context. |
| is_async | 1 to enable async mode, 0 to disable. |
| void csilk_set_cookie | ( | csilk_ctx_t * | c, |
| const char * | name, | ||
| const char * | value, | ||
| int | max_age, | ||
| const char * | path, | ||
| const char * | domain, | ||
| int | secure, | ||
| int | http_only | ||
| ) |
Set a cookie in the Set-Cookie response header.
Appends a Set-Cookie header (using csilk_add_header so multiple cookies are preserved).
| c | The request context. |
| name | Cookie name (not URL-encoded — the caller must encode if needed). |
| value | Cookie value (not URL-encoded). |
| max_age | Lifetime in seconds: >0 = max age, 0 = session cookie, -1 = immediate expiry (delete). |
| path | Cookie path scope, or NULL for "/". |
| domain | Cookie domain scope, or NULL for current host. |
| secure | Non-zero adds the Secure flag (HTTPS only). |
| http_only | Non-zero adds the HttpOnly flag (not accessible to JS). |
Set a cookie in the Set-Cookie response header.
Constructs a properly formatted Set-Cookie header with the given name, value, and attributes. The cookie is added using csilk_add_header() so multiple cookies can be set on the same response.
| c | The request context. |
| name | Cookie name (cannot be NULL). |
| value | Cookie value (cannot be NULL). |
| max_age | Cookie Max-Age in seconds. Pass 0 to omit, negative for immediate expiry (Max-Age=0), positive for a future expiry. |
| path | Cookie path (pass NULL for default "/"). |
| domain | Cookie domain (pass NULL to omit). |
| secure | If non-zero, adds the Secure flag. |
| http_only | If non-zero, adds the HttpOnly flag. |
| void csilk_set_file_response | ( | csilk_ctx_t * | c, |
| int | fd, | ||
| size_t | offset, | ||
| size_t | size | ||
| ) |
Set the zero-copy file response parameters.
Configures the context to send a file using platform-native zero-copy mechanisms (e.g., sendfile). This should be used in conjunction with setting the response as asynchronous.
| c | The request context. |
| fd | Open file descriptor (O_RDONLY). |
| offset | Starting byte offset in the file. |
| size | Number of bytes to send. |
Set the zero-copy file response parameters.
| c | The request context. |
| fd | Open file descriptor. |
| offset | Byte offset to start sending. |
| size | Number of bytes to send. |
| void csilk_set_header | ( | csilk_ctx_t * | c, |
| const char * | key, | ||
| const char * | value | ||
| ) |
Set (or overwrite) a response header.
If the header already exists its value is replaced. Key and value are copied into the request arena.
| c | The request context. |
| key | The header field name. |
| value | The header field value. |
Set (or overwrite) a response header.
| c | The request context. |
| key | Header key. |
| value | Header value. |
| void csilk_set_on_ws_message | ( | csilk_ctx_t * | c, |
| void(*)(csilk_ctx_t *c, const uint8_t *payload, size_t len, int opcode) | callback | ||
| ) |
Register a callback for incoming WebSocket messages.
Must be called after csilk_ws_handshake and before the event loop delivers data. The callback receives the context, payload bytes, payload length, and the WebSocket opcode.
| c | The request context. |
| cb | Callback function invoked for each received message. The callback must not block; it runs on the event-loop thread. |
The callback is invoked for each data frame received on the WebSocket connection. It receives the context, payload pointer, payload length, and the WebSocket opcode (0x01 for text, 0x02 for binary).
| c | The request context. |
| cb | Callback function. It receives the context, a pointer to the unmasked payload data, the payload length, and the frame opcode. |
| void csilk_set_on_ws_send | ( | csilk_ctx_t * | c, |
| void(*)(csilk_ctx_t *c, const uint8_t *payload, size_t len, int opcode) | callback | ||
| ) |
Set a callback for outgoing WebSocket frames (for testing).
| void csilk_set_request_header | ( | csilk_ctx_t * | c, |
| const char * | key, | ||
| const char * | value | ||
| ) |
Set (or overwrite) a request header.
The key and value are copied into the request arena.
| c | The request context. |
| key | The header field name. |
| value | The header field value. |
Set (or overwrite) a request header.
| c | The request context. |
| key | Header key (case-insensitive for matching on subsequent lookups). |
| value | Header value. |
| void csilk_set_request_id | ( | csilk_ctx_t * | c, |
| const char * | id | ||
| ) |
Set the request unique identifier.
| c | The request context. |
| id | The new request ID string. It is copied into the context. |
Set the request unique identifier.
| c | The request context. |
| id | The new UUID string (will be truncated to 36 chars). |
| void csilk_set_response_body | ( | csilk_ctx_t * | c, |
| const char * | body, | ||
| size_t | len, | ||
| int | managed | ||
| ) |
Overwrite the response body from middleware.
Useful for middleware that transforms the response (e.g., gzip compression, response transformation). If managed is 1 the framework takes ownership and calls free() when the response is sent.
| c | The request context. |
| body | Pointer to the new body data. |
| len | Byte length of body. |
| managed | Ownership flag: 1 = framework calls free(body) when done, 0 = caller retains ownership and body must stay valid until the response is sent. |
Overwrite the response body from middleware.
Replaces any existing response body. If the old body was marked as managed it is freed before replacement. The caller specifies whether the new body should be freed automatically during cleanup.
| c | The request context. |
| body | Pointer to the body data (may be NULL). |
| len | Body length in bytes. |
| managed | If non-zero, the framework will free body during cleanup. |
| void csilk_set_sse | ( | csilk_ctx_t * | c, |
| int | is_sse | ||
| ) |
Enable or disable Server-Sent Events (SSE) mode.
When SSE mode is active the framework will not automatically close the connection after the handler returns.
| c | The request context. |
| is_sse | 1 to enable SSE mode, 0 to disable. |
Enable or disable Server-Sent Events (SSE) mode.
| c | The request context. |
| is_sse | 1 to enable, 0 to disable. |
| void csilk_set_websocket | ( | csilk_ctx_t * | c, |
| int | is_websocket | ||
| ) |
Enable or disable WebSocket mode.
| c | The request context. |
| is_websocket | 1 to enable, 0 to disable. |
Enable or disable WebSocket mode.
| c | The request context. |
| is_websocket | 1 to enable, 0 to disable. |
| void csilk_split_url | ( | const char * | url, |
| char ** | path, | ||
| char ** | query | ||
| ) |
Split a URL into path and query-string components.
Internal helper. The returned path and query point into the original url string (the '?' separator is overwritten with NUL).
| url | Full URL string (will be modified in-place). | |
| [out] | path | Receives a pointer to the path portion inside url. |
| [out] | query | Receives a pointer to the query portion inside url, or NULL if no query was present. |
Split a URL into path and query-string components.
Finds the first '?' separator. The path portion is URL-decoded and returned in path. The query portion (everything after '?') is returned raw in query (NOT URL-decoded — use csilk_parse_query() for that). If there is no '?', the entire URL is treated as the path and query is set to NULL.
| url | Full URL string (e.g., "/foo/bar?key=val"). |
| path | [out] Receives a malloc'd, URL-decoded path string. |
| query | [out] Receives a malloc'd raw query string, or NULL if no query was present. |
| void csilk_sse_close | ( | csilk_ctx_t * | c | ) |
Close the SSE connection.
Sends any remaining buffered data and closes the TCP connection.
| c | The request context. |
Closes the underlying libuv stream handle for the SSE client connection. Performs a graceful close via uv_close(). Any pending write requests will complete before the handle is fully closed.
| c | The request context (must be in SSE mode with an active client). |
| void csilk_sse_init | ( | csilk_ctx_t * | c | ) |
Initialise a Server-Sent Events connection.
Sends the HTTP 200 response with Content-Type: text/event-stream and disables request buffering. Must be called at the start of an SSE handler before any csilk_sse_send calls.
| c | The request context. |
Initialise a Server-Sent Events connection.
Sets the Content-Type, Cache-Control, Connection, and X-Accel-Buffering headers, marks the context as an SSE connection (is_sse = 1), and writes the raw HTTP 200 OK response headers directly to the client socket.
| c | The request context. |
| void csilk_sse_send | ( | csilk_ctx_t * | c, |
| const char * | event, | ||
| const char * | data | ||
| ) |
Send an SSE event (or comment) to the client.
Formats and flushes one SSE message. If event is NULL and data is non-NULL, a default "message" event is sent. If data is NULL, a comment line (starting with ":") is written.
| c | The request context. |
| event | Optional event type string (e.g., "update"), or NULL. |
| data | Event data string, or NULL to send a comment line. |
Send an SSE event (or comment) to the client.
Formats and writes a Server-Sent Event message to the client. If an event type is provided, an "event:" line is emitted. The data is written as a "data:" line. Both are terminated by an empty line ("\n") as required by the SSE specification (RFC 8895 §2).
| c | The request context (must be in SSE mode). |
| event | Optional event type string (e.g. "message", "update"). May be NULL, in which case no "event:" line is emitted. |
| data | The event payload string. May be NULL (produces a "data:" line with no content). Must not contain embedded "\n\n" sequences unless multi-line data is intended per SSE spec. |
| void csilk_static | ( | csilk_ctx_t * | c, |
| const char * | root_dir | ||
| ) |
Serve static files from a local directory.
Maps the current request path to a file under root_dir. If the file exists and is readable its contents are sent with the appropriate Content-Type. If not found the handler chain continues (so a 404 handler can pick it up).
| c | The request context. |
| root_dir | Absolute or relative path to the directory to serve. |
Serve static files from a local directory.
Offloads file resolution, path traversal checks, and file open/stat operations to the libuv thread pool. The response is sent via the normal _csilk_send_response() path, which sends the file using platform-specific zero-copy mechanisms (e.g. sendfile on Linux).
The URL prefix is automatically stripped from the request path before resolving against root_dir — the "static_prefix" must be set via csilk_set(c, "static_prefix", prefix_string) before calling this function.
| c | The request context. |
| root_dir | Absolute or relative path to the static file root directory. Must not be NULL. |
| void csilk_status | ( | csilk_ctx_t * | c, |
| int | status | ||
| ) |
Set the HTTP response status code.
| c | The request context. |
| status | The HTTP status code (e.g., 200, 404, 500). |
| c | The request context. |
| status | HTTP status code (e.g., 200, 404, 500). |
| void csilk_string | ( | csilk_ctx_t * | c, |
| int | status, | ||
| const char * | msg | ||
| ) |
Set a plain-text response body and status code.
The msg string is copied into the request arena so the caller's buffer can be reused immediately. Equivalent to calling csilk_status then setting the response body.
| c | The request context. |
| status | The HTTP status code. |
| msg | The plain-text body string (NUL-terminated). |
Set a plain-text response body and status code.
If the context has an arena allocator, the body string is duplicated into arena memory. Otherwise, it falls back to strdup() and marks the body as managed (so it will be freed during cleanup). The Content-Type header is NOT set automatically — callers should set it explicitly if needed.
| c | The request context. |
| status | HTTP status code for the response. |
| msg | Plain text body (may be NULL). |
| const char * csilk_validate | ( | csilk_ctx_t * | c, |
| const csilk_valid_rule_t * | rules | ||
| ) |
Validate request parameters against a set of rules.
Iterates through the rule array and checks each field for presence, type, and range constraints. Returns the name of the first field that fails validation.
| c | The request context. |
| rules | NULL-terminated array of csilk_valid_rule_t. The array must end with an entry whose field field is NULL. |
field name (the returned pointer points into the rule array, not into the context).Validate request parameters against a set of rules.
Iterates through an array of validation rules, stopping at the first rule that fails. Each rule specifies the source of the value (query, form, header, cookie, or automatic fallback) and the validation flags to apply (CSILK_VALID_REQUIRED, CSILK_VALID_INT, CSILK_VALID_STRING, CSILK_VALID_EMAIL).
For integer validation, an optional [min, max] range can be specified. For string validation, an optional [min, max] length range can be specified. Ranges are ignored when min >= max.
| c | The request context to extract values from. |
| rules | A null-terminated array of csilk_valid_rule_t rules (the last entry must have field == NULL). Must not be NULL. |
| void csilk_ws_broadcast_room | ( | csilk_ctx_t * | c, |
| const char * | room_name, | ||
| const char * | message | ||
| ) |
Broadcast a message to all WebSockets in a room via MQ.
| c | Request context (used to access the server's MQ). |
| room_name | Room to broadcast to. |
| message | NUL-terminated message string. |
| void csilk_ws_close | ( | csilk_ctx_t * | c, |
| uint16_t | status_code, | ||
| const char * | reason | ||
| ) |
Send a WebSocket close frame.
Initiates the close handshake per RFC 6455 §5.5.1. After sending, the server waits for the client's close frame before fully closing the TCP connection.
| c | The request context. |
| status_code | Close status code (e.g., 1000 for normal closure, 0 to omit the status code from the frame). |
| reason | Optional human-readable reason string (may be NULL). |
Send a WebSocket close frame.
Constructs and sends a close frame with an optional status code and reason string. The payload is limited to 125 bytes (close frame + reason). After sending, the connection is NOT immediately closed — the peer is expected to respond with its own close frame.
| c | The request context. |
| status_code | WebSocket close status code (e.g., 1000 for normal, 1001 for "going away"). Pass 0 to omit the status code. |
| reason | Human-readable reason string (may be NULL). |
| void csilk_ws_handshake | ( | csilk_ctx_t * | c | ) |
Perform the WebSocket upgrade handshake (HTTP Upgrade request).
Validates the Upgrade, Connection, Sec-WebSocket-Key, and version headers, computes the Sec-WebSocket-Accept response, and sends a 101 Switching Protocols response. After success, csilk_is_websocket returns 1 and the connection can send/receive frames.
| c | The request context. |
Perform the WebSocket upgrade handshake (HTTP Upgrade request).
Validates the presence of the Sec-WebSocket-Key header, computes the expected Sec-WebSocket-Accept response by concatenating the key with the WebSocket GUID ("258EAFA5-E914-47DA-95CA-C5AB0DC85B11"), SHA-1 hashing the result, and Base64-encoding the digest. Sets the Upgrade, Connection, and Sec-WebSocket-Accept response headers, sets status to 101 Switching Protocols, and marks the context as a WebSocket connection.
| c | The request context. |
| void csilk_ws_join_room | ( | csilk_ctx_t * | c, |
| const char * | room_name | ||
| ) |
Join a WebSocket client to a room.
| c | Request context (must be a WebSocket). |
| room_name | Name of the room to join. |
| void csilk_ws_leave_room | ( | csilk_ctx_t * | c, |
| const char * | room_name | ||
| ) |
Remove a WebSocket client from a room.
| c | Request context. |
| room_name | Name of the room to leave. |
| void csilk_ws_send | ( | csilk_ctx_t * | c, |
| const uint8_t * | payload, | ||
| size_t | len, | ||
| int | opcode | ||
| ) |
Send a WebSocket data frame.
Encodes and sends a single WebSocket frame per RFC 6455. Masks the payload if required (client-to-server masking).
| c | The request context. |
| payload | Raw data to send. |
| len | Byte length of payload. |
| opcode | WebSocket opcode: 0x1 for text, 0x2 for binary, 0x9 for ping. |
Send a WebSocket data frame.
Constructs a WebSocket frame with the FIN bit set (final fragment), the specified opcode (0x01 for text, 0x02 for binary), and no masking (server-to-client frames are unmasked per RFC 6455). Supports payload lengths up to 2^64-1 using 7-bit, 16-bit, or 64-bit extended length fields as appropriate.
| c | The request context (must have _internal_client set). |
| payload | Frame payload data. |
| len | Payload length in bytes. |
| opcode | WebSocket opcode (0x01 for text, 0x02 for binary). |
| void(*)(csilk_ctx_t *c, const uint8_t *payload, size_t len, int opcode) csilk_get_on_ws_message(csilk_ctx_t *c) | ( | csilk_ctx_t * | c | ) |
Get the currently registered WebSocket message callback.
| c | The request context. |