redirect with the query
authorJosé Bollo <jose.bollo@iot.bzh>
Sun, 29 May 2016 21:44:51 +0000 (23:44 +0200)
committerJosé Bollo <jose.bollo@iot.bzh>
Sun, 29 May 2016 21:47:36 +0000 (23:47 +0200)
Change-Id: I36c6c6cbc62217ff0d79e004d9b40aa77e3fa0f4
Signed-off-by: José Bollo <jose.bollo@iot.bzh>
src/afb-hreq.c
src/afb-hreq.h
src/afb-hswitch.c

index ab174e2..a325fd4 100644 (file)
@@ -390,24 +390,24 @@ int afb_hreq_reply_file_if_exist(struct afb_hreq *hreq, int dirfd, const char *f
 
        /* serve directory */
        if (S_ISDIR(st.st_mode)) {
-               static const char *indexes[] = { "index.html", NULL };
-               int i = 0;
-               rc = 0;
-               while (indexes[i] != NULL) {
-                       if (faccessat(fd, indexes[i], R_OK, 0) == 0) {
-                               if (hreq->url[hreq->lenurl - 1] != '/') {
-                                       /* the redirect is needed for reliability of relative path */
-                                       char *tourl = alloca(hreq->lenurl + 2);
-                                       memcpy(tourl, hreq->url, hreq->lenurl);
-                                       tourl[hreq->lenurl] = '/';
-                                       tourl[hreq->lenurl + 1] = 0;
-                                       rc = afb_hreq_redirect_to(hreq, tourl);
-                               } else {
+               if (hreq->url[hreq->lenurl - 1] != '/') {
+                       /* the redirect is needed for reliability of relative path */
+                       char *tourl = alloca(hreq->lenurl + 2);
+                       memcpy(tourl, hreq->url, hreq->lenurl);
+                       tourl[hreq->lenurl] = '/';
+                       tourl[hreq->lenurl + 1] = 0;
+                       rc = afb_hreq_redirect_to(hreq, tourl, 1);
+               } else {
+                       static const char *indexes[] = { "index.html", NULL };
+                       int i = 0;
+                       rc = 0;
+                       while (indexes[i] != NULL) {
+                               if (faccessat(fd, indexes[i], R_OK, 0) == 0) {
                                        rc = afb_hreq_reply_file_if_exist(hreq, fd, indexes[i]);
+                                       break;
                                }
-                               break;
+                               i++;
                        }
-                       i++;
                }
                close(fd);
                return rc;
@@ -472,12 +472,103 @@ int afb_hreq_reply_file(struct afb_hreq *hreq, int dirfd, const char *filename)
        return 1;
 }
 
-int afb_hreq_redirect_to(struct afb_hreq *hreq, const char *url)
+struct _mkq_ {
+       int count;
+       size_t length;
+       size_t alloc;
+       char *text;
+};
+
+static void _mkq_add_(struct _mkq_ *mkq, char value)
+{
+       char *text = mkq->text;
+       if (text != NULL) {
+               if (mkq->length == mkq->alloc) {
+                       mkq->alloc += 100;
+                       text = realloc(text, mkq->alloc);
+                       if (text == NULL) {
+                               free(mkq->text);
+                               mkq->text = NULL;
+                               return;
+                       }
+                       mkq->text = text;
+               }
+               text[mkq->length++] = value;
+       }
+}
+
+static void _mkq_add_hex_(struct _mkq_ *mkq, char value)
+{
+       _mkq_add_(mkq, (char)(value < 10 ? value + '0' : value + 'A' - 10));
+}
+
+static void _mkq_add_esc_(struct _mkq_ *mkq, char value)
+{
+       _mkq_add_(mkq, '%');
+       _mkq_add_hex_(mkq, (char)((value >> 4) & 15));
+       _mkq_add_hex_(mkq, (char)(value & 15));
+}
+
+static void _mkq_add_char_(struct _mkq_ *mkq, char value)
+{
+       if (value <= ' ' || value >= 127)
+               _mkq_add_esc_(mkq, value);
+       else
+               switch(value) {
+               case '=':
+               case '&':
+               case '%':
+                       _mkq_add_esc_(mkq, value);
+                       break;
+               default:
+                       _mkq_add_(mkq, value);
+               }
+}
+
+static void _mkq_append_(struct _mkq_ *mkq, const char *value)
+{
+       while(*value)
+               _mkq_add_char_(mkq, *value++);
+}
+
+static int _mkquery_(struct _mkq_ *mkq, enum MHD_ValueKind kind, const char *key, const char *value)
+{
+       _mkq_add_(mkq, mkq->count++ ? '&' : '?');
+       _mkq_append_(mkq, key);
+       if (value != NULL) {
+               _mkq_add_(mkq, '=');
+               _mkq_append_(mkq, value);
+       }
+       return 1;
+}
+
+static char *url_with_query(struct afb_hreq *hreq, const char *url)
+{
+       struct _mkq_ mkq;
+
+       mkq.count = 0;
+       mkq.length = strlen(url);
+       mkq.alloc = mkq.length + 1000;
+       mkq.text = malloc(mkq.alloc);
+       if (mkq.text != NULL) {
+               strcpy(mkq.text, url);
+               MHD_get_connection_values(hreq->connection, MHD_GET_ARGUMENT_KIND, (void*)_mkquery_, &mkq);
+               _mkq_add_(&mkq, 0);
+       }
+       return mkq.text;
+}
+
+int afb_hreq_redirect_to(struct afb_hreq *hreq, const char *url, int add_query_part)
 {
-       /* TODO: append the query part! */
+       const char *to;
+       char *wqp;
+
+       wqp = add_query_part ? url_with_query(hreq, url) : NULL;
+       to = wqp ? : url;
        afb_hreq_reply_static(hreq, MHD_HTTP_MOVED_PERMANENTLY, 0, NULL,
-                       MHD_HTTP_HEADER_LOCATION, url, NULL);
+                       MHD_HTTP_HEADER_LOCATION, to, NULL);
        DEBUG("redirect from [%s] to [%s]", hreq->url, url);
+       free(wqp);
        return 1;
 }
 
index 8e12b62..836f470 100644 (file)
@@ -58,7 +58,7 @@ extern int afb_hreq_reply_file_if_exist(struct afb_hreq *request, int dirfd, con
 
 extern int afb_hreq_reply_file(struct afb_hreq *request, int dirfd, const char *filename);
 
-extern int afb_hreq_redirect_to(struct afb_hreq *request, const char *url);
+extern int afb_hreq_redirect_to(struct afb_hreq *request, const char *url, int add_query_part);
 
 extern const char *afb_hreq_get_cookie(struct afb_hreq *hreq, const char *name);
 
index 417b773..fea30c5 100644 (file)
@@ -73,7 +73,7 @@ int afb_hswitch_one_page_api_redirect(struct afb_hreq *hreq, void *data)
        url[plen++] = '#';
        url[plen++] = '!';
        memcpy(&url[plen], &hreq->tail[1], hreq->lentail);
-       return afb_hreq_redirect_to(hreq, url);
+       return afb_hreq_redirect_to(hreq, url, 1);
 }
 
 int afb_hswitch_websocket_switch(struct afb_hreq *hreq, void *data)