Repository navigation
Validation
CWIST has two validators:
Binding (bind.h) |
Zod-style (zod.h) |
|
|---|---|---|
| Input | request body (JSON or URL-encoded form) | a cJSON object or JSON string |
| Output | a filled C struct | the parsed cJSON tree |
| Rules | required, length, numeric range, regex, email, custom | required fields and types |
| Errors | per-field messages, optional automatic 400 response |
per-field messages |
Header: <cwist/core/validation/bind.h>
#include <cwist/core/validation/bind.h>
typedef struct {
char email[128];
int age;
} signup_t;
CWIST_BIND_RULES(email_rules, CWIST_RULE_REQUIRED(), CWIST_RULE_EMAIL());
CWIST_BIND_RULES(age_rules, CWIST_RULE_MIN_VAL(18), CWIST_RULE_MAX_VAL(120));
static const cwist_bind_field_t signup_fields[] = {
CWIST_BIND_FIELD(signup_t, email, "email", email_rules),
CWIST_BIND_FIELD(signup_t, age, "age", age_rules),
};
static void signup(cwist_http_request *req, cwist_http_response *res) {
signup_t in = {0};
cwist_bind_schema_t schema = CWIST_BIND_SCHEMA(signup_t, signup_fields);
if (!cwist_app_req_bind_json_or_400(req, res, &schema, &in))
return; /* res is already a 400 with JSON errors */
/* in.email, in.age are valid here */
}A failed bind answers:
{"success":false,"errors":[{"field":"email","message":"..."}]}| Macro | Rule |
|---|---|
CWIST_RULE_REQUIRED() |
present and non-empty |
CWIST_RULE_MIN_LEN(n), CWIST_RULE_MAX_LEN(n)
|
string length |
CWIST_RULE_MIN_VAL(v), CWIST_RULE_MAX_VAL(v)
|
numeric range |
CWIST_RULE_REGEX(pattern) |
POSIX extended regular expression (static string) |
CWIST_RULE_EMAIL() |
simplified RFC 5322 address shape |
CWIST_RULE_CUSTOM(fn, ctx) |
bool fn(const char *value, size_t len, void *ctx) |
CWIST_BIND_RULES(name, ...) declares a terminated static rule array.
CWIST_BIND_FIELD(Struct, member, "json_key", rules) infers the target type
from the member with _Generic: bool, signed and unsigned integers,
float, double, char * / char[] (copied, bounded by the member size),
cwist_sstring *, and cJSON * (ownership passes to you).
CWIST_BIND_SCHEMA(Struct, fields) builds the schema.
| Function | Description |
|---|---|
bool cwist_app_req_bind_json(cwist_http_request *req, const cwist_bind_schema_t *schema, void *out, cwist_bind_result_t *result) |
Parse the JSON body once, validate and fill out. false fills result with up to 32 errors. |
bool cwist_app_req_bind_form(cwist_http_request *req, const cwist_bind_schema_t *schema, void *out, cwist_bind_result_t *result) |
Same for application/x-www-form-urlencoded bodies. |
void cwist_bind_write_error_response(cwist_http_response *res, const cwist_bind_result_t *result) |
Write the 400 JSON error response. |
bool cwist_app_req_bind_json_or_400(req, res, schema, out) |
Bind JSON and write the 400 on failure. |
Header: <cwist/core/utils/zod.h>
Uses the same cwist_schema_t as JSON healing but
rejects non-conforming data instead of repairing it. Use it at trust
boundaries where silent coercion is unwanted.
cJSON *parsed = NULL;
cwist_zod_result_t r = cwist_zod_parse(req->body->data, &schema, &parsed);
if (!r.valid) {
res->status_code = CWIST_HTTP_BAD_REQUEST;
/* r.errors[i].field, r.errors[i].message for i < r.error_count */
return;
}
/* use parsed */
cJSON_Delete(parsed);| Function | Description |
|---|---|
cwist_zod_result_t cwist_zod_validate(const cJSON *json, const cwist_schema_t *schema) |
Check required fields and declared types of a parsed object. No coercion. |
cwist_zod_result_t cwist_zod_parse(const char *raw, const cwist_schema_t *schema, cJSON **out) |
Parse and validate; *out is the tree on success (free with cJSON_Delete()) and NULL otherwise. |
void cwist_zod_print_errors(const cwist_zod_result_t *r) |
Print the errors to stderr. |
cwist_db_query_strict() drops result rows that fail a schema; see
Database.
CWIST wiki, written against the dev branch of c4punks/CWIST. Pages marked "Source:" are generated from files under docs/; fix those in the repository. Questions: Discord.
Getting started
- Installation
- Quick Start
- Linking
- Server Modes
- Configuration and Environment
- Project CLI
- Tutorial / Korean
- Examples and Tutorials
Guides
Core
- API Reference
- Application
- Routing
- Middleware
- Requests and Responses
- Async Handlers
- Streaming Responses
- Error Handling
- Graceful Shutdown
- Multiport
Protocols
- HTTPS and TLS
- HTTP/2
- HTTP/3 and QUIC
- WebTransport
- WebSocket
- Server-Sent Events
- gRPC Server
- gRPC Client
- Protobuf and Codegen
- GraphQL
- WebRTC DataChannels
- HTTP Clients
Web features
- Static Files and Assets
- Big Dumb Reply Cache
- Compression
- Cookies
- Sessions and Flash
- Query Maps
- Multipart Uploads
- HTML Components
- Templates
- JSON
- Validation
- OpenAPI
Security
Data
Runtime
- Memory Management
- Full GC
- Async GC Ownership
- SString
- Reactor and I/O
- Metrics and Health
- Logging
- Testing
Platforms
Performance notes
- Benchmark Methodology
- C1M File Limits
- Reactor Fairness
- Cooperative Queuing
- Classic Pool Starvation
- Reactor Wakeup
- wrk Dual Histogram
- FIXED Endpoint Cache
- ADR-0001
- Durable Queue Gate
- Mux References
Project