Files
neuron-web/build/server.c
T

153 lines
4.1 KiB
C

#include <stdint.h>
#include <stdlib.h>
#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;
}