refactoring (in progress, tbf)
authorJosé Bollo <jose.bollo@iot.bzh>
Wed, 30 Mar 2016 17:22:34 +0000 (19:22 +0200)
committerJosé Bollo <jose.bollo@iot.bzh>
Wed, 30 Mar 2016 17:22:34 +0000 (19:22 +0200)
Change-Id: I7461983aa3177f8ae54ca72761d916e646888fca
Signed-off-by: José Bollo <jose.bollo@iot.bzh>
include/proto-def.h
src/afb-hreq.c
src/afb-hreq.h
src/afb-rest-api.c
src/afb-websock.c
src/helper-api.c
src/http-svc.c

index 21e0303..0db8abb 100644 (file)
@@ -28,10 +28,6 @@ extern AFB_PostCtx* getPostContext (AFB_request *request);
 extern char* getPostPath (AFB_request *request);
 
 extern json_object *jsonNewMessage (AFB_error level, char* format, ...);
-extern json_object *jsonNewStatus (AFB_error level);
-extern json_object *jsonNewjtype (void);
-extern json_object *jsonNewMessage (AFB_error level, char* format, ...);
-extern void jsonDumpObject (json_object * jObject);
 
 // rest-api
 extern void endPostRequest(AFB_PostHandle *posthandle); 
index f7f3bb1..bc42bf1 100644 (file)
 #include "afb-req-itf.h"
 #include "afb-hreq.h"
 
-static char empty_string[1] = "";
+static char empty_string[] = "";
 
+struct hreq_data {
+       struct hreq_data *next;
+       char *key;
+       int file;
+       size_t length;
+       char *value;
+};
+
+
+static struct hreq_data *get_data(struct afb_hreq *hreq, const char *key, int create)
+{
+       struct hreq_data *data = hreq->data;
+       if (key == NULL)
+               key = empty_string;
+       while (data != NULL) {
+               if (!strcasecmp(data->key, key))
+                       return data;
+               data = data->next;
+       }
+       if (create) {
+               data = calloc(1, sizeof *data);
+               if (data != NULL) {
+                       data->key = strdup(key);
+                       if (data->key == NULL) {
+                               free(data);
+                               data = NULL;
+                       } else {
+                               data->next = hreq->data;
+                               hreq->data = data;
+                       }
+               }
+       }
+       return data;
+}
 
 /* a valid subpath is a relative path not looking deeper than root using .. */
 static int validsubpath(const char *subpath)
@@ -237,7 +271,8 @@ const char *afb_hreq_get_cookie(struct afb_hreq *hreq, const char *name)
 
 const char *afb_hreq_get_argument(struct afb_hreq *hreq, const char *name)
 {
-       return MHD_lookup_connection_value(hreq->connection, MHD_GET_ARGUMENT_KIND, name);
+       struct hreq_data *data = get_data(hreq, name, 0);
+       return data ? data->value : MHD_lookup_connection_value(hreq->connection, MHD_GET_ARGUMENT_KIND, name);
 }
 
 const char *afb_hreq_get_header(struct afb_hreq *hreq, const char *name)
@@ -245,8 +280,64 @@ const char *afb_hreq_get_header(struct afb_hreq *hreq, const char *name)
        return MHD_lookup_connection_value(hreq->connection, MHD_HEADER_KIND, name);
 }
 
