fix uninit variable causing crash on 0 value
[oweals/gnunet.git] / src / gns / plugin_rest_gns.c
index bd28c23f3250a59a7cc4cfd71967a1bf7644171a..3cddbc2469a2754ab04266bca1201611669fbe5c 100644 (file)
@@ -1,22 +1,22 @@
 /*
-     This file is part of GNUnet.
-     Copyright (C) 2012-2015 Christian Grothoff (and other contributing authors)
-
-     GNUnet is free software; you can redistribute it and/or modify
-     it under the terms of the GNU General Public License as published
-     by the Free Software Foundation; either version 3, or (at your
-     option) any later version.
-
-     GNUnet is distributed in the hope that it will be useful, but
-     WITHOUT ANY WARRANTY; without even the implied warranty of
-     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-     General Public License for more details.
-
-     You should have received a copy of the GNU General Public License
-     along with GNUnet; see the file COPYING.  If not, write to the
-     Free Software Foundation, Inc., 59 Temple Place - Suite 330,
-     Boston, MA 02111-1307, USA.
-*/
+   This file is part of GNUnet.
+   Copyright (C) 2012-2015 GNUnet e.V.
+
+   GNUnet is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published
+   by the Free Software Foundation; either version 3, or (at your
+   option) any later version.
+
+   GNUnet is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with GNUnet; see the file COPYING.  If not, write to the
+   Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+   Boston, MA 02110-1301, USA.
+   */
 /**
  * @author Martin Schanzenbach
  * @file gns/plugin_rest_gns.c
 #include <gnunet_gnsrecord_lib.h>
 #include <gnunet_namestore_service.h>
 #include <gnunet_gns_service.h>
+#include <gnunet_rest_lib.h>
+#include <gnunet_jsonapi_lib.h>
+#include <gnunet_jsonapi_util.h>
 #include <jansson.h>
 
-#define API_NAMESPACE "gns"
+#define GNUNET_REST_API_NS_GNS "/gns"
+
+#define GNUNET_REST_JSONAPI_GNS_RECORD_TYPE "record_type"
+
+#define GNUNET_REST_JSONAPI_GNS_TYPEINFO "gns_name"
+
+#define GNUNET_REST_JSONAPI_GNS_RECORD "records"
+
+#define GNUNET_REST_JSONAPI_GNS_EGO "ego"
+
+#define GNUNET_REST_JSONAPI_GNS_PKEY "pkey"
+
+#define GNUNET_REST_JSONAPI_GNS_OPTIONS "options"
 
 /**
  * @brief struct returned by the initialization function of the plugin
@@ -47,103 +62,157 @@ const struct GNUNET_CONFIGURATION_Handle *cfg;
 
 struct LookupHandle
 {
-    /**
-     * Handle to GNS service.
-     */
-    struct GNUNET_GNS_Handle *gns;
-    
-    /**
-     * Desired timeout for the lookup (default is no timeout).
-     */
-    struct GNUNET_TIME_Relative timeout;
-    
-    /**
-     * Handle to lookup request
-     */
-    struct GNUNET_GNS_LookupRequest *lookup_request;
-
-    /**
-     * Lookup an ego with the identity service.
-     */
-    struct GNUNET_IDENTITY_EgoLookup *el;
-
-    /**
-     * Handle for identity service.
-     */
-    struct GNUNET_IDENTITY_Handle *identity;
-
-    /**
-     * Active operation on identity service.
-     */
-    struct GNUNET_IDENTITY_Operation *id_op;
-    /**
-     * ID of a task associated with the resolution process.
-     */
-    struct GNUNET_SCHEDULER_Task * timeout_task;    
-    
-    json_t *json_root;
-
-    GNUNET_REST_ResultProcessor proc;
-
-    char *name;
-
-    const char *ego_str;
-
-    const char *pkey_str;
-
-    int type;
-
-    struct GNUNET_CRYPTO_EcdsaPublicKey pkey;
-
-    struct GNUNET_CRYPTO_EcdsaPublicKey pkeym;
-    
-    enum GNUNET_GNS_LocalOptions options;
-    
-    struct GNUNET_CRYPTO_EcdsaPrivateKey shorten_key;
-    void *proc_cls;
+  /**
+   * Handle to GNS service.
+   */
+  struct GNUNET_GNS_Handle *gns;
+
+  /**
+   * Desired timeout for the lookup (default is no timeout).
+   */
+  struct GNUNET_TIME_Relative timeout;
+
+  /**
+   * Handle to lookup request
+   */
+  struct GNUNET_GNS_LookupRequest *lookup_request;
+
+  /**
+   * Handle to rest request
+   */
+  struct GNUNET_REST_RequestHandle *rest_handle;
+
+  /**
+   * Lookup an ego with the identity service.
+   */
+  struct GNUNET_IDENTITY_EgoLookup *el;
+
+  /**
+   * Handle for identity service.
+   */
+  struct GNUNET_IDENTITY_Handle *identity;
+
+  /**
+   * Active operation on identity service.
+   */
+  struct GNUNET_IDENTITY_Operation *id_op;
+
+  /**
+   * ID of a task associated with the resolution process.
+   */
+  struct GNUNET_SCHEDULER_Task * timeout_task;
+
+  /**
+   * The root of the received JSON or NULL
+   */
+  json_t *json_root;
+
+  /**
+   * The plugin result processor
+   */
+  GNUNET_REST_ResultProcessor proc;
+
+  /**
+   * The closure of the result processor
+   */
+  void *proc_cls;
+
+  /**
+   * The name to look up
+   */
+  char *name;
+
+  /**
+   * The ego to use
+   * In string representation from JSON
+   */
+  const char *ego_str;
+
+  /**
+   * The Pkey to use
+   * In string representation from JSON
+   */
+  const char *pkey_str;
+
+  /**
+   * The record type
+   */
+  int type;
+
+  /**
+   * The public key of to use for lookup
+   */
+  struct GNUNET_CRYPTO_EcdsaPublicKey pkey;
+
+  /**
+   * The public key to use for lookup
+   */
+  struct GNUNET_CRYPTO_EcdsaPublicKey pkeym;
+
+  /**
+   * The resolver options
+   */
+  enum GNUNET_GNS_LocalOptions options;
+
+  /**
+   * the shorten key
+   */
+  struct GNUNET_CRYPTO_EcdsaPrivateKey shorten_key;
+
+  /**
+   * HTTP response code
+   */
+  int response_code;
+
 };
 
