POST support WIP
All checks were successful
continuous-integration/drone/push Build is passing

This commit is contained in:
2020-01-21 23:00:59 +01:00
parent 9acd116ab2
commit f1a4c5448b
8 changed files with 113 additions and 100 deletions

View File

@@ -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);

View File

@@ -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 */

View File

@@ -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,

View File

@@ -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);

View File

@@ -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);
}

View File

@@ -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.
*/

View File

@@ -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);

View File

@@ -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);