Web/macros.h
2025-09-15 15:29:08 -05:00

180 lines
6.2 KiB
C

#ifndef MACROS_H
#define MACROS_H
#include "app.h"
#include "context.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// Global app instance for simplified API
extern app_t *_global_app;
// Initialize the simplified API
#define APP_INIT() do { \
_global_app = app_new(); \
if (!_global_app) { \
fprintf(stderr, "Failed to create app\n"); \
exit(1); \
} \
} while(0)
// Simple route registration without app parameter
#define GET(path, handler) app_get(_global_app, path, handler)
#define POST(path, handler) app_post(_global_app, path, handler)
#define PUT(path, handler) app_put(_global_app, path, handler)
#define DELETE(path, handler) app_delete(_global_app, path, handler)
// Configuration
#define WORKERS(n) app_set_workers(_global_app, n)
#define PORT(p) app_listen(_global_app, p)
#define RUN() app_run(_global_app)
#define SERVE(port_num) do { \
PORT(port_num); \
printf("🚀 Server running on http://localhost:%d\n", port_num); \
RUN(); \
} while(0)
// Route parameter syntax helpers - make parameters explicit
// Usage: GET(app, ROUTE_PATH("/users/" ROUTE_PARAM("id") "/posts/" ROUTE_PARAM("post_id")), handler)
#define ROUTE_PARAM(name) ":" name
#define ROUTE_PATH(...) __VA_ARGS__
#define ROUTE_WILDCARD "*"
// Alternative clearer syntax for routes with parameters
#define GET_PARAM(app, base_path, param_name, handler) \
GET(app, base_path ":" param_name, handler)
#define GET_PARAMS(app, base_path, param1, param2, handler) \
GET(app, base_path ":" param1 "/" ":" param2, handler)
// Builder-style route definitions for maximum clarity
#define ROUTE_WITH_PARAMS(method, app, ...) method(app, __VA_ARGS__)
#define STATIC_PATH(path) path
#define PARAM_PATH(name) ":" name
#define ANY_PATH "*"
// Examples:
// ROUTE_WITH_PARAMS(GET, app, STATIC_PATH("/users/"), PARAM_PATH("id"), handler)
// ROUTE_WITH_PARAMS(GET, app, STATIC_PATH("/api/"), PARAM_PATH("version"), STATIC_PATH("/users"), handler)
// Documentation macros for route definitions
#define ROUTE_DOC(description) /* description */
#define PARAMS(...) /* Parameters: __VA_ARGS__ */
#define RETURNS(type) /* Returns: type */
// Handler definition macros
#define HANDLER(name) void name(context_t *ctx)
#define ASYNC_HANDLER(name) void name(context_t *ctx, void (*done)(context_t*))
// Response macros - simplified (ctx is implicit in handlers)
#define OK(text) ctx_text(ctx, 200, text)
#define CREATED(text) ctx_text(ctx, 201, text)
#define JSON(json) ctx_json(ctx, 200, json)
#define HTML(html) ctx_html(ctx, 200, html)
#define ERROR(code, msg) ctx_error(ctx, code, msg)
#define FILE(path) ctx_file(ctx, path)
// Error responses
#define BAD_REQUEST(msg) ctx_error(ctx, 400, msg)
#define UNAUTHORIZED(msg) ctx_error(ctx, 401, msg)
#define FORBIDDEN(msg) ctx_error(ctx, 403, msg)
#define NOT_FOUND(msg) ctx_error(ctx, 404, msg)
#define SERVER_ERROR(msg) ctx_error(ctx, 500, msg)
// JSON response macros
#define JSON_OK(ctx, ...) ctx_json(ctx, 200, __VA_ARGS__)
#define JSON_CREATED(ctx, ...) ctx_json(ctx, 201, __VA_ARGS__)
#define JSON_ERROR(ctx, code, msg) ctx_json(ctx, code, "{\"error\":\"" msg "\"}")
// HTML response macros
#define HTML_OK(ctx, ...) ctx_html(ctx, 200, __VA_ARGS__)
#define HTML_PAGE(ctx, title, body) \
ctx_html(ctx, 200, \
"<!DOCTYPE html><html><head><title>" title "</title></head>" \
"<body>" body "</body></html>")
// Redirect macros
#define REDIRECT(ctx, url) ctx_redirect(ctx, url)
#define REDIRECT_PERMANENT(ctx, url) do { \
ctx_status(ctx, 301); \
ctx_header_set(ctx, "Location", url); \
ctx_send(ctx); \
} while(0)
// Request accessor macros - simplified (ctx is implicit in handlers)
#define PARAM(name) ctx_param(ctx, name)
#define QUERY(name) ctx_query(ctx, name)
#define HEADER(name) ctx_header(ctx, name)
#define COOKIE(name) ctx_cookie(ctx, name)
#define BODY() ctx_body(ctx)
#define METHOD() ((ctx)->request ? (ctx)->request->method : NULL)
#define PATH() ((ctx)->request ? (ctx)->request->path : NULL)
// Middleware-style macros
#define NEXT(ctx, next) next(ctx)
#define ABORT(ctx, code, msg) do { \
ctx_error(ctx, code, msg); \
return; \
} while(0)
// Common patterns - simplified (ctx is implicit)
#define REQUIRE_AUTH() do { \
if (!HEADER("Authorization")) { \
UNAUTHORIZED("Authentication required"); \
return; \
} \
} while(0)
#define REQUIRE_JSON() do { \
const char *ct = HEADER("Content-Type"); \
if (!ct || strstr(ct, "application/json") == NULL) { \
BAD_REQUEST("Content-Type must be application/json"); \
return; \
} \
} while(0)
#define CORS() do { \
ctx_header_set(ctx, "Access-Control-Allow-Origin", "*"); \
ctx_header_set(ctx, "Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS"); \
ctx_header_set(ctx, "Access-Control-Allow-Headers", "Content-Type, Authorization"); \
} while(0)
// Utility macros for building responses
#define JSON_BEGIN(buf, size) char buf[size]; int _json_pos = 0; _json_pos += snprintf(buf, size, "{")
#define JSON_FIELD(buf, size, key, fmt, val) \
_json_pos += snprintf(buf + _json_pos, size - _json_pos, \
"%s\"%s\":" fmt, (_json_pos > 1 ? "," : ""), key, val)
#define JSON_STRING(buf, size, key, val) JSON_FIELD(buf, size, key, "\"%s\"", val)
#define JSON_NUMBER(buf, size, key, val) JSON_FIELD(buf, size, key, "%d", val)
#define JSON_BOOL(buf, size, key, val) JSON_FIELD(buf, size, key, "%s", (val) ? "true" : "false")
#define JSON_END(buf, size) snprintf(buf + _json_pos, size - _json_pos, "}")
// App configuration macros
#define APP_CONFIG(app, ...) do { \
struct { \
int workers; \
int max_conns; \
size_t read_buf; \
size_t write_buf; \
int cpu_affinity; \
} config = {0, 10000, 8192, 8192, 1, ##__VA_ARGS__}; \
if (config.workers > 0) app_set_workers(app, config.workers); \
app_set_max_conns(app, config.max_conns); \
app_set_buffer_sizes(app, config.read_buf, config.write_buf); \
app_set_cpu_affinity(app, config.cpu_affinity); \
} while(0)
// Quick app setup macro
#define QUICK_APP(port, ...) ({ \
app_t *_app = app_new(); \
if (_app) { \
APP_CONFIG(_app, ##__VA_ARGS__); \
__VA_ARGS__; \
app_listen(_app, port); \
} \
_app; \
})
#endif // MACROS_H