-void
+
+/**
+ * Cleanup lookup handle.
+ *
+ * @param handle Handle to clean up
+ */
+static void
 cleanup_handle (struct LookupHandle *handle)
 {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                                    "Cleaning up\n");
-    if (NULL != handle->json_root)
-        json_decref (handle->json_root);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Cleaning up\n");
+  if (NULL != handle->json_root)
+    json_decref (handle->json_root);
 
-    if (NULL != handle->name)
-       GNUNET_free (handle->name);
-    if (NULL != handle->el)
-    {
-        GNUNET_IDENTITY_ego_lookup_cancel (handle->el);
-        handle->el = NULL;
-    }
-    if (NULL != handle->id_op)
-    {
-        GNUNET_IDENTITY_cancel (handle->id_op);
-        handle->id_op = NULL;
-    }
-    if (NULL != handle->lookup_request)
-    {
-        GNUNET_GNS_lookup_cancel (handle->lookup_request);
-        handle->lookup_request = NULL;
-    }
-    if (NULL != handle->identity)
-    {
-        GNUNET_IDENTITY_disconnect (handle->identity);
-        handle->identity = NULL;
-    }
-    if (NULL != handle->gns)
-    {
-        GNUNET_GNS_disconnect (handle->gns);
-        handle->gns = NULL;
-    }
+  if (NULL != handle->name)
+    GNUNET_free (handle->name);
+  if (NULL != handle->el)
+  {
+    GNUNET_IDENTITY_ego_lookup_cancel (handle->el);
+    handle->el = NULL;
+  }
+  if (NULL != handle->id_op)
+  {
+    GNUNET_IDENTITY_cancel (handle->id_op);
+    handle->id_op = NULL;
+  }
+  if (NULL != handle->lookup_request)
+  {
+    GNUNET_GNS_lookup_cancel (handle->lookup_request);
+    handle->lookup_request = NULL;
+  }
+  if (NULL != handle->identity)
+  {
+    GNUNET_IDENTITY_disconnect (handle->identity);
+    handle->identity = NULL;
+  }
+  if (NULL != handle->gns)
+  {
+    GNUNET_GNS_disconnect (handle->gns);
+    handle->gns = NULL;
+  }
 
