Added more documentation to kcgi opcodes. No code changes. (0.41.10)
This commit is contained in:
parent
fdaed27527
commit
303e48d37e
2 changed files with 125 additions and 3 deletions
4
Doxyfile
4
Doxyfile
|
|
@ -48,7 +48,7 @@ PROJECT_NAME = "Fun API Documentation"
|
||||||
# could be handy for archiving the generated documentation or if some version
|
# could be handy for archiving the generated documentation or if some version
|
||||||
# control system is used.
|
# control system is used.
|
||||||
|
|
||||||
PROJECT_NUMBER = 0.41.8
|
PROJECT_NUMBER = 0.41.10
|
||||||
|
|
||||||
# Using the PROJECT_BRIEF tag one can provide an optional one line description
|
# Using the PROJECT_BRIEF tag one can provide an optional one line description
|
||||||
# for a project that appears at the top of each page and should give viewers a
|
# for a project that appears at the top of each page and should give viewers a
|
||||||
|
|
@ -1131,7 +1131,7 @@ RECURSIVE = YES
|
||||||
# Note that relative paths are relative to the directory from which Doxygen is
|
# Note that relative paths are relative to the directory from which Doxygen is
|
||||||
# run.
|
# run.
|
||||||
|
|
||||||
EXCLUDE =
|
EXCLUDE = src/vm
|
||||||
|
|
||||||
# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
|
# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
|
||||||
# directories that are symbolic links (a Unix file system feature) are excluded
|
# directories that are symbolic links (a Unix file system feature) are excluded
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,46 @@
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @file kcgi.c
|
* @file kcgi.c
|
||||||
* @brief kcgi helpers for Fun VM KCGI-related opcodes (conditional build).
|
* @brief Thin kcgi integration helpers used by VM opcodes under src/vm/kcgi/.
|
||||||
|
*
|
||||||
|
* This module centralizes compact helpers around the kcgi API so the VM
|
||||||
|
* opcode snippets included by vm.c can remain minimal and focus on stack
|
||||||
|
* marshalling. The helpers here do not depend on VM internals beyond the
|
||||||
|
* Value conversion utilities used to represent HTTP requests as Fun values.
|
||||||
|
* Keeping the external-API specifics in src/extensions/ mirrors other
|
||||||
|
* integrations (OpenSSL, PCRE2, SQLite, XML2, JSON, INI) and improves
|
||||||
|
* maintainability.
|
||||||
|
*
|
||||||
|
* Build-time feature flag:
|
||||||
|
* - All code in this file is compiled only when FUN_WITH_KCGI is enabled.
|
||||||
|
* When disabled, the file provides no symbols and VM opcodes compiled
|
||||||
|
* from src/vm/kcgi/*.c will fall back to no-op/falsey behaviors as
|
||||||
|
* documented in those opcode snippets.
|
||||||
|
*
|
||||||
|
* Ownership and memory model:
|
||||||
|
* - kcgi_parse_request() allocates a struct kreq via khttp_parse() and, on
|
||||||
|
* success, returns it through the out-parameter; the caller takes ownership
|
||||||
|
* and must later release it with kcgi_free_request().
|
||||||
|
* - kcgi_free_request() calls khttp_free() and then frees the allocation
|
||||||
|
* wrapper used by this module.
|
||||||
|
* - kcgi_write_str() does not take ownership of the input string; it may be
|
||||||
|
* NULL, which is treated as an empty string.
|
||||||
|
* - kreq_to_fun() and kcgi_fields_to_map() create Fun Values following the
|
||||||
|
* VM's normal ownership semantics (returned by value to the caller).
|
||||||
|
*
|
||||||
|
* Global state and lifetime:
|
||||||
|
* - A thread-local pointer g_kcgi_req holds the current request for the
|
||||||
|
* active CGI handling context. VM opcodes are responsible for setting and
|
||||||
|
* clearing this pointer by calling the helpers exposed here.
|
||||||
|
*
|
||||||
|
* Error handling:
|
||||||
|
* - Functions return 0/NULL on failure and non-zero/valid objects on success.
|
||||||
|
* Callers should check return values before use. No errno is set.
|
||||||
|
*
|
||||||
|
* Thread-safety:
|
||||||
|
* - The request handle is stored in a thread-local variable to isolate state
|
||||||
|
* between concurrent executions. Helpers otherwise maintain no global
|
||||||
|
* mutable state.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifdef FUN_WITH_KCGI
|
#ifdef FUN_WITH_KCGI
|
||||||
|
|
@ -25,6 +64,24 @@ static __declspec(thread) struct kreq *g_kcgi_req = NULL;
|
||||||
static __thread struct kreq *g_kcgi_req = NULL;
|
static __thread struct kreq *g_kcgi_req = NULL;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert kcgi form/query fields to a Fun map Value.
|
||||||
|
*
|
||||||
|
* Each entry from r->fields is copied into a newly created Fun map where
|
||||||
|
* the kcgi key becomes the map key and the kcgi value becomes a Fun string.
|
||||||
|
*
|
||||||
|
* Notes:
|
||||||
|
* - If the request pointer is NULL, an empty map is returned.
|
||||||
|
* - When multiple kcgi fields share the same key, later occurrences will
|
||||||
|
* overwrite earlier ones ("last write wins").
|
||||||
|
* - Empty or NULL keys/values are converted to empty strings ("").
|
||||||
|
*
|
||||||
|
* Ownership:
|
||||||
|
* - The returned Value is owned by the caller (normal VM semantics).
|
||||||
|
*
|
||||||
|
* @param r Parsed kcgi request pointer (may be NULL).
|
||||||
|
* @return A Fun map Value containing string keys and values.
|
||||||
|
*/
|
||||||
static Value kcgi_fields_to_map(const struct kreq *r) {
|
static Value kcgi_fields_to_map(const struct kreq *r) {
|
||||||
Value m = make_map_empty();
|
Value m = make_map_empty();
|
||||||
if (!r) return m;
|
if (!r) return m;
|
||||||
|
|
@ -36,6 +93,22 @@ static Value kcgi_fields_to_map(const struct kreq *r) {
|
||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convert a kcgi request handle into a structured Fun Value.
|
||||||
|
*
|
||||||
|
* The resulting map contains at least the following keys:
|
||||||
|
* - "host": string; empty if unavailable
|
||||||
|
* - "port": int; TCP port
|
||||||
|
* - "path": string; request path
|
||||||
|
* - "suffix": string; request suffix (kcgi notion)
|
||||||
|
* - "fields": map; key/value pairs from form/query fields
|
||||||
|
*
|
||||||
|
* Missing fields from kcgi are converted to empty strings where applicable.
|
||||||
|
* If r is NULL, an empty map is returned.
|
||||||
|
*
|
||||||
|
* @param r Parsed kcgi request pointer (may be NULL).
|
||||||
|
* @return A Fun map Value describing the request.
|
||||||
|
*/
|
||||||
static Value kreq_to_fun(const struct kreq *r) {
|
static Value kreq_to_fun(const struct kreq *r) {
|
||||||
Value out = make_map_empty();
|
Value out = make_map_empty();
|
||||||
if (!r) return out;
|
if (!r) return out;
|
||||||
|
|
@ -51,6 +124,24 @@ static Value kreq_to_fun(const struct kreq *r) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Lifecycle helpers used by VM opcodes */
|
/* Lifecycle helpers used by VM opcodes */
|
||||||
|
/**
|
||||||
|
* Parse the current CGI/FCGI request using kcgi.
|
||||||
|
*
|
||||||
|
* On success, this allocates and initializes a struct kreq by calling
|
||||||
|
* khttp_parse() and stores it in *out. The caller takes ownership of the
|
||||||
|
* returned handle and must later free it with kcgi_free_request().
|
||||||
|
*
|
||||||
|
* Behavior details:
|
||||||
|
* - All keys are accepted (kvalid array with a single {NULL,NULL} entry).
|
||||||
|
* - On allocation or parse failure, *out is not modified and 0 is returned.
|
||||||
|
*
|
||||||
|
* Threading:
|
||||||
|
* - This function is independent of the thread-local g_kcgi_req; setting that
|
||||||
|
* pointer is left to the caller/opcode.
|
||||||
|
*
|
||||||
|
* @param[out] out Where to store the newly allocated struct kreq on success.
|
||||||
|
* @return 1 on success, 0 on failure.
|
||||||
|
*/
|
||||||
static int kcgi_parse_request(struct kreq **out) {
|
static int kcgi_parse_request(struct kreq **out) {
|
||||||
static const struct kvalid keys[] = { { NULL, NULL } }; /* accept all */
|
static const struct kvalid keys[] = { { NULL, NULL } }; /* accept all */
|
||||||
struct kreq *r = (struct kreq *)calloc(1, sizeof(*r));
|
struct kreq *r = (struct kreq *)calloc(1, sizeof(*r));
|
||||||
|
|
@ -61,12 +152,34 @@ static int kcgi_parse_request(struct kreq **out) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Free a request previously returned by kcgi_parse_request().
|
||||||
|
*
|
||||||
|
* Safe to call with NULL.
|
||||||
|
*
|
||||||
|
* @param r Request handle to free (may be NULL).
|
||||||
|
*/
|
||||||
static void kcgi_free_request(struct kreq *r) {
|
static void kcgi_free_request(struct kreq *r) {
|
||||||
if (!r) return;
|
if (!r) return;
|
||||||
khttp_free(r);
|
khttp_free(r);
|
||||||
free(r);
|
free(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Begin the HTTP response for the current request.
|
||||||
|
*
|
||||||
|
* This emits an optional Content-Type header and then switches into body
|
||||||
|
* mode by calling khttp_body(). If g_kcgi_req is not set, the call fails.
|
||||||
|
*
|
||||||
|
* Notes:
|
||||||
|
* - The status code parameter is currently not passed to kcgi; unless set
|
||||||
|
* elsewhere, kcgi will default the status to 200 OK.
|
||||||
|
* - If ctype is NULL or empty, no Content-Type header is emitted here.
|
||||||
|
*
|
||||||
|
* @param code Suggested HTTP status code (reserved for future use).
|
||||||
|
* @param ctype MIME type to emit as Content-Type (may be NULL/empty).
|
||||||
|
* @return 1 on success, 0 on failure.
|
||||||
|
*/
|
||||||
static int kcgi_reply_start(int code, const char *ctype) {
|
static int kcgi_reply_start(int code, const char *ctype) {
|
||||||
if (!g_kcgi_req) return 0;
|
if (!g_kcgi_req) return 0;
|
||||||
/* Emit Content-Type header; Status defaults to 200 if not set */
|
/* Emit Content-Type header; Status defaults to 200 if not set */
|
||||||
|
|
@ -79,6 +192,15 @@ static int kcgi_reply_start(int code, const char *ctype) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write a UTF-8 string to the HTTP response body.
|
||||||
|
*
|
||||||
|
* Requires an active request in g_kcgi_req and an initialized response body
|
||||||
|
* (kcgi_reply_start() or equivalent must have been called).
|
||||||
|
*
|
||||||
|
* @param s NUL-terminated string to write; NULL is treated as "".
|
||||||
|
* @return 1 on success, 0 on failure.
|
||||||
|
*/
|
||||||
static int kcgi_write_str(const char *s) {
|
static int kcgi_write_str(const char *s) {
|
||||||
if (!g_kcgi_req) return 0;
|
if (!g_kcgi_req) return 0;
|
||||||
if (!s) s = "";
|
if (!s) s = "";
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue