From 0113c9eec6a25ffe0c4aa3d77fcf91f402820658 Mon Sep 17 00:00:00 2001 From: NADAL Jean-Baptiste Date: Tue, 24 Dec 2019 14:11:51 +0100 Subject: [PATCH] restd is functional. --- lib/include/restd_server.h | 4 +- lib/src/restd_rest_handler.c | 169 +++++++++++++++++++++++++++++------ lib/src/restd_server.c | 2 + src/main.c | 49 +++++++--- 4 files changed, 185 insertions(+), 39 deletions(-) diff --git a/lib/include/restd_server.h b/lib/include/restd_server.h index 3ecc6c5..0713da4 100644 --- a/lib/include/restd_server.h +++ b/lib/include/restd_server.h @@ -47,8 +47,8 @@ typedef struct restd_conn_s restd_conn_t; #define RESTD_DONE (2) /*!< We're done with this request but keep the connection open. */ #define RESTD_CLOSE (3) /*!< We're done with this request. Close as soon as we sent all data out. */ -#define RESTD_NOT_ALLOWED (4) -#define RESTD_NOT_FOUND (5) +#define RESTD_ERROR_METHOD_NOT_ALLOWED (1) +#define RESTD_ERROR_PATH_NOT_FOUND (2) /* * These flags are used for ad_log_level(); diff --git a/lib/src/restd_rest_handler.c b/lib/src/restd_rest_handler.c index b3f632f..e36b315 100644 --- a/lib/src/restd_rest_handler.c +++ b/lib/src/restd_rest_handler.c @@ -30,6 +30,9 @@ #include #include +#include +#include +#include #include @@ -39,6 +42,108 @@ #include "macro.h" +/*--------------------------------------------------------------------------*/ + +struct mimetype_s +{ + const char *extn; + const char *mime; +}; + +/*--------------------------------------------------------------------------*/ + +static const struct mimetype_s g_mime_types[] = { + + {"txt", "text/plain"}, + {"log", "text/plain"}, + {"js", "text/javascript"}, + {"css", "text/css"}, + {"htm", "text/html"}, + {"html", "text/html"}, + {"diff", "text/x-patch"}, + {"patch", "text/x-patch"}, + {"c", "text/x-csrc"}, + {"h", "text/x-chdr"}, + {"o", "text/x-object"}, + {"ko", "text/x-object"}, + + {"bmp", "image/bmp"}, + {"gif", "image/gif"}, + {"png", "image/png"}, + {"jpg", "image/jpeg"}, + {"jpeg", "image/jpeg"}, + {"svg", "image/svg+xml"}, + + {"json", "application/json"}, + {"jsonp", "application/javascript"}, + {"zip", "application/zip"}, + {"pdf", "application/pdf"}, + {"xml", "application/xml"}, + {"xsl", "application/xml"}, + {"doc", "application/msword"}, + {"ppt", "application/vnd.ms-powerpoint"}, + {"xls", "application/vnd.ms-excel"}, + {"odt", "application/vnd.oasis.opendocument.text"}, + {"odp", "application/vnd.oasis.opendocument.presentation"}, + {"pl", "application/x-perl"}, + {"sh", "application/x-shellscript"}, + {"php", "application/x-php"}, + {"deb", "application/x-deb"}, + {"iso", "application/x-cd-image"}, + {"tar.gz", "application/x-compressed-tar"}, + {"tgz", "application/x-compressed-tar"}, + {"gz", "application/x-gzip"}, + {"tar.bz2", "application/x-bzip-compressed-tar"}, + {"tbz", "application/x-bzip-compressed-tar"}, + {"bz2", "application/x-bzip"}, + {"tar", "application/x-tar"}, + {"rar", "application/x-rar-compressed"}, + + {"mp3", "audio/mpeg"}, + {"ogg", "audio/x-vorbis+ogg"}, + {"wav", "audio/x-wav"}, + + {"mpg", "video/mpeg"}, + {"mpeg", "video/mpeg"}, + {"avi", "video/x-msvideo"}, + + {"README", "text/plain"}, + {"log", "text/plain"}, + {"cfg", "text/plain"}, + {"conf", "text/plain"}, + + {"pac", "application/x-ns-proxy-autoconfig"}, + {"wpad.dat", "application/x-ns-proxy-autoconfig"}, + {"appcache", "text/cache-manifest"}, + {"manifest", "text/cache-manifest"}, + + {NULL, NULL}}; + +/*--------------------------------------------------------------------------*/ + +static const char *file_mime_lookup(const char *path) +{ + const struct mimetype_s *m = &g_mime_types[0]; + const char *e; + + while (m->extn) + { + e = &path[strlen(path) - 1]; + + while (e >= path) + { + if ((*e == '.' || *e == '/') && !strcasecmp(&e[1], m->extn)) + return m->mime; + + e--; + } + + m++; + } + + return "application/octet-stream"; +} + /*! ---------------------------------------------------------------------------- * @fn restd_rest_handler * @@ -46,48 +151,60 @@ */ int restd_rest_handler(short event, restd_conn_t *conn, void *userdata) { - bool found = false; - DEBUG("JBN call_hooks: event 0x%x", event); + int reason = RESTD_ERROR_PATH_NOT_FOUND; + // DEBUG("restd_rest_handler: event 0x%x", event); restd_http_t *http = (restd_http_t *)restd_conn_get_extra(conn); + char *root_path; qlist_t *hooks = conn->server->hooks; qlist_obj_t obj; bzero((void *)&obj, sizeof(qlist_obj_t)); while (hooks->getnext(hooks, &obj, false) == true) { - DEBUG(">>>>>>>>>\n"); restd_hook_t *hook = (restd_hook_t *)obj.data; if (hook->cb) { - DEBUG("JBN call_hooks: method: %s - %s \n", hook->method, conn->method); - DEBUG("JBN call_hooks: path: %s - %s\n", hook->path, http->request.path); - if ((hook->method == NULL) || (conn->method == NULL) || (strcmp(hook->method, conn->method) != 0)) - { - DEBUG("JBN - ca va pas 1 \n"); - continue; - } + // DEBUG("call_hooks: method: %s - %s \n", hook->method, conn->method); + // DEBUG("call_hooks: path: %s - %s\n", hook->path, http->request.path); if ((hook->path == NULL) || (http->request.path == NULL) || (strcmp(hook->path, http->request.path) != 0)) { - DEBUG("JBN - ca va pas 2 \n"); continue; } - DEBUG("JBN FOUND !!!!\n"); + // DEBUG("HOOK FOUND !!!!\n"); + if ((hook->method == NULL) || (conn->method == NULL) || (strcmp(hook->method, conn->method) != 0)) + { + // DEBUG("Hook found but method failed.\n"); + reason = RESTD_ERROR_METHOD_NOT_ALLOWED; + break; + } - return RESTD_OK; - //int status = hook->cb(event, conn, hook->userdata); - //if (status != RESTD_OK) - //{ - // return status; - //} + return hook->cb(event, conn, hook->userdata); + } + } + // No Hook Found check if it's a real file into document root. + root_path = restd_server_get_option(conn->server, "server.root_path"); + if ((root_path != NULL) && (strlen(root_path) != 0)) + { + FILE *file; + char buf[1024] = ""; + qstrcatf(buf, "%s%s", root_path, http->request.path); + if ((file = fopen(buf, "r"))) + { + long fsize; + char *file_buf; + fseek(file, 0, SEEK_END); + fsize = ftell(file); + fseek(file, 0, SEEK_SET); + file_buf = malloc(fsize + 1); + fread(file_buf, 1, fsize, file); + fclose(file); + file_buf[fsize] = 0; + + printf("mime type:%s\n", file_mime_lookup(buf)); + restd_http_response(conn, 200, file_mime_lookup(buf), file_buf, fsize); + return RESTD_CLOSE; } } - if (found == false) - { - printf("Call error handler...\n"); - return RESTD_NOT_ALLOWED; - } - - DEBUG("JBN call_hooks - DONE\n"); - return RESTD_OK; + return conn->server->error_handler(reason, conn, NULL); } diff --git a/lib/src/restd_server.c b/lib/src/restd_server.c index a602bcb..ede569f 100644 --- a/lib/src/restd_server.c +++ b/lib/src/restd_server.c @@ -87,6 +87,8 @@ static void *get_userdata(restd_conn_t *conn, int index); #define RESTD_SERVER_OPTIONS { \ {"server.port", "8888"}, \ \ + {"server.root_path", ""}, \ + \ /* Addr format IPv4="1.2.3.4", IPv6="1:2:3:4:5:6", Unix="/path" */ \ {"server.addr", "0.0.0.0"}, \ \ diff --git a/src/main.c b/src/main.c index 5458d4d..547d3b2 100644 --- a/src/main.c +++ b/src/main.c @@ -28,8 +28,12 @@ /*-------------------------------- INCLUDES ---------------------------------*/ +#include + #include +/*--------------------------------------------------------------------------*/ + int my_http_get_handler(short event, restd_conn_t *conn, void *userdata) { if (event & RESTD_EVENT_READ) @@ -43,28 +47,51 @@ int my_http_get_handler(short event, restd_conn_t *conn, void *userdata) return RESTD_OK; } -int my_http_default_handler(short event, restd_conn_t *conn, void *userdata) +/*--------------------------------------------------------------------------*/ + +int my_error_handler(short event, restd_conn_t *conn, void *userdata) { - printf("Error Handler...\n"); - if (event & RESTD_EVENT_READ) + int http_code = 500; + if (event & RESTD_ERROR_METHOD_NOT_ALLOWED) { - if (restd_http_get_status(conn) == RESTD_HTTP_REQ_DONE) - { - restd_http_response(conn, 500, "application/json", "{\"status\":\"error\"}", 18); - return RESTD_CLOSE; // Close connection. - } + http_code = 405; } - return RESTD_OK; + else if (event & RESTD_ERROR_PATH_NOT_FOUND) + { + http_code = 404; + } + + restd_http_response(conn, http_code, "application/json", "{\"status\":\"error\"}", 18); + return RESTD_CLOSE; // Close connection. } +/*--------------------------------------------------------------------------*/ + +void usage(void) +{ + printf("Usage : domo-iot [web server path] \n"); + printf("web server path: \t root path of the Web server.\n"); +} + +/*--------------------------------------------------------------------------*/ + int main(int argc, char **argv) { + restd_server_t *server; + + if (argc < 2) + { + usage(); + return -1; + } + restd_log_level(RESTD_LOG_DEBUG); - restd_server_t *server = restd_server_new(); + server = restd_server_new(); restd_server_set_option(server, "server.port", "8888"); + restd_server_set_option(server, "server.root_path", argv[1]); restd_server_register_request_handler(server, restd_rest_handler); - restd_server_register_error_handler(server, my_http_default_handler); + restd_server_register_error_handler(server, my_error_handler); restd_server_register_hook(server, restd_http_handler, NULL); restd_server_register_hook_on_path(server, "GET", "/api/zob", my_http_get_handler, NULL);