-    if (NULL != handle->timeout_task)
-    {
-        GNUNET_SCHEDULER_cancel (handle->timeout_task);
-    }
-    GNUNET_free (handle);
+  if (NULL != handle->timeout_task)
+  {
+    GNUNET_SCHEDULER_cancel (handle->timeout_task);
+  }
+  GNUNET_free (handle);
 }
 
 
@@ -154,13 +223,64 @@ cleanup_handle (struct LookupHandle *handle)
  * @param tc scheduler context
  */
 static void
-do_error (void *cls,
-         const struct GNUNET_SCHEDULER_TaskContext *tc)
+do_error (void *cls)
 {
   struct LookupHandle *handle = cls;
-  
+  struct MHD_Response *resp;
+
+  resp = GNUNET_REST_create_response (NULL);
+  handle->proc (handle->proc_cls, resp, handle->response_code);
   cleanup_handle (handle);
-  handle->proc (handle->proc_cls, NULL, 0, GNUNET_SYSERR);
+}
+
+
+/**
+ * Create json representation of a GNSRECORD
+ *
+ * @param rd the GNSRECORD_Data
+ */
+static json_t *
+gnsrecord_to_json (const struct GNUNET_GNSRECORD_Data *rd)
+{
+  const char *typename;
+  char *string_val;
+  const char *exp_str;
+  json_t *record_obj;
+
+  typename = GNUNET_GNSRECORD_number_to_typename (rd->record_type);
+  string_val = GNUNET_GNSRECORD_value_to_string (rd->record_type,
+                                                 rd->data,
+                                                 rd->data_size);
+
+  if (NULL == string_val)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Record of type %d malformed, skipping\n",
+                (int) rd->record_type);
+    return NULL;
+  }
+  record_obj = json_object ();
+  json_object_set_new (record_obj, "type", json_string (typename));
+  json_object_set_new (record_obj, "value", json_string (string_val));
+  GNUNET_free (string_val);
+
+  if (GNUNET_GNSRECORD_RF_RELATIVE_EXPIRATION & rd->flags)
+  {
+    struct GNUNET_TIME_Relative time_rel;
+    time_rel.rel_value_us = rd->expiration_time;
+    exp_str = GNUNET_STRINGS_relative_time_to_string (time_rel, 1);
+  }
+  else
+  {
+    struct GNUNET_TIME_Absolute time_abs;
+    time_abs.abs_value_us = rd->expiration_time;
+    exp_str = GNUNET_STRINGS_absolute_time_to_string (time_abs);
+  }
+  json_object_set_new (record_obj, "expiration_time", json_string (exp_str));
+
+  json_object_set_new (record_obj, "expired",
+                       json_boolean (GNUNET_YES == GNUNET_GNSRECORD_is_expired (rd)));
+  return record_obj;
 }
 
 /**
@@ -172,66 +292,45 @@ do_error (void *cls,
  */
 static void
 process_lookup_result (void *cls, uint32_t rd_count,
-               const struct GNUNET_GNSRECORD_Data *rd)
+                       const struct GNUNET_GNSRECORD_Data *rd)
 {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                                              "result \n");
   struct LookupHandle *handle = cls;
+  struct MHD_Response *resp;
+  struct GNUNET_JSONAPI_Document *json_document;
+  struct GNUNET_JSONAPI_Resource *json_resource;
   uint32_t i;
-  const char *typename;
-  char *string_val;
   char *result;
-  json_t *result_root;
-  json_t *result_name;
   json_t *result_array;
   json_t *record_obj;
 
-
-  result_root = json_object();
-  result_name = json_string (handle->name);
   result_array = json_array();
