#include #include #include "el_runtime.h" el_val_t strip_query(el_val_t path); el_val_t root_dir(void); el_val_t parse_port(void); el_val_t content_type_for(el_val_t path); el_val_t route_health(void); el_val_t route_founding_count(void); el_val_t route_index(void); el_val_t route_static(el_val_t path); el_val_t route_brand(el_val_t path); el_val_t err_404(el_val_t path); el_val_t handle_request(el_val_t method, el_val_t path, el_val_t body); el_val_t strip_query(el_val_t path) { el_val_t q = str_index_of(path, EL_STR("?")); if (q < 0) { return path; } return str_slice(path, 0, q); return 0; } el_val_t root_dir(void) { el_val_t r = env(EL_STR("LANDING_ROOT")); if (str_eq(r, EL_STR(""))) { r = EL_STR("./src"); } return r; return 0; } el_val_t parse_port(void) { el_val_t p = env(EL_STR("PORT")); if (str_eq(p, EL_STR(""))) { p = EL_STR("8080"); } return str_to_int(p); return 0; } el_val_t content_type_for(el_val_t path) { if (str_ends_with(path, EL_STR(".html"))) { return EL_STR("text/html; charset=utf-8"); } if (str_ends_with(path, EL_STR(".css"))) { return EL_STR("text/css; charset=utf-8"); } if (str_ends_with(path, EL_STR(".js"))) { return EL_STR("application/javascript; charset=utf-8"); } if (str_ends_with(path, EL_STR(".json"))) { return EL_STR("application/json; charset=utf-8"); } if (str_ends_with(path, EL_STR(".png"))) { return EL_STR("image/png"); } if (str_ends_with(path, EL_STR(".jpg"))) { return EL_STR("image/jpeg"); } if (str_ends_with(path, EL_STR(".jpeg"))) { return EL_STR("image/jpeg"); } if (str_ends_with(path, EL_STR(".svg"))) { return EL_STR("image/svg+xml"); } if (str_ends_with(path, EL_STR(".ico"))) { return EL_STR("image/x-icon"); } if (str_ends_with(path, EL_STR(".webp"))) { return EL_STR("image/webp"); } if (str_ends_with(path, EL_STR(".woff2"))) { return EL_STR("font/woff2"); } if (str_ends_with(path, EL_STR(".woff"))) { return EL_STR("font/woff"); } return EL_STR("application/octet-stream"); return 0; } el_val_t route_health(void) { return EL_STR("{\"status\":\"ok\",\"engine\":\"el-landing\"}"); return 0; } el_val_t route_founding_count(void) { el_val_t sold = 47; el_val_t total = 1000; el_val_t remaining = (total - sold); return el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR("{\"sold\":"), int_to_str(sold)), EL_STR(",\"total\":")), int_to_str(total)), EL_STR(",\"remaining\":")), int_to_str(remaining)), EL_STR("}")); return 0; } el_val_t route_index(void) { return fs_read(el_str_concat(root_dir(), EL_STR("/index.html"))); return 0; } el_val_t route_static(el_val_t path) { return fs_read(el_str_concat(root_dir(), path)); return 0; } el_val_t route_brand(el_val_t path) { el_val_t after = str_slice(path, 6, str_len(path)); return fs_read(el_str_concat(el_str_concat(root_dir(), EL_STR("/assets/brand")), after)); return 0; } el_val_t err_404(el_val_t path) { return el_str_concat(el_str_concat(EL_STR("{\"error\":\"not found\",\"path\":\""), path), EL_STR("\"}")); return 0; } el_val_t handle_request(el_val_t method, el_val_t path, el_val_t body) { el_val_t clean = strip_query(path); if (!str_eq(method, EL_STR("GET"))) { return EL_STR("{\"error\":\"method not allowed\"}"); } if (str_eq(clean, EL_STR("/"))) { return route_index(); } if (str_eq(clean, EL_STR("/health"))) { return route_health(); } if (str_eq(clean, EL_STR("/api/founding-count"))) { return route_founding_count(); } if (str_starts_with(clean, EL_STR("/assets/"))) { return route_static(clean); } if (str_starts_with(clean, EL_STR("/brand/"))) { return route_brand(clean); } return err_404(clean); return 0; } int main(int argc, char** argv) { el_runtime_init_args(argc, argv); el_val_t port = parse_port(); println(el_str_concat(EL_STR("[landing] root="), root_dir())); println(el_str_concat(EL_STR("[landing] listening on "), int_to_str(port))); http_set_handler(EL_STR("handle_request")); http_serve(port, EL_STR("handle_request")); return 0; }