|
Csilk 0.2.1
A lightweight, high-performance C HTTP web framework
|
Request/response context implementation. More...
#include <ctype.h>#include <stddef.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <strings.h>#include <uv.h>#include "context_internal.h"#include "csilk/core/internal.h"#include "csilk/csilk.h"#include "server_internal.h"
Functions | |
| static uint32_t | hash_key (const char *key) |
| Hash a header key string into a bucket index using djb2. | |
| static const char * | map_get (csilk_header_map_t *map, const char *key) |
| Look up a header value by key in the hash map (case-insensitive). | |
| static void | map_set (csilk_ctx_t *c, csilk_header_map_t *map, const char *key, const char *value) |
| Set a header value in the hash map, overwriting any existing entry. | |
| static void | map_add (csilk_ctx_t *c, csilk_header_map_t *map, const char *key, const char *value) |
| Add a header value to the hash map, allowing duplicate keys. | |
| void | csilk_next (csilk_ctx_t *c) |
| Advance to the next handler in the chain and invoke it. | |
| void | csilk_abort (csilk_ctx_t *c) |
| Abort the handler chain immediately. | |
| 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 the response body as plain text with a status code. | |
| const char * | csilk_get_param (csilk_ctx_t *c, const char *key) |
| Get a URL path parameter value by name. | |
| int | csilk_get_params_count (csilk_ctx_t *c) |
| Get the count of path parameters. | |
| const char * | csilk_get_param_key (csilk_ctx_t *c, int index) |
| Get the name of a parameter by index. | |
| const char * | csilk_get_param_value (csilk_ctx_t *c, int index) |
| Get the value of a parameter by index. | |
| const char * | csilk_get_header (csilk_ctx_t *c, const char *key) |
| Get a request header value by key (case-insensitive). | |
| const char * | csilk_get_response_header (csilk_ctx_t *c, const char *key) |
| Get a response header value by key (case-insensitive). | |
| const char * | csilk_get_query (csilk_ctx_t *c, const char *key) |
| Get a query parameter value by key. | |
| void | csilk_set_request_header (csilk_ctx_t *c, const char *key, const char *value) |
| Set a request header, overwriting any existing value for the same key. | |
| void | csilk_set_header (csilk_ctx_t *c, const char *key, const char *value) |
| Set a response header, overwriting any existing value for the same key. | |
| void | csilk_ctx_cleanup (csilk_ctx_t *c) |
| Clean up request context resources between requests. | |
| 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 URL path of the current request. | |
| const char * | csilk_get_body (csilk_ctx_t *c, size_t *out_len) |
| Get the request body data and optionally its length. | |
| size_t | csilk_get_body_len (csilk_ctx_t *c) |
| Get the length of the request body. | |
| int | csilk_is_websocket (csilk_ctx_t *c) |
| Check if the current request is a WebSocket upgrade. | |
| void | csilk_set_websocket (csilk_ctx_t *c, int is_websocket) |
| Enable/disable WebSocket mode. | |
| int | csilk_is_sse (csilk_ctx_t *c) |
| Check if the current connection is a Server-Sent Events stream. | |
| void | csilk_set_sse (csilk_ctx_t *c, int is_sse) |
| Enable/disable SSE mode. | |
| void * | _csilk_get_internal_client (csilk_ctx_t *c) |
| Get the internal client connection handle. | |
| void | _csilk_set_internal_client (csilk_ctx_t *c, void *client) |
| Set the internal client connection handle. | |
| const char * | csilk_get_request_id (csilk_ctx_t *c) |
| Get the unique request ID string. | |
| csilk_arena_t * | csilk_get_arena (csilk_ctx_t *c) |
| Get the arena allocator associated with the context. | |
| int | csilk_get_status (csilk_ctx_t *c) |
| Get the currently set response status code. | |
| void | csilk_set_async (csilk_ctx_t *c, int is_async) |
| Mark the response as asynchronous (sent later, not automatically). | |
| csilk_server_t * | csilk_ctx_get_server (csilk_ctx_t *c) |
| Get the server instance owning this context. | |
| csilk_mq_t * | csilk_ctx_get_mq (csilk_ctx_t *c) |
| Get the internal MQ instance from the context. | |
| int | csilk_is_async (csilk_ctx_t *c) |
| Check if the response is in async mode. | |
| int | csilk_get_handler_index (csilk_ctx_t *c) |
| Get the handler chain index. | |
| void | csilk_set_request_id (csilk_ctx_t *c, const char *id) |
| Set the request UUID. | |
| uv_work_t * | csilk_get_work_req (csilk_ctx_t *c) |
| Get the internal libuv work request. | |
| void | csilk_set_file_response (csilk_ctx_t *c, int fd, size_t offset, size_t size) |
| Configure zero-copy file transmission. | |
| int | csilk_get_file_fd (csilk_ctx_t *c) |
| Get the zero-copy file descriptor. | |
| const char * | csilk_ctx_get_handler_path (csilk_ctx_t *c) |
| Get the route pattern for the current request. | |
| const char * | csilk_ctx_get_handler_perm_required (csilk_ctx_t *c) |
| Get the permission required by the current handler. | |
| const char * | csilk_ctx_get_handler_perm_resource (csilk_ctx_t *c) |
| Get the resource pattern for the current handler's permission check. | |
| 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_set_response_body (csilk_ctx_t *c, const char *body, size_t len, int managed) |
| Set the response body directly with explicit ownership semantics. | |
| int | csilk_is_aborted (csilk_ctx_t *c) |
| Check if the client has disconnected (connection 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). | |
| void | _csilk_ctx_init (csilk_ctx_t *c, struct csilk_server_s *s, void *client) |
| Initialize a request context. | |
| void | csilk_ctx_set_storage_driver (csilk_ctx_t *c, csilk_storage_driver_t *driver) |
| Set the storage driver. | |
| void | csilk_ctx_set_crypto_driver (csilk_ctx_t *c, csilk_crypto_driver_t *driver) |
| Set the crypto driver. | |
| void | csilk_ctx_set_cipher_driver (csilk_ctx_t *c, csilk_cipher_driver_t *driver) |
| Set the cipher driver. | |
| void | csilk_redirect (csilk_ctx_t *c, int status, const char *location) |
| Redirect the client to a different URL with a specific status code. | |
| void | csilk_redirect_simple (csilk_ctx_t *c, const char *url) |
| Redirect to another URL using the default status code 302 (Found). | |
| void | csilk_set (csilk_ctx_t *c, const char *key, void *value) |
| Store a value in the context's key-value storage. | |
| void * | csilk_get (csilk_ctx_t *c, const char *key) |
| Retrieve a value from the context's key-value storage. | |
| cJSON * | csilk_bind_json (csilk_ctx_t *c) |
| Parse the request body as JSON using cJSON. | |
| cJSON * | csilk_bind_json_err (csilk_ctx_t *c, const char **error) |
| Parse the request body as JSON with detailed error feedback. | |
| const char * | csilk_get_cookie (csilk_ctx_t *c, const char *name) |
| Get a cookie value by its name from the Cookie header. | |
| void | csilk_add_header (csilk_ctx_t *c, const char *key, const char *value) |
| Add a response header, allowing multiple values for the same key. | |
| 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 response via Set-Cookie header. | |
| void | csilk_json (csilk_ctx_t *c, int status, cJSON *json) |
| Send a JSON response. The cJSON object is freed by this call. | |
| void | csilk_json_error (csilk_ctx_t *c, int status, const char *message) |
| Send a JSON error response containing an "error" field. | |
| int | csilk_bind_reflect (csilk_ctx_t *c, const char *type_name, void *ptr) |
| Bind the request body JSON to a registered struct via reflection. | |
| void | csilk_json_reflect (csilk_ctx_t *c, int status, const char *type_name, const void *ptr) |
| Send a JSON response from a registered struct via reflection. | |
| void | csilk_parse_query (csilk_ctx_t *c, const char *query_string) |
| Parse a raw query string into the context's query_params hash map. | |
| 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. | |
| static void | on_stream_write (uv_write_t *req, int status) |
| libuv write completion callback for streaming (non-terminal) writes. | |
| static int | client_wants_close (csilk_ctx_t *c) |
| Check if the client requested "Connection: close" in the request. | |
| static void | on_stream_end_write (uv_write_t *req, int status) |
| libuv write completion callback for a terminal chunk — closes the connection. | |
| static int | send_chunked_headers (csilk_ctx_t *c) |
| Send HTTP response headers with Transfer-Encoding: chunked. | |
| static void | write_chunk_frame (csilk_ctx_t *c, const uint8_t *data, size_t len) |
| Write a single chunked transfer frame: [hex-size]\r\n[data]\r\n. | |
| void | csilk_response_write (csilk_ctx_t *c, const uint8_t *data, size_t len) |
| Write data to a streaming response using chunked transfer encoding. | |
| void | csilk_response_end (csilk_ctx_t *c) |
| Finalize a streaming response by sending the terminal chunk. | |
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 registered WebSocket callback. | |
Request/response context implementation.
Provides the per-request csilk_ctx_t lifecycle: header hash-map operations (djb2-based, case-insensitive), request/body management, response status and body setup, query parameter parsing, async/chunked response support, and context cleanup.
Key design points:
| void _csilk_ctx_init | ( | csilk_ctx_t * | c, |
| struct csilk_server_s * | s, | ||
| void * | client | ||
| ) |
Initialize a request context.
Internal context initialiser.
Sets up default values for all fields. Should be called for both static (embedded in client) and dynamic (H2 stream) contexts.
| c | The context to initialize. |
| s | The owning server instance. |
| client | The underlying connection object (csilk_client_t*). |
| void * _csilk_get_internal_client | ( | csilk_ctx_t * | c | ) |
Get the internal client connection handle.
Get the internal client connection object.
| c | The request context. |
| void _csilk_set_internal_client | ( | csilk_ctx_t * | c, |
| void * | client | ||
| ) |
Set the internal client connection handle.
Set the internal client connection object.
| c | The request context. |
| client | Opaque pointer to csilk_client_t. |
|
static |
Check if the client requested "Connection: close" in the request.
Examines the "Connection" request header for a value of "close" (case-insensitive).
| c | The request context. |
| void csilk_abort | ( | csilk_ctx_t * | c | ) |
Abort the handler chain immediately.
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 | ||
| ) |
Add a response header, allowing multiple values for the same key.
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. |
| cJSON * csilk_bind_json | ( | csilk_ctx_t * | c | ) |
Parse the request body as JSON using cJSON.
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 | ||
| ) |
Parse the request body as JSON with detailed error feedback.
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 | ||
| ) |
Bind the request body JSON to a registered struct via reflection.
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_ctx_cleanup | ( | csilk_ctx_t * | c | ) |
Clean up request context resources between requests.
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 current request.
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 required by the current handler.
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 current handler's permission check.
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 owning this 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.
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.
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.
Set the storage driver for the context.
| c | The request context. |
| driver | Pointer to driver vtable. |
| void * csilk_get | ( | csilk_ctx_t * | c, |
| const char * | key | ||
| ) |
Retrieve a value from the context's key-value storage.
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 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 request body data and optionally its 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 request body.
Get the length of the raw request body.
| c | The request context. |
| const char * csilk_get_cookie | ( | csilk_ctx_t * | c, |
| const char * | name | ||
| ) |
Get a cookie value by its name from the Cookie header.
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 zero-copy file descriptor.
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.
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 handler chain index.
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 key (case-insensitive).
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.
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 value by name.
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 parameter by index.
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 parameter by index.
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 count of path parameters.
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 URL path of the current request.
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 parameter value by key.
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 request ID string.
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 key (case-insensitive).
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 currently set response status code.
Get the current response status code.
| c | The request context. |
| uv_work_t * csilk_get_work_req | ( | csilk_ctx_t * | c | ) |
Get the internal libuv work request.
Get the libuv work request associated with the context.
| c | The request context. |
| int csilk_is_aborted | ( | csilk_ctx_t * | c | ) |
Check if the client has disconnected (connection aborted).
Check whether the handler chain has been aborted.
| c | The request context. |
| int csilk_is_async | ( | csilk_ctx_t * | c | ) |
Check if the response is in async mode.
Check whether asynchronous response mode is enabled.
| c | The request context. |
| int csilk_is_sse | ( | csilk_ctx_t * | c | ) |
Check if the current connection is a Server-Sent Events stream.
Check whether the connection is in Server-Sent Events mode.
| c | The request context. |
| int csilk_is_websocket | ( | csilk_ctx_t * | c | ) |
Check if the current request is a WebSocket upgrade.
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. The cJSON object is freed by this call.
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 error response containing an "error" field.
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 | ||
| ) |
Send a JSON response from a registered struct via reflection.
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. |
| void csilk_next | ( | csilk_ctx_t * | c | ) |
Advance to the next handler in the chain and invoke it.
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_parse_form_urlencoded | ( | csilk_ctx_t * | c | ) |
Parse the request body as application/x-www-form-urlencoded.
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 into the context's query_params hash map.
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_redirect | ( | csilk_ctx_t * | c, |
| int | status, | ||
| const char * | location | ||
| ) |
Redirect the client to a different URL with a specific status code.
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 | ||
| ) |
Redirect to another URL using the default status code 302 (Found).
Send a simple 302 Found redirect.
Convenience wrapper around csilk_redirect().
| c | The request context. |
| url | The target URL for the redirect. |
| void csilk_response_end | ( | csilk_ctx_t * | c | ) |
Finalize a streaming response by sending the terminal chunk.
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 data to a streaming response using chunked transfer encoding.
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_set | ( | csilk_ctx_t * | c, |
| const char * | key, | ||
| void * | value | ||
| ) |
Store a value in the context's key-value storage.
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 | ||
| ) |
Mark the response as asynchronous (sent later, not automatically).
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 response via Set-Cookie header.
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 | ||
| ) |
Configure zero-copy file transmission.
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 a response header, overwriting any existing value for the same key.
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.
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 a request header, overwriting any existing value for the same key.
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 UUID.
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 | ||
| ) |
Set the response body directly with explicit ownership semantics.
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/disable SSE mode.
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/disable WebSocket mode.
Enable or disable WebSocket mode.
| c | The request context. |
| is_websocket | 1 to enable, 0 to disable. |
| void csilk_status | ( | csilk_ctx_t * | c, |
| int | status | ||
| ) |
Set the HTTP response status code.
| 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 the response body as plain text with a status code.
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). |
|
static |
Hash a header key string into a bucket index using djb2.
Applies the djb2 hash algorithm with case-insensitive character folding (via tolower()) so that "Content-Type" and "content-type" map to the same bucket. This ensures consistent lookups regardless of header casing.
| key | Header key string (null-terminated). |
key is non-NULL.
|
static |
Add a header value to the hash map, allowing duplicate keys.
Unlike map_set(), this function does NOT search for an existing entry with the same key. It always prepends a new header node, so multiple calls with the same key produce multiple entries (e.g., multiple Set-Cookie headers).
| c | Request context for arena-based memory allocation. |
| map | Header hash map. |
| key | Header key. |
| value | Header value. |
|
static |
Look up a header value by key in the hash map (case-insensitive).
Iterates the linked list at the hashed bucket and compares keys using strcasecmp. Returns the first matching value.
| map | Header hash map (must not be NULL). |
| key | Header key to find (case-insensitive). |
|
static |
Set a header value in the hash map, overwriting any existing entry.
Hashes the key, searches the bucket for an existing entry, and replaces its value. If no entry is found, a new header node is allocated via the context's arena allocator and prepended to the bucket's linked list.
| c | Request context used for arena-based memory allocation. |
| map | Header hash map (request or response headers). |
| key | Header key (case-insensitive via strcasecmp on lookup). |
| value | Header value string. |
|
static |
libuv write completion callback for a terminal chunk — closes the connection.
Frees the write buffer and request structure, then closes the underlying handle. This is used for the final chunk of a streaming response.
| req | The completed write request (freed by this callback). |
| status | UV status code (negative indicates error). |
|
static |
libuv write completion callback for streaming (non-terminal) writes.
Frees the write buffer and request structure. On error, logs to stderr. Does NOT close the connection — terminal writes use on_stream_end_write().
| req | The completed write request (freed by this callback). |
| status | UV status code (negative indicates error). |
|
static |
Send HTTP response headers with Transfer-Encoding: chunked.
Constructs and sends the HTTP status line, chunked transfer-encoding header, connection header (keep-alive or close), and all custom response headers. This is automatically called on the first call to csilk_response_write() if the response has not started yet.
| c | Request context. |
|
static |
Write a single chunked transfer frame: [hex-size]\r\n[data]\r\n.
Formats the data length as a hex string, prepends it, appends the trailing CRLF, and sends the complete frame via _csilk_send_data(). The frame buffer is heap-allocated and freed after sending.
| c | Request context. |
| data | Payload data for this chunk. |
| len | Length of payload in bytes. |
| 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 registered WebSocket callback.
| c | The request context. |