-  json_object_set (result_root, "name", result_name);
-  json_decref (result_name);
-
+  json_document = GNUNET_JSONAPI_document_new ();
+  json_resource = GNUNET_JSONAPI_resource_new (GNUNET_REST_JSONAPI_GNS_TYPEINFO, handle->name);
   handle->lookup_request = NULL;
-  
   for (i=0; i<rd_count; i++)
   {
     if ( (rd[i].record_type != handle->type) &&
-     (GNUNET_GNSRECORD_TYPE_ANY != handle->type) )
-      continue;
-    typename = GNUNET_GNSRECORD_number_to_typename (rd[i].record_type);
-    string_val = GNUNET_GNSRECORD_value_to_string (rd[i].record_type,
-                           rd[i].data,
-                           rd[i].data_size);
-    if (NULL == string_val)
-    {
-      GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-           "Record %u of type %d malformed, skipping\n",
-           (unsigned int) i,
-           (int) rd[i].record_type);
+         (GNUNET_GNSRECORD_TYPE_ANY != handle->type) )
       continue;
-    }
-    else
-    {
-      record_obj = json_object();
-      json_object_set_new (record_obj, "type", json_string (typename));
-      json_object_set_new (record_obj, "value", json_string (string_val));
-      json_array_append (result_array, record_obj);
-      json_decref (record_obj);
-    }
-    GNUNET_free (string_val);
+    record_obj = gnsrecord_to_json (&(rd[i]));
+    json_array_append (result_array, record_obj);
+    json_decref (record_obj);
   }
-  json_object_set (result_root, "query_result", result_array);
+  GNUNET_JSONAPI_resource_add_attr (json_resource,
+                                         GNUNET_REST_JSONAPI_GNS_RECORD,
+                                         result_array);
+  GNUNET_JSONAPI_document_resource_add (json_document, json_resource);
+  GNUNET_JSONAPI_document_serialize (json_document, &result);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result);
   json_decref (result_array);
-  result = json_dumps (result_root, JSON_COMPACT);
-  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Result %s\n", result);
-  json_decref (result_root);
-  handle->proc (handle->proc_cls, result, strlen (result), GNUNET_OK);
+  GNUNET_JSONAPI_document_delete (json_document);
+  resp = GNUNET_REST_create_response (result);
+  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
   GNUNET_free (result);
   cleanup_handle (handle);
 }
 
+
 /**
  * Perform the actual resolution, starting with the zone
  * identified by the given public key and the shorten zone.
@@ -242,32 +341,26 @@ process_lookup_result (void *cls, uint32_t rd_count,
 static void
 lookup_with_keys (struct LookupHandle *handle, const struct GNUNET_CRYPTO_EcdsaPrivateKey *shorten_key)
 {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                                              "Lookup w/ keys \n");
   if (UINT32_MAX == handle->type)
   {
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-             _("Invalid typename specified, assuming `ANY'\n"));
+                _("Invalid typename specified, assuming `ANY'\n"));
     handle->type = GNUNET_GNSRECORD_TYPE_ANY;
   }
-
   if (NULL != handle->name)
   {
     handle->lookup_request = GNUNET_GNS_lookup (handle->gns,
-                    handle->name,
-                    &handle->pkey,
-                    handle->type,
-                    handle->options,
-                    shorten_key,
-                    &process_lookup_result,
-                    handle);
+                                                handle->name,
+                                                &handle->pkey,
+                                                handle->type,
+                                                handle->options,
+                                                shorten_key,
+                                                &process_lookup_result,
+                                                handle);
   }
   else
   {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-         _("Please specify name to lookup!\n"));
-    handle->proc (handle->proc_cls, NULL, 0, GNUNET_SYSERR);
-    cleanup_handle (handle);
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
     return;
   }
 }
@@ -286,12 +379,10 @@ lookup_with_keys (struct LookupHandle *handle, const struct GNUNET_CRYPTO_EcdsaP
  */
 static void
 identity_shorten_cb (void *cls,
-             struct GNUNET_IDENTITY_Ego *ego,
-             void **ctx,
-             const char *name)
+                     struct GNUNET_IDENTITY_Ego *ego,
+                     void **ctx,
+                     const char *name)
 {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                                              "shorten \n");
   struct LookupHandle *handle = cls;
 
   handle->id_op = NULL;
