X-Git-Url: https://gerrit.automotivelinux.org/gerrit/gitweb?a=blobdiff_plain;f=src%2Fhttp-svc.c;h=e8ccfe8329bf8c68d75b3585595ef5c5e3b55c48;hb=20f5ff02e455580c6e7129479f3328787b3333ff;hp=f281bbf99c5ec87f1846ce847f710b8e9c337a96;hpb=4a6f90f69c15bb4d99bbbae50e9c9e267dc9b244;p=src%2Fapp-framework-binder.git diff --git a/src/http-svc.c b/src/http-svc.c index f281bbf9..e8ccfe83 100644 --- a/src/http-svc.c +++ b/src/http-svc.c @@ -26,12 +26,14 @@ #include "afb-hreq.h" #include "afb-websock.h" +#define JSON_CONTENT "application/json" +#define FORM_CONTENT MHD_HTTP_POST_ENCODING_MULTIPART_FORMDATA struct afb_hsrv_handler { struct afb_hsrv_handler *next; const char *prefix; size_t length; - int (*handler) (struct afb_hreq *, struct afb_hreq_post *, void *); + int (*handler) (struct afb_hreq *, void *); void *data; int priority; }; @@ -45,7 +47,6 @@ struct afb_diralias { int afb_hreq_one_page_api_redirect( struct afb_hreq *hreq, - struct afb_hreq_post *post, void *data) { size_t plen; @@ -71,10 +72,10 @@ int afb_hreq_one_page_api_redirect( return afb_hreq_redirect_to(hreq, url); } -struct afb_hsrv_handler *afb_hsrv_handler_new( +static struct afb_hsrv_handler *new_handler( struct afb_hsrv_handler *head, const char *prefix, - int (*handler) (struct afb_hreq *, struct afb_hreq_post *, void *), + int (*handler) (struct afb_hreq *, void *), void *data, int priority) { @@ -112,37 +113,40 @@ struct afb_hsrv_handler *afb_hsrv_handler_new( return head; } -int afb_req_add_handler( +int afb_hsrv_add_handler( AFB_session * session, const char *prefix, - int (*handler) (struct afb_hreq *, struct afb_hreq_post *, void *), + int (*handler) (struct afb_hreq *, void *), void *data, int priority) { struct afb_hsrv_handler *head; - head = afb_hsrv_handler_new(session->handlers, prefix, handler, data, priority); + head = new_handler(session->handlers, prefix, handler, data, priority); if (head == NULL) return 0; session->handlers = head; return 1; } -static int relay_to_doRestApi(struct afb_hreq *hreq, struct afb_hreq_post *post, void *data) +static int relay_to_doRestApi(struct afb_hreq *hreq, void *data) { int later; - if (afb_websock_check(hreq, &later)) { + if (hreq->lentail == 0 && afb_websock_check(hreq, &later)) { if (!later) { struct afb_websock *ws = afb_websock_create(hreq->connection); } return 1; } +return 0; +/* return doRestApi(hreq->connection, hreq->session, &hreq->tail[1], get_method_name(hreq->method), post->upload_data, post->upload_data_size, (void **)hreq->recorder); +*/ } -static int handle_alias(struct afb_hreq *hreq, struct afb_hreq_post *post, void *data) +static int handle_alias(struct afb_hreq *hreq, void *data) { struct afb_diralias *da = data; @@ -159,7 +163,7 @@ static int handle_alias(struct afb_hreq *hreq, struct afb_hreq_post *post, void return afb_hreq_reply_file(hreq, da->dirfd, &hreq->tail[1]); } -int afb_req_add_alias(AFB_session * session, const char *prefix, const char *alias, int priority) +int afb_hsrv_add_alias(AFB_session * session, const char *prefix, const char *alias, int priority) { struct afb_diralias *da; int dirfd; @@ -175,7 +179,7 @@ int afb_req_add_alias(AFB_session * session, const char *prefix, const char *ali da->directory = alias; da->lendir = strlen(da->directory); da->dirfd = dirfd; - if (afb_req_add_handler(session, prefix, handle_alias, da, priority)) + if (afb_hsrv_add_handler(session, prefix, handle_alias, da, priority)) return 1; free(da); } @@ -183,25 +187,39 @@ int afb_req_add_alias(AFB_session * session, const char *prefix, const char *ali return 0; } -static int my_default_init(AFB_session * session) +void afb_hsrv_reply_error(struct MHD_Connection *connection, unsigned int status) { - int idx; - - if (!afb_req_add_handler(session, session->config->rootapi, relay_to_doRestApi, NULL, 1)) - return 0; - - for (idx = 0; session->config->aliasdir[idx].url != NULL; idx++) - if (!afb_req_add_alias - (session, session->config->aliasdir[idx].url, session->config->aliasdir[idx].path, 0)) - return 0; - - if (!afb_req_add_alias(session, "", session->config->rootdir, -10)) - return 0; - - if (!afb_req_add_handler(session, session->config->rootbase, afb_hreq_one_page_api_redirect, NULL, -20)) - return 0; + char *buffer; + int length; + struct MHD_Response *response; + + length = asprintf(&buffer, "error %u", status); + if (length > 0) + response = MHD_create_response_from_buffer((unsigned)length, buffer, MHD_RESPMEM_MUST_FREE); + else { + buffer = "error"; + response = MHD_create_response_from_buffer(strlen(buffer), buffer, MHD_RESPMEM_PERSISTENT); + } + if (!MHD_queue_response(connection, status, response)) + fprintf(stderr, "Failed to reply error code %u", status); + MHD_destroy_response(response); +} - return 1; +static int postproc(void *cls, + enum MHD_ValueKind kind, + const char *key, + const char *filename, + const char *content_type, + const char *transfer_encoding, + const char *data, + uint64_t off, + size_t size) +{ + struct afb_hreq *hreq = cls; + if (filename != NULL) + return afb_hreq_post_add_file(hreq, key, filename, data, size); + else + return afb_hreq_post_add(hreq, key, data, size); } static int access_handler( @@ -211,83 +229,108 @@ static int access_handler( const char *methodstr, const char *version, const char *upload_data, - size_t * upload_data_size, - void **recorder) + size_t *upload_data_size, + void **recordreq) { - struct afb_hreq_post post; - struct afb_hreq hreq; + struct afb_hreq *hreq; enum afb_method method; AFB_session *session; struct afb_hsrv_handler *iter; + const char *type; session = cls; - post.upload_data = upload_data; - post.upload_data_size = upload_data_size; - -#if 0 - struct afb_hreq *previous; - - previous = *recorder; - if (previous) { - assert((void **)previous->recorder == recorder); - assert(previous->session == session); - assert(previous->connection == connection); - assert(previous->method == get_method(methodstr)); - assert(previous->url == url); + hreq = *recordreq; + if (hreq == NULL) { + /* create the request */ + hreq = calloc(1, sizeof *hreq); + if (hreq == NULL) + goto internal_error; + *recordreq = hreq; + + /* get the method */ + method = get_method(methodstr); + method &= afb_method_get | afb_method_post; + if (method == afb_method_none) { + afb_hsrv_reply_error(connection, MHD_HTTP_BAD_REQUEST); + return MHD_YES; + } - /* TODO */ -/* - assert(previous->post_handler != NULL); - previous->post_handler(previous, &post); - return MHD_NO; -*/ + /* init the request */ + hreq->session = cls; + hreq->connection = connection; + hreq->method = method; + hreq->version = version; + hreq->tail = hreq->url = url; + hreq->lentail = hreq->lenurl = strlen(url); + + /* init the post processing */ + if (method == afb_method_post) { + type = afb_hreq_get_header(hreq, MHD_HTTP_HEADER_CONTENT_TYPE); + if (type == NULL) { + /* an empty post, let's process it as a get */ + hreq->method = afb_method_get; + } else if (strcasestr(type, FORM_CONTENT) != NULL) { + hreq->postform = MHD_create_post_processor (connection, 65500, postproc, hreq); + if (hreq->postform == NULL) + goto internal_error; + } else if (strcasestr(type, JSON_CONTENT) == NULL) { + afb_hsrv_reply_error(connection, MHD_HTTP_UNSUPPORTED_MEDIA_TYPE); + return MHD_YES; + } + } } -#endif - method = get_method(methodstr); - if (method == afb_method_none) { - afb_hreq_reply_error(&hreq, MHD_HTTP_BAD_REQUEST); - return MHD_YES; + /* process further data */ + if (*upload_data_size) { + if (hreq->postform != NULL) { + if (!MHD_post_process (hreq->postform, upload_data, *upload_data_size)) + goto internal_error; + } else { + if (!afb_hreq_post_add(hreq, NULL, upload_data, *upload_data_size)) + goto internal_error; + } + *upload_data_size = 0; + return MHD_YES; } - /* init the request */ - hreq.session = cls; - hreq.connection = connection; - hreq.method = method; - hreq.version = version; - hreq.tail = hreq.url = url; - hreq.lentail = hreq.lenurl = strlen(url); - hreq.recorder = (struct afb_hreq **)recorder; - hreq.post_handler = NULL; - hreq.post_completed = NULL; - hreq.post_data = NULL; + /* flush the data */ + afb_hreq_post_end(hreq); /* search an handler for the request */ iter = session->handlers; while (iter) { - if (afb_hreq_unprefix(&hreq, iter->prefix, iter->length)) { - if (iter->handler(&hreq, &post, iter->data)) + if (afb_hreq_unprefix(hreq, iter->prefix, iter->length)) { + if (iter->handler(hreq, iter->data)) return MHD_YES; - hreq.tail = hreq.url; - hreq.lentail = hreq.lenurl; + hreq->tail = hreq->url; + hreq->lentail = hreq->lenurl; } iter = iter->next; } /* no handler */ - afb_hreq_reply_error(&hreq, method != afb_method_get ? MHD_HTTP_BAD_REQUEST : MHD_HTTP_NOT_FOUND); + afb_hreq_reply_error(hreq, MHD_HTTP_NOT_FOUND); + return MHD_YES; + +internal_error: + afb_hsrv_reply_error(connection, MHD_HTTP_INTERNAL_SERVER_ERROR); return MHD_YES; } /* Because of POST call multiple time requestApi we need to free POST handle here */ -static void end_handler(void *cls, struct MHD_Connection *connection, void **con_cls, +static void end_handler(void *cls, struct MHD_Connection *connection, void **recordreq, enum MHD_RequestTerminationCode toe) { - AFB_PostHandle *posthandle = *con_cls; + AFB_session *session; + struct afb_hreq *hreq; - /* if post handle was used let's free everything */ - if (posthandle != NULL) - endPostRequest(posthandle); + session = cls; + hreq = *recordreq; + + if (hreq != NULL) { + if (hreq->postform != NULL) + MHD_destroy_post_processor(hreq->postform); + } } static int new_client_handler(void *cls, const struct sockaddr *addr, socklen_t addrlen) @@ -316,20 +359,37 @@ static int init_lib_magic (AFB_session *session) /* Warning: should not use NULL for DB [libmagic bug wont pass efence check] */ if (magic_load(session->magic, MAGIC_DB) != 0) { fprintf(stderr,"cannot load magic database - %s\n", magic_error(session->magic)); -/* magic_close(session->magic); session->magic = NULL; return 0; -*/ } return 1; } #endif -AFB_error httpdStart(AFB_session * session) +static int my_default_init(AFB_session * session) { + int idx; + + if (!afb_hsrv_add_handler(session, session->config->rootapi, relay_to_doRestApi, NULL, 1)) + return 0; + for (idx = 0; session->config->aliasdir[idx].url != NULL; idx++) + if (!afb_hsrv_add_alias (session, session->config->aliasdir[idx].url, session->config->aliasdir[idx].path, 0)) + return 0; + + if (!afb_hsrv_add_alias(session, "", session->config->rootdir, -10)) + return 0; + + if (!afb_hsrv_add_handler(session, session->config->rootbase, afb_hreq_one_page_api_redirect, NULL, -20)) + return 0; + + return 1; +} + +AFB_error httpdStart(AFB_session * session) +{ if (!my_default_init(session)) { printf("Error: initialisation of httpd failed"); return AFB_FATAL;