From f1a4c5448bfab717290e1ee1a91b8957e393fbb4 Mon Sep 17 00:00:00 2001 From: NADAL Jean-Baptiste Date: Tue, 21 Jan 2020 23:00:59 +0100 Subject: [PATCH] POST support WIP --- lib/include/restd_http_handler.h | 1 + lib/include/restd_rest_handler.h | 2 +- lib/include/restd_server.h | 4 + lib/src/restd_http_handler.c | 3 +- lib/src/restd_rest_handler.c | 168 +++++++++++++++---------------- lib/src/restd_server.c | 22 ++-- src/rest/rest_devices_handlers.c | 9 +- src/rest/rest_server.c | 4 +- 8 files changed, 113 insertions(+), 100 deletions(-) diff --git a/lib/include/restd_http_handler.h b/lib/include/restd_http_handler.h index e158f09..26e20c3 100644 --- a/lib/include/restd_http_handler.h +++ b/lib/include/restd_http_handler.h @@ -104,6 +104,7 @@ extern off_t restd_http_get_content_length(restd_conn_t *conn); extern size_t restd_http_get_content_length_stored(restd_conn_t *conn); extern void *restd_http_get_content(restd_conn_t *conn, size_t maxsize, size_t *storedsize); extern int restd_http_is_keepalive_request(restd_conn_t *conn); +extern int http_parser(restd_http_t *http, struct evbuffer *in); extern int restd_http_set_response_header(restd_conn_t *conn, const char *name, const char *value); extern const char *restd_http_get_response_header(restd_conn_t *conn, const char *name); diff --git a/lib/include/restd_rest_handler.h b/lib/include/restd_rest_handler.h index 96761ce..194d6f6 100644 --- a/lib/include/restd_rest_handler.h +++ b/lib/include/restd_rest_handler.h @@ -28,6 +28,6 @@ /*------------------------------- INCLUDES ----------------------------------*/ -extern int restd_rest_handler(short event, restd_conn_t *conn, void *userdata); +extern int restd_rest_handler(short event, restd_conn_t *conn); #endif /* _RESTD_REST_HANDLER_H */ \ No newline at end of file diff --git a/lib/include/restd_server.h b/lib/include/restd_server.h index 65ee867..236bc6b 100644 --- a/lib/include/restd_server.h +++ b/lib/include/restd_server.h @@ -70,6 +70,7 @@ enum restd_log_e /** * User callback(hook) prototype. */ +typedef int (*restd_call_hook_cb)(short event, restd_conn_t *conn); typedef int (*restd_callback)(short event, restd_conn_t *conn, void *userdata); typedef void (*restd_userdata_free_cb)(restd_conn_t *conn, void *userdata); @@ -107,6 +108,8 @@ struct restd_server_s struct event_base *evbase; /*!< event base */ struct bufferevent *notify_buffer; /*!< internal notification channel */ + + restd_call_hook_cb call_hooks; restd_callback request_handler; restd_callback error_handler; }; @@ -157,6 +160,7 @@ extern int restd_server_get_option_int(restd_server_t *server, const char *key); extern void restd_server_register_request_handler(restd_server_t *server, restd_callback cb); extern void restd_server_register_error_handler(restd_server_t *server, restd_callback cb); +extern void restd_server_register_call_hooks_handler(restd_server_t *server, restd_call_hook_cb cb); extern void restd_server_register_hook(restd_server_t *server, restd_callback cb, void *userdata); extern void restd_server_register_hook_on_method(restd_server_t *server, const char *method, diff --git a/lib/src/restd_http_handler.c b/lib/src/restd_http_handler.c index 7492fdc..e7e70b0 100644 --- a/lib/src/restd_http_handler.c +++ b/lib/src/restd_http_handler.c @@ -45,7 +45,6 @@ static void http_free(restd_http_t *http); static size_t http_add_inbuf(struct evbuffer *buffer, restd_http_t *http, size_t maxsize); -static int http_parser(restd_http_t *http, struct evbuffer *in); static int parse_requestline(restd_http_t *http, char *line); static int parse_headers(restd_http_t *http, struct evbuffer *in); static int parse_body(restd_http_t *http, struct evbuffer *in); @@ -617,7 +616,7 @@ static size_t http_add_inbuf(struct evbuffer *buffer, restd_http_t *http, /*--------------------------------------------------------------------------*/ -static int http_parser(restd_http_t *http, struct evbuffer *in) +int http_parser(restd_http_t *http, struct evbuffer *in) { ASSERT(http != NULL && in != NULL); diff --git a/lib/src/restd_rest_handler.c b/lib/src/restd_rest_handler.c index 5e347ba..632ef22 100644 --- a/lib/src/restd_rest_handler.c +++ b/lib/src/restd_rest_handler.c @@ -175,7 +175,7 @@ static bool contain(const char *src, const char *dest, int len) * * @brief Main function to manage rest request. */ -int restd_rest_handler(short event, restd_conn_t *conn, void *userdata) +int restd_rest_handler(short event, restd_conn_t *conn) { if (event & RESTD_EVENT_INIT) { @@ -186,99 +186,93 @@ int restd_rest_handler(short event, restd_conn_t *conn, void *userdata) restd_conn_set_extra(conn, http, http_free_cb); return RESTD_OK; } - else if (event & RESTD_EVENT_READ) - { - DEBUG("==> HTTP READ"); - return RESTD_OK; - } - else if (event & RESTD_EVENT_WRITE) - { - DEBUG("==> HTTP WRITE"); - return RESTD_OK; - } else if (event & RESTD_EVENT_CLOSE) { DEBUG("==> HTTP CLOSE=%x (TIMEOUT=%d, SHUTDOWN=%d)", event, event & RESTD_EVENT_TIMEOUT, event & RESTD_EVENT_SHUTDOWN); return RESTD_OK; } + else if ((event & RESTD_EVENT_READ) || (event & RESTD_EVENT_WRITE)) + { + restd_http_t *http = (restd_http_t *)restd_conn_get_extra(conn); + int status = http_parser(http, conn->in); + if (conn->method == NULL && http->request.method != NULL) + { + restd_conn_set_method(conn, http->request.method); + } + DEBUG("==> HTTP READ || HTTP WRITE"); + int reason = RESTD_ERROR_PATH_NOT_FOUND; + DEBUG("ZOB********restd_rest_handler: event 0x%x", event); + 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) + { + restd_hook_t *hook = (restd_hook_t *)obj.data; + if (hook->cb) + { + DEBUG("ZOB call_hooks: method: %s - %s \n", hook->method, conn->method); + DEBUG("call_hooks: path: %s - %s\n", hook->path, http->request.path); + 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; + } + + if ((hook->path != NULL) && (http->request.path != NULL)) + { + int i = 0; + int pos = -1; + while (hook->path[i]) + { + if (hook->path[i] == ':') + pos = i; + i++; + } + if (pos != -1 && contain(hook->path, http->request.path, pos)) + { + const char *buffer = &http->request.path[pos]; + // printf("buffer: <%s>\n", buffer); + conn->id = atoi(buffer); + return hook->cb(event, conn, hook->userdata); + } + else if (strcmp(hook->path, http->request.path) == 0) + 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; + } + } + + return conn->server->error_handler(reason, conn, NULL); + } BUG_EXIT(); return RESTD_CLOSE; } - - -int restd_rest_handler2(short event, restd_conn_t *conn, void *userdata) -{ - int reason = RESTD_ERROR_PATH_NOT_FOUND; - DEBUG("ZOB********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) - { - restd_hook_t *hook = (restd_hook_t *)obj.data; - if (hook->cb) - { - DEBUG("ZOB call_hooks: method: %s - %s \n", hook->method, conn->method); - DEBUG("call_hooks: path: %s - %s\n", hook->path, http->request.path); - 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; - } - - if ((hook->path != NULL) && (http->request.path != NULL)) - { - int i = 0; - int pos = -1; - while (hook->path[i]) - { - if (hook->path[i] == ':') - pos = i; - i++; - } - if (pos != -1 && contain(hook->path, http->request.path, pos)) - { - const char *buffer = &http->request.path[pos]; - // printf("buffer: <%s>\n", buffer); - conn->id = atoi(buffer); - return hook->cb(event, conn, hook->userdata); - } - else if (strcmp(hook->path, http->request.path) == 0) - 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; - } - } - - return conn->server->error_handler(reason, conn, NULL); -} diff --git a/lib/src/restd_server.c b/lib/src/restd_server.c index 8f3287d..7a0819c 100644 --- a/lib/src/restd_server.c +++ b/lib/src/restd_server.c @@ -154,6 +154,7 @@ restd_server_t *restd_server_new(void) server->options = qhashtbl(0, 0); server->stats = qhashtbl(100, QHASHTBL_THREADSAFE); server->hooks = qlist(0); + server->call_hooks = call_hooks; if (server->options == NULL || server->stats == NULL || server->hooks == NULL) { restd_server_free(server); @@ -535,7 +536,7 @@ static restd_conn_t *conn_new(restd_server_t *server, struct bufferevent *buffer { return NULL; } - + printf("conn_new\n"); // Create a new connection container. restd_conn_t *conn = NEW_OBJECT(restd_conn_t); if (conn == NULL) @@ -555,7 +556,7 @@ static restd_conn_t *conn_new(restd_server_t *server, struct bufferevent *buffer bufferevent_enable(buffer, EV_READ); // Run callbacks with AD_EVENT_INIT event. - conn->status = call_hooks(RESTD_EVENT_INIT | RESTD_EVENT_WRITE, conn); + conn->status = conn->server->call_hooks(RESTD_EVENT_INIT | RESTD_EVENT_WRITE, conn); // conn->id = -1; @@ -600,7 +601,7 @@ static void conn_free(restd_conn_t *conn) { if (conn->status != RESTD_CLOSE) { - call_hooks(RESTD_EVENT_CLOSE | RESTD_EVENT_SHUTDOWN, conn); + conn->server->call_hooks(RESTD_EVENT_CLOSE | RESTD_EVENT_SHUTDOWN, conn); } conn_reset(conn); if (conn->buffer) @@ -652,7 +653,7 @@ static void conn_cb(restd_conn_t *conn, int event) DEBUG("conn_cb: status:0x%x, event:0x%x", conn->status, event) if (conn->status == RESTD_OK || conn->status == RESTD_TAKEOVER) { - int status = call_hooks(event, conn); + int status = conn->server->call_hooks(event, conn); // Update status only when it's higher then before. if (!(conn->status == RESTD_CLOSE || (conn->status == RESTD_DONE && conn->status >= status))) { @@ -664,9 +665,9 @@ static void conn_cb(restd_conn_t *conn, int event) { if (restd_server_get_option_int(conn->server, "server.request_pipelining")) { - call_hooks(RESTD_EVENT_CLOSE, conn); + conn->server->call_hooks(RESTD_EVENT_CLOSE, conn); conn_reset(conn); - call_hooks(RESTD_EVENT_INIT, conn); + conn->server->call_hooks(RESTD_EVENT_INIT, conn); } else { @@ -684,7 +685,7 @@ static void conn_cb(restd_conn_t *conn, int event) if (evbuffer_get_length(conn->out) <= 0) { int newevent = (event & RESTD_EVENT_CLOSE) ? event : RESTD_EVENT_CLOSE; - call_hooks(newevent, conn); + //conn->server->call_hooks(newevent, conn); conn_free(conn); DEBUG("Connection closed."); return; @@ -708,6 +709,13 @@ void restd_server_register_error_handler(restd_server_t *server, restd_callback /*--------------------------------------------------------------------------*/ +void restd_server_register_call_hooks_handler(restd_server_t *server, restd_call_hook_cb cb) +{ + server->call_hooks = cb; +} + +/*--------------------------------------------------------------------------*/ + /** * Register user hook. */ diff --git a/src/rest/rest_devices_handlers.c b/src/rest/rest_devices_handlers.c index 6c3cf00..3613b87 100644 --- a/src/rest/rest_devices_handlers.c +++ b/src/rest/rest_devices_handlers.c @@ -42,7 +42,7 @@ int outlet_create_handler(short event, restd_conn_t *conn, void *userdata) { printf("outlet_create_handler\n\n"); - if (event & RESTD_EVENT_CLOSE) + if (event & RESTD_EVENT_WRITE) { off_t data_size; @@ -55,6 +55,9 @@ int outlet_create_handler(short event, restd_conn_t *conn, void *userdata) data = restd_http_get_content(conn, 0, &data_size); printf("2/data size: %ld\n", data_size); + printf("3/data size: %s\n", data); + +#if 0 root_node = json_tokener_parse(data); free(data); @@ -71,6 +74,10 @@ int outlet_create_handler(short event, restd_conn_t *conn, void *userdata) return RESTD_CLOSE; } } +#endif + restd_http_response(conn, 204, "application/json", "{}", 2); + return RESTD_CLOSE; + } restd_http_response(conn, 400, "application/json", "{\"status\":\"error\"}", 18); diff --git a/src/rest/rest_server.c b/src/rest/rest_server.c index ca83349..49dcbaf 100644 --- a/src/rest/rest_server.c +++ b/src/rest/rest_server.c @@ -62,8 +62,8 @@ int setup_rest_server(restd_server_t *rest_server, const char *port, const char //restd_server_register_request_handler(rest_server, restd_rest_handler); restd_server_register_error_handler(rest_server, my_error_handler); - restd_server_register_hook(rest_server, restd_rest_handler, NULL); - + restd_server_register_call_hooks_handler(rest_server, restd_rest_handler); + // restd_server_register_hook(rest_server, restd_http_handler, NULL); // Capabilities. restd_server_register_hook_on_path(rest_server, "GET", "/api/v1/capabilities", NULL, dm);