@@ -299,7 +390,7 @@ identity_shorten_cb (void *cls,
     lookup_with_keys (handle, NULL);
   else
     lookup_with_keys (handle,
-              GNUNET_IDENTITY_ego_get_private_key (ego));
+                      GNUNET_IDENTITY_ego_get_private_key (ego));
 }
 
 /**
@@ -311,14 +402,12 @@ identity_shorten_cb (void *cls,
 static void
 lookup_with_public_key (struct LookupHandle *handle)
 {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                                  "Lookup w/ pkey \n");
   handle->pkeym = handle->pkey;
   GNUNET_break (NULL == handle->id_op);
   handle->id_op = GNUNET_IDENTITY_get (handle->identity,
-                   "gns-short",
-                   &identity_shorten_cb,
-                   handle);
+                                       "gns-short",
+                                       &identity_shorten_cb,
+                                       handle);
   if (NULL == handle->id_op)
   {
     GNUNET_break (0);
@@ -335,7 +424,7 @@ lookup_with_public_key (struct LookupHandle *handle)
  */
 static void
 identity_zone_cb (void *cls,
-          const struct GNUNET_IDENTITY_Ego *ego)
+                  const struct GNUNET_IDENTITY_Ego *ego)
 {
   struct LookupHandle *handle = cls;
 
@@ -343,9 +432,8 @@ identity_zone_cb (void *cls,
   if (NULL == ego)
   {
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-         _("Ego for not found, cannot perform lookup.\n"));
-    handle->proc (handle->proc_cls, NULL, 0, GNUNET_SYSERR);
-    cleanup_handle (handle);
+                _("Ego for not found, cannot perform lookup.\n"));
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
     return;
   }
   else
@@ -370,22 +458,19 @@ identity_zone_cb (void *cls,
  */
 static void
 identity_master_cb (void *cls,
-            struct GNUNET_IDENTITY_Ego *ego,
-            void **ctx,
-            const char *name)
+                    struct GNUNET_IDENTITY_Ego *ego,
+                    void **ctx,
+                    const char *name)
 {
   const char *dot;
   struct LookupHandle *handle = cls;
-    
-  GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                      "Master cb \n");
+
   handle->id_op = NULL;
   if (NULL == ego)
   {
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-         _("Ego for `gns-master' not found, cannot perform lookup.  Did you run gnunet-gns-import.sh?\n"));
-    handle->proc (handle->proc_cls, NULL, 0, GNUNET_SYSERR);
-    cleanup_handle (handle);
+                _("Ego for `gns-master' not found, cannot perform lookup.  Did you run gnunet-gns-import.sh?\n"));
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
     return;
   }
   GNUNET_IDENTITY_ego_get_public_key (ego, &handle->pkey);
@@ -401,93 +486,168 @@ identity_master_cb (void *cls,
   lookup_with_public_key (handle);
 }
 
-int
+/**
+ * Parse REST uri for name and record type
+ *
+ * @param url Url to parse
+ * @param handle lookup handle to populate
+ * @return GNUNET_SYSERR on error
+ */
+static int
 parse_url (const char *url, struct LookupHandle *handle)
 {
-    char *name;
-    char *type;
-    char tmp_url[strlen(url)+1];
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Parsing %s\n", url);
-    strcpy (tmp_url, url);
-
-    char *tok = strtok ((char*)tmp_url, "/");
-    
-    
-    if (NULL == tok)
-        return GNUNET_SYSERR;
-
-    name = strtok (NULL, "/");
-
-    if (NULL == name)
-        return GNUNET_SYSERR;
+  char *name;
+  char tmp_url[strlen(url)+1];
+  char *tok;
+
+  strcpy (tmp_url, url);
+  tok = strtok ((char*)tmp_url, "/");
+  if (NULL == tok)
+    return GNUNET_SYSERR;
+  name = strtok (NULL, "/");
+  if (NULL == name)
+    return GNUNET_SYSERR;
+  GNUNET_asprintf (&handle->name,
+                   "%s",
+                   name);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Got name: %s\n", handle->name);
+  return GNUNET_OK;
+}
 
