|
|
|
/* SPDX-License-Identifier: GPL-3.0-or-later */
|
|
|
|
/* Copyright 2022 Ivan Polyakov */
|
|
|
|
|
|
|
|
#include "app.h"
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
/*!
|
|
|
|
* \brief Selects a route handler based on requested path.
|
|
|
|
* \param app Application instance.
|
|
|
|
* \param req Request.
|
|
|
|
* \return Pointer to route handler.
|
|
|
|
*/
|
|
|
|
static rpd_route *routes_fabric(rpd_app *app, rpd_req *req);
|
|
|
|
|
|
|
|
int rpd_app_create(rpd_app *app)
|
|
|
|
{
|
|
|
|
app->running = app->routes_len = 0;
|
|
|
|
app->routes = NULL;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
int rpd_app_add_route(rpd_app *app, const char *path, rpd_route_cb cb,
|
|
|
|
void *userdata)
|
|
|
|
{
|
|
|
|
rpd_route route;
|
|
|
|
if (rpd_route_init(&route, path, cb, userdata))
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
app->routes = (rpd_route *) realloc(app->routes, sizeof(rpd_route) * (app->routes_len + 1));
|
|
|
|
if (!app->routes)
|
|
|
|
return 2;
|
|
|
|
|
|
|
|
app->routes[app->routes_len++] = route;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void rpd_app_handle_request(rpd_app *app, rpd_req *req, rpd_res *res)
|
|
|
|
{
|
|
|
|
rpd_route *route = routes_fabric(app, req);
|
|
|
|
if (!route) {
|
|
|
|
res->status = rpd_res_st_not_found;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
route->cb(req, res, route->userdata);
|
|
|
|
}
|
|
|
|
|
|
|
|
static rpd_route *routes_fabric(rpd_app *app, rpd_req *req)
|
|
|
|
{
|
|
|
|
const rpd_url *req_path, *route_path = 0;
|
|
|
|
req_path = &req->path;
|
|
|
|
|
|
|
|
for (int i = 0; i < app->routes_len; i++) {
|
|
|
|
route_path = &app->routes[i].path;
|
|
|
|
if (req_path->parts_len != route_path->parts_len)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
int match = 1;
|
|
|
|
for (int j = 1; j < route_path->parts_len && match; j++) {
|
|
|
|
int cur_part_is_dyn = route_path->parts[i][0] == ':';
|
|
|
|
if (!cur_part_is_dyn && strcmp(req_path->parts[i], route_path->parts[i])) {
|
|
|
|
match = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!match)
|
|
|
|
continue;
|
|
|
|
|
|
|
|
rpd_keyval_init(&req->params, 0);
|
|
|
|
rpd_url_params_parse_keys(&req->params, route_path);
|
|
|
|
rpd_url_params_parse_vals(&req->params, req_path, route_path);
|
|
|
|
return &app->routes[i];
|
|
|
|
}
|
|
|
|
return NULL;
|
|
|
|
}
|