-struct afb_req_itf afb_hreq_itf = {
+const struct afb_req_itf afb_hreq_itf = {
        .get_cookie = (void*)afb_hreq_get_cookie,
        .get_argument = (void*)afb_hreq_get_argument
 };
 
+
+void afb_hreq_post_end(struct afb_hreq *hreq)
+{
+       struct hreq_data *data = hreq->data;
+       while(data) {
+               if (data->file > 0) {
+                       close(data->file);
+                       data->file = -1;
+               }
+               data = data->next;
+       }
+}
+
+int afb_hreq_post_add(struct afb_hreq *hreq, const char *key, const char *data, size_t size)
+{
+       void *p;
+       struct hreq_data *hdat = get_data(hreq, key, 1);
+       if (hdat->file) {
+               return 0;
+       }
+       p = realloc(hdat->value, hdat->length + size + 1);
+       if (p == NULL) {
+               return 0;
+       }
+       hdat->value = p;
+       memcpy(&hdat->value[hdat->length], data, size);
+       hdat->length += size;
+       hdat->value[hdat->length] = 0;
+       return 1;
+}
+
+int afb_hreq_post_add_file(struct afb_hreq *hreq, const char *key, const char *file, const char *data, size_t size)
+{
+       struct hreq_data *hdat = get_data(hreq, key, 1);
+
+       /* continuation with reopening */
+       if (hdat->file < 0) {
+               hdat->file = open(hdat->value, O_WRONLY|O_APPEND);
+               if (hdat->file == 0) {
+                       hdat->file = dup(0);
+                       close(0);
+               }
+               if (hdat->file <= 0)
+                       return 0;
+       }
+       if (hdat->file > 0) {
+               write(hdat->file, data, size);
+               return 1;
+       }
+
+       /* creation */
+       /* TODO */
+       return 0;
+       
+}
+
index b5f1e0b..7e77427 100644 (file)
  */
 
 
-struct afb_req_itf;
-
-
-struct afb_hreq_post {
-       const char *upload_data;
-       size_t *upload_data_size;
-};
-
 struct afb_hreq {
        AFB_session *session;
        struct MHD_Connection *connection;
@@ -33,10 +25,8 @@ struct afb_hreq {
        size_t lenurl;
        const char *tail;
        size_t lentail;
-       struct afb_hreq **recorder;
-       int (*post_handler) (struct afb_hreq *, struct afb_hreq_post *);
-       int (*post_completed) (struct afb_hreq *, struct afb_hreq_post *);
-       void *post_data;
+       struct MHD_PostProcessor *postform;
+       void *data;
 };
 
 extern int afb_hreq_unprefix(struct afb_hreq *request, const char *prefix, size_t length);
@@ -57,5 +47,12 @@ extern const char *afb_hreq_get_argument(struct afb_hreq *hreq, const char *name
 
 extern const char *afb_hreq_get_header(struct afb_hreq *hreq, const char *name);
 
-extern struct afb_req_itf afb_hreq_itf;
+extern int afb_hreq_post_add_file(struct afb_hreq *hreq, const char *key, const char *file, const char *data, size_t size);
+
+extern int afb_hreq_post_add(struct afb_hreq *hreq, const char *key, const char *data, size_t size);
+
+extern void afb_hreq_post_end(struct afb_hreq *hreq);
+
+struct afb_req_itf;
+extern const struct afb_req_itf afb_hreq_itf;
 
index 2b47794..49e5d8b 100644 (file)
@@ -36,7 +36,7 @@
 #define AFB_MSG_JTYPE "AJB_reply"
 
 #define JSON_CONTENT  "application/json"
-#define FORM_CONTENT  "multipart/form-data"    /* TODO: replace with MHD_HTTP_POST_ENCODING_MULTIPART_FORMDATA */
+#define FORM_CONTENT  MHD_HTTP_POST_ENCODING_MULTIPART_FORMDATA
 
 static json_object *afbJsonType;
 
@@ -67,8 +67,7 @@ static AFB_error doCallPluginApi(AFB_request * request, int apiidx, int verbidx,
 
        // Request was found and at least partially executed
        jreqt = json_object_new_object();
-       json_object_get(afbJsonType);   // increate jsontype reference count
-       json_object_object_add(jreqt, "jtype", afbJsonType);
+       json_object_object_add(jreqt, "jtype", json_object_get(afbJsonType));
 
        // prepare an object to store calling values
        jcall = json_object_new_object();
@@ -157,6 +156,7 @@ static AFB_error doCallPluginApi(AFB_request * request, int apiidx, int verbidx,
                        break;
                }
        }
+
        // Effectively CALL PLUGIN API with a subset of the context
        jresp = afb_apis_get(apiidx, verbidx)->callback(request, context);
 
@@ -193,7 +193,7 @@ ExitOnDone:
 extern __thread sigjmp_buf *error_handler;
 static AFB_error callPluginApi(AFB_request * request, int apiidx, int verbidx, void *context)
 {
-       sigjmp_buf jmpbuf;
+       sigjmp_buf jmpbuf, *older;
 
        json_object *jcall, *jreqt;
        int status;
@@ -204,8 +204,7 @@ static AFB_error callPluginApi(AFB_request * request, int apiidx, int verbidx, v
 
                // Request was found and at least partially executed
                jreqt = json_object_new_object();
-               json_object_get(afbJsonType);   // increate jsontype reference count
-               json_object_object_add(jreqt, "jtype", afbJsonType);
+               json_object_object_add(jreqt, "jtype", json_object_get(afbJsonType));
 
                // prepare an object to store calling values
                jcall = json_object_new_object();
@@ -217,23 +216,20 @@ static AFB_error callPluginApi(AFB_request * request, int apiidx, int verbidx, v
                json_object_object_add(jcall, "info", json_object_new_string("Plugin broke during execution"));
                json_object_object_add(jreqt, "request", jcall);
                request->jresp = jreqt;
-               goto ExitOnDone;
-
        } else {
 
                // Trigger a timer to protect from unacceptable long time execution
                if (request->config->apiTimeout > 0)
                        alarm((unsigned)request->config->apiTimeout);
 
+               older = error_handler;
                error_handler = &jmpbuf;
                doCallPluginApi(request, apiidx, verbidx, context);
-               error_handler = NULL;
+               error_handler = older;
 
                // cancel timeout and plugin signal handle before next call
                alarm(0);
        }
-
-ExitOnDone:
        return AFB_DONE;
 }
 
@@ -411,6 +407,7 @@ static int doRestApiPost(struct MHD_Connection *connection, AFB_session * sessio
                        postHandle->type = AFB_POST_EMPTY;
                        return MHD_YES;
                }
+
                // Form post is handle through a PostProcessor and call API once per form key
                if (strcasestr(encoding, FORM_CONTENT) != NULL) {
                        if (verbose)
@@ -449,11 +446,10 @@ static int doRestApiPost(struct MHD_Connection *connection, AFB_session * sessio
                        // if (verbose) fprintf(stderr, "Create PostJson[uid=%d] Size=%d\n", postHandle->uid, contentlen);
                        return MHD_YES;
 
-               } else {
-                       // We only support Json and Form Post format
-                       errMessage = jsonNewMessage(AFB_FATAL, "Post Date wrong type encoding=%s != %s", encoding, JSON_CONTENT);
-                       goto ExitOnError;
                }
+               // We only support Json and Form Post format
+               errMessage = jsonNewMessage(AFB_FATAL, "Post Date wrong type encoding=%s != %s", encoding, JSON_CONTENT);
+               goto ExitOnError;
        }
 
        // This time we receive partial/all Post data. Note that even if we get all POST data. We should nevertheless
@@ -475,41 +471,44 @@ static int doRestApiPost(struct MHD_Connection *connection, AFB_session * sessio
                *upload_data_size = 0;
                return MHD_YES;
 
-       } else {        // we have finish with Post reception let's finish the work
+       }
 
+       if (postHandle->type == AFB_POST_FORM)
+               request = postHandle->privatebuf;
+       else
                // Create a request structure to finalise the request
                request = createRequest(connection, session, url);
-               if (request->jresp != NULL) {
-                       errMessage = request->jresp;
-                       goto ExitOnError;
-               }
-               postRequest.type = postHandle->type;
 
-               // Postform add application context handle to request
-               if (postHandle->type == AFB_POST_FORM) {
-                       postRequest.data = (char *)postHandle;
-                       request->post = &postRequest;
-               }
+       if (request->jresp != NULL) {
+               errMessage = request->jresp;
+               goto ExitOnError;
+       }
+       postRequest.type = postHandle->type;
 
-               if (postHandle->type == AFB_POST_JSON) {
-                       // if (verbose) fprintf(stderr, "Processing PostJson[uid=%d]\n", postHandle->uid);
+       // Postform add application context handle to request
+       if (postHandle->type == AFB_POST_FORM) {
+               postRequest.data = (char *)postHandle;
+               request->post = &postRequest;
+       }
 
-                       param = MHD_lookup_connection_value(connection, MHD_HEADER_KIND, MHD_HTTP_HEADER_CONTENT_LENGTH);
-                       if (param)
-                               sscanf(param, "%i", &contentlen);
+       if (postHandle->type == AFB_POST_JSON) {
+               // if (verbose) fprintf(stderr, "Processing PostJson[uid=%d]\n", postHandle->uid);
 
-                       // At this level we're may verify that we got everything and process DATA
-                       if (postHandle->len != contentlen) {
-                               errMessage = jsonNewMessage(AFB_FATAL, "Post Data Incomplete UID=%d Len %d != %d", postHandle->uid, contentlen, postHandle->len);
-                               goto ExitOnError;
-                       }
-                       // Before processing data, make sure buffer string is properly ended
-                       postHandle->privatebuf[postHandle->len] = '\0';
-                       postRequest.data = postHandle->privatebuf;
-                       request->post = &postRequest;
+               param = MHD_lookup_connection_value(connection, MHD_HEADER_KIND, MHD_HTTP_HEADER_CONTENT_LENGTH);
+               if (param)
+                       sscanf(param, "%i", &contentlen);
 
-                       // if (verbose) fprintf(stderr, "Close Post[%d] Buffer=%s\n", postHandle->uid, request->post->data);
+               // At this level we're may verify that we got everything and process DATA
+               if (postHandle->len != contentlen) {
+                       errMessage = jsonNewMessage(AFB_FATAL, "Post Data Incomplete UID=%d Len %d != %d", postHandle->uid, contentlen, postHandle->len);
+                       goto ExitOnError;
                }
+               // Before processing data, make sure buffer string is properly ended
+               postHandle->privatebuf[postHandle->len] = '\0';
+               postRequest.data = postHandle->privatebuf;
+               request->post = &postRequest;
+
+               // if (verbose) fprintf(stderr, "Close Post[%d] Buffer=%s\n", postHandle->uid, request->post->data);
        }
 
  ProcessApiCall:
index 1c087e2..b604432 100644 (file)
@@ -136,7 +136,6 @@ static int headerhas(const char *header, const char *needle)
                if (!*header)
                        return 0;
                len = strcspn(header, sep);
-printf("!!!%.*s!!!\n",len,header);
                if (n == len && 0 == strncasecmp(needle, header, n))
                        return 1;
                header += len;
index 912093b..303fd57 100644 (file)
@@ -234,25 +234,6 @@ static void jsoninit()
 }
 
 
-
-// get JSON object from error level and increase its reference count
-struct json_object *jsonNewStatus (AFB_error level)
-{
-  jsoninit();
-  json_object *target =  AFBerr[level].json;
-  json_object_get (target);
-
-  return (target);
-}
-
-// get AFB object type with adequate usage count
-struct json_object *jsonNewjtype (void)
-{
-  jsoninit();
-  json_object_get (jTypeStatic); // increase reference count
-  return (jTypeStatic);
-}
-
 // build an ERROR message and return it as a valid json object
 struct json_object *jsonNewMessage (AFB_error level, char* format, ...) {
    static int count = 0;
@@ -270,7 +251,7 @@ struct json_object *jsonNewMessage (AFB_error level, char* format, ...) {
    }
 
    AFBResponse = json_object_new_object();
-   json_object_object_add (AFBResponse, "jtype", jsonNewjtype ());
+   json_object_object_add (AFBResponse, "jtype", json_object_get (jTypeStatic));
    json_object_object_add (AFBResponse, "status" , json_object_new_string (ERROR_LABEL[level]));
    if (format != NULL) {
         json_object_object_add (AFBResponse, "info"   , json_object_new_string (message));
@@ -288,11 +269,3 @@ struct json_object *jsonNewMessage (AFB_error level, char* format, ...) {
    return (AFBResponse);
 }
 
-// Dump a message on stderr
-void jsonDumpObject (struct json_object * jObject) {
-
-   if (verbose) {
-        fprintf (stderr, "AFB:dump [%s]\n", json_object_to_json_string(jObject));
-   }
-}
-
index f281bbf..e8ccfe8 100644 (file)
 #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, "<html><body>error %u</body></html>", status);
+       if (length > 0)
+               response = MHD_create_response_from_buffer((unsigned)length, buffer, MHD_RESPMEM_MUST_FREE);
+       else {
+               buffer = "<html><body>error</body></html>";
+               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;