-    GNUNET_asprintf (&handle->name,
-                     "%s",
-                     name);
+static void
+get_gns_cont (struct GNUNET_REST_RequestHandle *conndata_handle,
+              const char* url,
+              void *cls)
+{
+  struct LookupHandle *handle = cls;
+  struct GNUNET_HashCode key;
 
+  //parse name and type from url
+  if (GNUNET_OK != parse_url (url, handle))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error parsing url...\n");
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Connecting...\n");
+  handle->gns = GNUNET_GNS_connect (cfg);
+  handle->identity = GNUNET_IDENTITY_connect (cfg, NULL, NULL);
+  handle->timeout_task = GNUNET_SCHEDULER_add_delayed (handle->timeout,
+                                                       &do_error, handle);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
+              "Connected\n");
+  if (NULL == handle->gns)
+  {
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-            "Got name: %s\n", handle->name);
-
-    type = strtok (NULL, "/");
+                "Connecting to GNS failed\n");
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+  GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_GNS_OPTIONS,
+                      strlen (GNUNET_REST_JSONAPI_GNS_OPTIONS),
+                      &key);
+  handle->options = GNUNET_GNS_LO_DEFAULT;
+  if ( GNUNET_YES ==
+       GNUNET_CONTAINER_multihashmap_contains (conndata_handle->url_param_map,
+                                               &key) )
+  {
+    handle->options = GNUNET_GNS_LO_DEFAULT;//TODO(char*) GNUNET_CONTAINER_multihashmap_get (conndata_handle->url_param_map,
+    //&key);
+  }
+  GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_GNS_RECORD_TYPE,
+                      strlen (GNUNET_REST_JSONAPI_GNS_RECORD_TYPE),
+                      &key);
+  if ( GNUNET_YES ==
+       GNUNET_CONTAINER_multihashmap_contains (conndata_handle->url_param_map,
+                                               &key) )
+  {
+    handle->type = GNUNET_GNSRECORD_typename_to_number
+      (GNUNET_CONTAINER_multihashmap_get (conndata_handle->url_param_map,
+                                          &key));
+  }
+  else
+    handle->type = GNUNET_GNSRECORD_TYPE_ANY;
 
-    if (NULL == type)
+  GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_GNS_PKEY,
+                      strlen (GNUNET_REST_JSONAPI_GNS_PKEY),
+                      &key);
+  if ( GNUNET_YES ==
+       GNUNET_CONTAINER_multihashmap_contains (conndata_handle->url_param_map,
+                                               &key) )
+  {
+    handle->pkey_str = GNUNET_CONTAINER_multihashmap_get (conndata_handle->url_param_map,
+                                                          &key);
+    if (GNUNET_OK !=
+        GNUNET_CRYPTO_ecdsa_public_key_from_string (handle->pkey_str,
+                                                    strlen(handle->pkey_str),
+                                                    &(handle->pkey)))
     {
-        handle->type = GNUNET_GNSRECORD_TYPE_ANY;
-        return GNUNET_OK;
+      GNUNET_SCHEDULER_add_now (&do_error, handle);
+      return;
     }
-
-    handle->type = GNUNET_GNSRECORD_typename_to_number (type);
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-            "Got type: %s\n", type);   
-    return GNUNET_OK;
+    lookup_with_public_key (handle);
+    return;
+  }
+  GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_GNS_EGO,
+                      strlen (GNUNET_REST_JSONAPI_GNS_EGO),
+                      &key);
+  if ( GNUNET_YES ==
+       GNUNET_CONTAINER_multihashmap_contains (conndata_handle->url_param_map,
+                                               &key) )
+  {
+    handle->ego_str = GNUNET_CONTAINER_multihashmap_get (conndata_handle->url_param_map,
+                                                         &key);
+    handle->el = GNUNET_IDENTITY_ego_lookup (cfg,
+                                             handle->ego_str,
+                                             &identity_zone_cb,
+                                             handle);
+    return;
+  }
+  if ( (NULL != handle->name) &&
+       (strlen (handle->name) > 4) &&
+       (0 == strcmp (".zkey",
+                     &handle->name[strlen (handle->name) - 4])) )
+  {
+    GNUNET_CRYPTO_ecdsa_key_get_public
+      (GNUNET_CRYPTO_ecdsa_key_get_anonymous (),
+       &(handle->pkey));
+    lookup_with_public_key (handle);
+  }
+  else
+  {
+    GNUNET_break (NULL == handle->id_op);
+    handle->id_op = GNUNET_IDENTITY_get (handle->identity,
+                                         "gns-master",
+                                         &identity_master_cb,
+                                         handle);
+    GNUNET_assert (NULL != handle->id_op);
+  }
 }
 
-int
-parse_json (const char *data, size_t data_size, struct LookupHandle *handle)
+/**
+ * Handle rest request
+ *
+ * @param handle the lookup handle
+ */
+static void
+options_cont (struct GNUNET_REST_RequestHandle *con_handle,
+              const char* url,
+              void *cls)
 {
-    json_error_t error;
-    json_t *pkey_json;
-    json_t *ego_json;
-    json_t *options_json;
-
-    char term_data[data_size+1];
-    term_data[data_size] = '\0';
-
-    memcpy (term_data, data, data_size);
-
-    handle->json_root = json_loads (term_data, 0, &error);
-
-    if (NULL == handle->json_root)
-    {
-        GNUNET_log (GNUNET_ERROR_TYPE_ERROR, error.text);
-        return GNUNET_SYSERR;
-    }
-
-    if(!json_is_object(handle->json_root))
-    {
-        return GNUNET_SYSERR;
-    }
-   
-    ego_json = json_object_get (handle->json_root, "ego");
-    
-    if(json_is_string(ego_json))
-    {
-        handle->ego_str = json_string_value (ego_json);
-    }
-
-    pkey_json = json_object_get (handle->json_root, "pkey");
-    if(json_is_string(pkey_json))
-    {
-        handle->pkey_str = json_string_value (pkey_json);
-    }
+  struct MHD_Response *resp;
+  struct LookupHandle *handle = cls;
 
-    options_json = json_object_get (handle->json_root, "options");
-    if(json_is_integer (options_json))
-    {
-        handle->options = json_integer_value (options_json);
-    }
-    return GNUNET_OK;
+  //For GNS, independent of path return all options
+  resp = GNUNET_REST_create_response (NULL);
+  MHD_add_response_header (resp,
+                           "Access-Control-Allow-Methods",
+                           MHD_HTTP_METHOD_GET);
+  handle->proc (handle->proc_cls,
+               resp,
+               MHD_HTTP_OK);
+  cleanup_handle (handle);
 }
 
 
@@ -502,113 +662,36 @@ parse_json (const char *data, size_t data_size, struct LookupHandle *handle)
  * @param proc_cls closure for callback function
  * @return GNUNET_OK if request accepted
  */
-void
-rest_gns_process_request(const char *method,
-                         const char *url,
-                         const char *data,
-                         size_t data_size,
+static void
+rest_gns_process_request(struct GNUNET_REST_RequestHandle *conndata_handle,
                          GNUNET_REST_ResultProcessor proc,
                          void *proc_cls)
 {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                        "In plugin\n");
-    struct LookupHandle *handle = GNUNET_new (struct LookupHandle);
-    
-    handle->timeout = GNUNET_TIME_UNIT_FOREVER_REL; //TODO read from json
-
-    //parse name and type from url
-    if (GNUNET_OK != parse_url (url, handle))
-    {
-        GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error parsing url...\n");
-        proc (proc_cls, NULL, 0, GNUNET_SYSERR);
-        cleanup_handle (handle);
-        return;
-    }
-    handle->proc_cls = proc_cls;
-    handle->proc = proc;
-    if (0 < data_size)
-    {
-        if (GNUNET_OK != parse_json (data, data_size, handle))
-        {
-            GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Error parsing json...\n");
-            proc (proc_cls, NULL, 0, GNUNET_SYSERR);
-            cleanup_handle (handle);
-            return;
-        }
-    }
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                        "Connecting...\n");
-    handle->gns = GNUNET_GNS_connect (cfg);
-    handle->identity = GNUNET_IDENTITY_connect (cfg, NULL, NULL);
-
-    handle->timeout_task = GNUNET_SCHEDULER_add_delayed (handle->timeout,
-                                  &do_error, handle);
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                        "Connected\n");
-
-    if (NULL == handle->gns)
-    {
-        GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                                        "Connecting to GNS failed\n");
-        proc (proc_cls, NULL, 0, GNUNET_SYSERR);
-        cleanup_handle (handle);
-        return;
-    }
-
-    if (NULL != handle->pkey_str)
-    {
-        GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                                      "pkey_str\n");
-        if (GNUNET_OK !=
-        GNUNET_CRYPTO_ecdsa_public_key_from_string (handle->pkey_str,
-                                                    strlen(handle->pkey_str),
-                                                    &(handle->pkey)))
-        {
-            proc (proc_cls, NULL, 0, GNUNET_SYSERR);
-            cleanup_handle (handle);
-            return;
-        }
-        lookup_with_public_key (handle);
-
-    }
-    if (NULL != handle->ego_str)
-    {
-        GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                                      "ego_str\n");
-        handle->el = GNUNET_IDENTITY_ego_lookup (cfg,
-                handle->ego_str,
-                &identity_zone_cb,
-                handle);
-        return;
-    }
-    if ( (NULL != handle->name) &&
-            (strlen (handle->name) > 4) &&
-            (0 == strcmp (".zkey",
-                          &handle->name[strlen (handle->name) - 4])) )
-    {
-        GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                                      "zkey\n");
-        /* no zone required, use 'anonymous' zone */
-        GNUNET_CRYPTO_ecdsa_key_get_public
-            (GNUNET_CRYPTO_ecdsa_key_get_anonymous (),
-             &(handle->pkey));
-        lookup_with_public_key (handle);
-    }
-    else
-    {
-        GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                                      "gns_master\n");
-        GNUNET_break (NULL == handle->id_op);
-        handle->id_op = GNUNET_IDENTITY_get (handle->identity,
-                "gns-master",
-                &identity_master_cb,
-                handle);
-        GNUNET_assert (NULL != handle->id_op);
-    }
+  struct LookupHandle *handle = GNUNET_new (struct LookupHandle);
+  struct GNUNET_REST_RequestHandlerError err;
+
+  handle->timeout = GNUNET_TIME_UNIT_FOREVER_REL;
+  handle->proc_cls = proc_cls;
+  handle->proc = proc;
+  handle->rest_handle = conndata_handle;
+
+  static const struct GNUNET_REST_RequestHandler handlers[] = {
+    {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_GNS, &get_gns_cont},
+    {MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_GNS, &options_cont},
+    GNUNET_REST_HANDLER_END
+  };
+
+  if (GNUNET_NO == GNUNET_JSONAPI_handle_request (conndata_handle,
+                                                  handlers,
+                                                  &err,
+                                                  handle))
+  {
+    handle->response_code = err.error_code;
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+  }
 }
 
+
 /**
  * Entry point for the plugin.
  *
@@ -628,10 +711,10 @@ libgnunet_plugin_rest_gns_init (void *cls)
   plugin.cfg = cfg;
   api = GNUNET_new (struct GNUNET_REST_Plugin);
   api->cls = &plugin;
-  api->name = API_NAMESPACE;
+  api->name = GNUNET_REST_API_NS_GNS;
   api->process_request = &rest_gns_process_request;
   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
-       _("GNS REST API initialized\n"));
+              _("GNS REST API initialized\n"));
   return api;
 }
 
@@ -643,7 +726,7 @@ libgnunet_plugin_rest_gns_init (void *cls)
  * @return always NULL
  */
 void *
-libgnunet_plugin_namestore_sqlite_done (void *cls)
+libgnunet_plugin_rest_gns_done (void *cls)
 {
   struct GNUNET_REST_Plugin *api = cls;
   struct Plugin *plugin = api->cls;
@@ -651,7 +734,7 @@ libgnunet_plugin_namestore_sqlite_done (void *cls)
   plugin->cfg = NULL;
   GNUNET_free (api);
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-       "GNS REST plugin is finished\n");
+              "GNS REST plugin is finished\n");
   return NULL;
 }