allow empty/NULL context message
[oweals/gnunet.git] / src / namestore / plugin_rest_namestore.c
index 9b6b5c57c270373129c1ac701355920ebda655e1..78b6398c6845c6c1b4e81ecda476b1f7134a1907 100644 (file)
@@ -1,6 +1,6 @@
 /*
    This file is part of GNUnet.
-   Copyright (C) 2012-2015 Christian Grothoff (and other contributing authors)
+   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
 #include "gnunet_namestore_service.h"
 #include "gnunet_identity_service.h"
 #include "gnunet_rest_lib.h"
+#include "gnunet_jsonapi_lib.h"
+#include "gnunet_jsonapi_util.h"
 #include "microhttpd.h"
 #include <jansson.h>
 
 #define GNUNET_REST_API_NS_NAMESTORE "/names"
 
+#define GNUNET_REST_API_NS_NAMESTORE_ZKEY "/names/zkey"
+
 #define GNUNET_REST_JSONAPI_NAMESTORE_TYPEINFO "record"
 
+#define GNUNET_REST_JSONAPI_NAMESTORE_NAME "name"
+
+#define GNUNET_REST_JSONAPI_NAMESTORE_REVINFO "revinfo"
+
 #define GNUNET_REST_JSONAPI_NAMESTORE_RECORD GNUNET_REST_JSONAPI_NAMESTORE_TYPEINFO
 
 #define GNUNET_REST_JSONAPI_NAMESTORE_RECORD_TYPE "record_type"
@@ -48,6 +56,8 @@
 
 #define GNUNET_REST_JSONAPI_NAMESTORE_PKEY "pkey"
 
+#define GNUNET_REST_JSONAPI_NAMESTORE_ZKEY "zkey"
+
 #define GNUNET_REST_JSONAPI_NAMESTORE_EXPIRATION "expiration"
 
 #define GNUNET_REST_JSONAPI_NAMESTORE_EGO "ego"
@@ -60,6 +70,12 @@ struct Plugin
   const struct GNUNET_CONFIGURATION_Handle *cfg;
 };
 
+
+/**
+ * HTTP methods allows for this plugin
+ */
+static char* allow_methods;
+
 const struct GNUNET_CONFIGURATION_Handle *cfg;
 
 struct RecordEntry
@@ -68,12 +84,12 @@ struct RecordEntry
    * DLL
    */
   struct RecordEntry *next;
-  
+
   /**
    * DLL
    */
   struct RecordEntry *prev;
-  
+
 };
 
 struct RequestHandle
@@ -91,13 +107,13 @@ struct RequestHandle
   /**
    * JSON response object
    */
-  struct JsonApiObject *resp_object;
-  
+  struct GNUNET_JSONAPI_Document *resp_object;
+
   /**
    * Rest connection
    */
-  struct RestConnectionDataHandle *conndata_handle;
-  
+  struct GNUNET_REST_RequestHandle *rest_handle;
+
   /**
    * Handle to GNS service.
    */
@@ -107,12 +123,12 @@ struct RequestHandle
    * Handle to NAMESTORE
    */
   struct GNUNET_NAMESTORE_Handle *ns_handle;
-  
+
   /**
    * Handle to NAMESTORE it
    */
   struct GNUNET_NAMESTORE_ZoneIterator *list_it;
-  
+
   /**
    * Private key for the zone
    */
@@ -153,6 +169,11 @@ struct RequestHandle
    */
   char *value;
 
+  /**
+   * Zkey string
+   */
+  const char* zkey_str;
+
   /**
    * record type
    */
@@ -168,11 +189,16 @@ struct RequestHandle
    */
   unsigned int rd_count;
 
-    /**
+  /**
    * NAMESTORE Operation
    */
   struct GNUNET_NAMESTORE_QueueEntry *add_qe;
 
+  /**
+   * NAMESTORE Operation
+   */
+  struct GNUNET_NAMESTORE_QueueEntry *reverse_qe;
+
   /**
    * Desired timeout for the lookup (default is no timeout).
    */
@@ -181,7 +207,7 @@ struct RequestHandle
   /**
    * ID of a task associated with the resolution process.
    */
-  struct GNUNET_SCHEDULER_Task * timeout_task;    
+  struct GNUNET_SCHEDULER_Task * timeout_task;
 
   /**
    * The plugin result processor
@@ -199,25 +225,21 @@ struct RequestHandle
   char *url;
 
   /**
-   * The data from the REST request
+   * Cfg
    */
-  const char* data;
+  const struct GNUNET_CONFIGURATION_Handle *cfg;
 
   /**
-   * the length of the REST data
+   * HTTP response code
    */
-  size_t data_size;
-  
-  /**
-   * Cfg
-   */
-  const struct GNUNET_CONFIGURATION_Handle *cfg;
+  int response_code;
 
 };
 
 
 /**
  * Cleanup lookup handle
+ *
  * @param handle Handle to clean up
  */
 static void
@@ -226,8 +248,11 @@ cleanup_handle (struct RequestHandle *handle)
   struct RecordEntry *record_entry;
   struct RecordEntry *record_tmp;
   int i;
+
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               "Cleaning up\n");
+  if (NULL != handle->resp_object)
+    GNUNET_JSONAPI_document_delete (handle->resp_object);
   if (NULL != handle->name)
     GNUNET_free (handle->name);
   if (NULL != handle->timeout_task)
@@ -269,6 +294,7 @@ cleanup_handle (struct RequestHandle *handle)
   GNUNET_free (handle);
 }
 
+
 /**
  * Create json representation of a GNSRECORD
  *
@@ -324,28 +350,43 @@ gnsrecord_to_json (const struct GNUNET_GNSRECORD_Data *rd)
 
 
 /**
- * Task run on shutdown.  Cleans up everything.
+ * Task run on error.  Generates error response and cleans up.
  *
- * @param cls unused
- * @param tc scheduler context
+ * @param cls the request to generate an error response for
  */
 static void
-do_error (void *cls,
-          const struct GNUNET_SCHEDULER_TaskContext *tc)
+do_error (void *cls)
 {
   struct RequestHandle *handle = cls;
-  struct MHD_Response *resp = GNUNET_REST_create_json_response (NULL);
-  handle->proc (handle->proc_cls, resp, MHD_HTTP_BAD_REQUEST);
+  struct MHD_Response *resp = GNUNET_REST_create_response (NULL);
+
+  handle->proc (handle->proc_cls, resp, handle->response_code);
   cleanup_handle (handle);
 }
 
+
+/**
+ * Task run on timeout.
+ *
+ * @param cls the request to time out
+ */
+static void
+do_timeout (void *cls)
+{
+  struct RequestHandle *handle = cls;
+
+  handle->timeout_task = NULL;
+  do_error (handle);
+}
+
+
 static void
-cleanup_handle_delayed (void *cls,
-                        const struct GNUNET_SCHEDULER_TaskContext *tc)
+cleanup_handle_delayed (void *cls)
 {
   cleanup_handle (cls);
 }
 
+
 /**
  * Create a response with requested records
  *
@@ -359,7 +400,7 @@ namestore_list_response (void *cls,
                          const struct GNUNET_GNSRECORD_Data *rd)
 {
   struct RequestHandle *handle = cls;
-  struct JsonApiResource *json_resource;
+  struct GNUNET_JSONAPI_Resource *json_resource;
   struct MHD_Response *resp;
   json_t *result_array;
   json_t *record_obj;
@@ -367,21 +408,20 @@ namestore_list_response (void *cls,
   char *result;
 
   if (NULL == handle->resp_object)
-    handle->resp_object = GNUNET_REST_jsonapi_object_new ();
+    handle->resp_object = GNUNET_JSONAPI_document_new ();
 
   if (NULL == rname)
   {
     handle->list_it = NULL;
     //Handle response
-    if (GNUNET_SYSERR == GNUNET_REST_jsonapi_data_serialize (handle->resp_object, &result))
+    if (GNUNET_SYSERR == GNUNET_JSONAPI_document_serialize (handle->resp_object, &result))
     {
       GNUNET_SCHEDULER_add_now (&do_error, handle);
       return;
     }
-    GNUNET_REST_jsonapi_object_delete (handle->resp_object);
-    resp = GNUNET_REST_create_json_response (result);
+    resp = GNUNET_REST_create_response (result);
     handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
-    GNUNET_free (result);
+    GNUNET_free_non_null (result);
     GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle);
     return;
   }
@@ -410,12 +450,15 @@ namestore_list_response (void *cls,
     json_decref (record_obj);
   }
 
-  json_resource = GNUNET_REST_jsonapi_resource_new (GNUNET_REST_JSONAPI_NAMESTORE_TYPEINFO,
-                                                    rname);
-  GNUNET_REST_jsonapi_resource_add_attr (json_resource,
-                                         GNUNET_REST_JSONAPI_NAMESTORE_RECORD,
-                                         result_array);
-  GNUNET_REST_jsonapi_object_resource_add (handle->resp_object, json_resource);
+  if (0 < json_array_size(result_array))
+  {
+    json_resource = GNUNET_JSONAPI_resource_new (GNUNET_REST_JSONAPI_NAMESTORE_TYPEINFO,
+                                                      rname);
+    GNUNET_JSONAPI_resource_add_attr (json_resource,
+                                           GNUNET_REST_JSONAPI_NAMESTORE_RECORD,
+                                           result_array);
+    GNUNET_JSONAPI_document_resource_add (handle->resp_object, json_resource);
+  }
 
   json_decref (result_array);
   GNUNET_NAMESTORE_zone_iterator_next (handle->list_it);
@@ -437,7 +480,7 @@ create_finished (void *cls, int32_t success, const char *emsg)
     GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle);
     return;
   }
-  resp = GNUNET_REST_create_json_response (NULL);
+  resp = GNUNET_REST_create_response (NULL);
   handle->proc (handle->proc_cls, resp, MHD_HTTP_NO_CONTENT);
   GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle);
 }
@@ -471,13 +514,10 @@ create_new_record_cont (void *cls,
     return;
   }
 
-  GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-              "Received %u records for name `%s'\n",
-              rd_count, rec_name);
   if (0 != rd_count)
   {
     handle->proc (handle->proc_cls,
-                  GNUNET_REST_create_json_response (NULL),
+                  GNUNET_REST_create_response (NULL),
                   MHD_HTTP_CONFLICT);
     GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle);
     return;
@@ -520,7 +560,7 @@ del_finished (void *cls,
     return;
   }
   handle->proc (handle->proc_cls,
-                GNUNET_REST_create_json_response (NULL),
+                GNUNET_REST_create_response (NULL),
                 MHD_HTTP_NO_CONTENT);
   GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle);
 }
@@ -533,7 +573,7 @@ del_cont (void *cls,
           const struct GNUNET_GNSRECORD_Data *rd)
 {
   struct RequestHandle *handle = cls;
-
+  handle->add_qe = NULL;
   if (0 == rd_count)
   {
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
@@ -552,7 +592,7 @@ del_cont (void *cls,
 }
 
 static void
-namestore_delete_cont (struct RestConnectionDataHandle *con,
+namestore_delete_cont (struct GNUNET_REST_RequestHandle *con,
                        const char *url,
                        void *cls)
 {
@@ -619,7 +659,7 @@ json_to_gnsrecord (const json_t *records_json,
                   "Value property is no string\n");
       return GNUNET_SYSERR;
     }
-    GNUNET_asprintf (&value, "%s", json_string_value (value_json));
+    value = GNUNET_strdup (json_string_value (value_json));
     if (GNUNET_OK != GNUNET_GNSRECORD_string_to_value ((*rd)[i].record_type,
                                                        value,
                                                        &rdata,
@@ -663,7 +703,7 @@ json_to_gnsrecord (const json_t *records_json,
     {
       (*rd)[i].expiration_time = etime_abs.abs_value_us;
     }
-    else 
+    else
     {
       GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Value `%s' invalid for record type `%s'\n"),
                   value, typestring);
@@ -674,18 +714,23 @@ json_to_gnsrecord (const json_t *records_json,
 }
 
 static void
-namestore_create_cont (struct RestConnectionDataHandle *con,
+namestore_create_cont (struct GNUNET_REST_RequestHandle *con,
                        const char *url,
                        void *cls)
 {
   struct RequestHandle *handle = cls;
   struct MHD_Response *resp;
-  struct JsonApiObject *json_obj;
-  struct JsonApiResource *json_res;
-  json_t *name_json;
+  struct GNUNET_JSONAPI_Document *json_obj;
+  struct GNUNET_JSONAPI_Resource *json_res;
   json_t *records_json;
-  char term_data[handle->data_size+1];
-
+  json_t *data_js;
+  json_error_t err;
+  char term_data[handle->rest_handle->data_size+1];
+  struct GNUNET_JSON_Specification docspec[] = {
+    GNUNET_JSON_spec_jsonapi_document (&json_obj),
+    GNUNET_JSON_spec_end()
+  };
+  
   if (strlen (GNUNET_REST_API_NS_NAMESTORE) != strlen (handle->url))
   {
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
@@ -693,14 +738,22 @@ namestore_create_cont (struct RestConnectionDataHandle *con,
     GNUNET_SCHEDULER_add_now (&do_error, handle);
     return;
   }
-  if (0 >= handle->data_size)
+  if (0 >= handle->rest_handle->data_size)
   {
     GNUNET_SCHEDULER_add_now (&do_error, handle);
     return;
   }
-  term_data[handle->data_size] = '\0';
-  memcpy (term_data, handle->data, handle->data_size);
-  json_obj = GNUNET_REST_jsonapi_object_parse (term_data);
+  term_data[handle->rest_handle->data_size] = '\0';
+  memcpy (term_data,
+          handle->rest_handle->data,
+          handle->rest_handle->data_size);
+  data_js = json_loads (term_data,
+                        JSON_DECODE_ANY,
+                        &err);
+  GNUNET_assert (GNUNET_OK ==
+                 GNUNET_JSON_parse (data_js, docspec,
+                                    NULL, NULL));
+  json_decref (data_js);
   if (NULL == json_obj)
   {
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
@@ -709,54 +762,45 @@ namestore_create_cont (struct RestConnectionDataHandle *con,
     GNUNET_SCHEDULER_add_now (&do_error, handle);
     return;
   }
-  if (1 != GNUNET_REST_jsonapi_object_resource_count (json_obj))
+  if (1 != GNUNET_JSONAPI_document_resource_count (json_obj))
   {
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
                 "Cannot create more than 1 resource! (Got %d)\n",
-                GNUNET_REST_jsonapi_object_resource_count (json_obj));
-    GNUNET_REST_jsonapi_object_delete (json_obj);
+                GNUNET_JSONAPI_document_resource_count (json_obj));
+    GNUNET_JSONAPI_document_delete (json_obj);
     GNUNET_SCHEDULER_add_now (&do_error, handle);
     return;
   }
-  json_res = GNUNET_REST_jsonapi_object_get_resource (json_obj, 0);
-  if (GNUNET_NO == GNUNET_REST_jsonapi_resource_check_type (json_res,
-                                                            GNUNET_REST_JSONAPI_NAMESTORE_RECORD))
+  json_res = GNUNET_JSONAPI_document_get_resource (json_obj, 0);
+  if (GNUNET_NO == GNUNET_JSONAPI_resource_check_type (json_res,
+                                                       GNUNET_REST_JSONAPI_NAMESTORE_RECORD))
   {
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
                 "Unsupported JSON data type\n");
-    GNUNET_REST_jsonapi_object_delete (json_obj);
-    resp = GNUNET_REST_create_json_response (NULL);
+    GNUNET_JSONAPI_document_delete (json_obj);
+    resp = GNUNET_REST_create_response (NULL);
     handle->proc (handle->proc_cls, resp, MHD_HTTP_CONFLICT);
     cleanup_handle (handle);
     return;
   }
-  name_json = GNUNET_REST_jsonapi_resource_read_attr (json_res, GNUNET_REST_JSONAPI_KEY_ID);
-  if (!json_is_string (name_json))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Name property is no string\n");
-    GNUNET_REST_jsonapi_object_delete (json_obj); 
-    GNUNET_SCHEDULER_add_now (&do_error, handle);
-    return;
-  }
-  GNUNET_asprintf (&handle->name, "%s", json_string_value (name_json));
-  records_json = GNUNET_REST_jsonapi_resource_read_attr (json_res,
-                                                         GNUNET_REST_JSONAPI_NAMESTORE_RECORD);
+  handle->name = GNUNET_strdup (GNUNET_JSONAPI_resource_get_id (json_res));
+  records_json = GNUNET_JSONAPI_resource_read_attr (json_res,
+                                                    GNUNET_REST_JSONAPI_NAMESTORE_RECORD);
   if (NULL == records_json)
   {
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
                 "No records given\n");
-    GNUNET_REST_jsonapi_object_delete (json_obj);
+    GNUNET_JSONAPI_document_delete (json_obj);
     GNUNET_SCHEDULER_add_now (&do_error, handle);
     return;
   }
   if (GNUNET_SYSERR == json_to_gnsrecord (records_json, &handle->rd, &handle->rd_count))
   {
-    GNUNET_REST_jsonapi_object_delete (json_obj);
+    GNUNET_JSONAPI_document_delete (json_obj);
     GNUNET_SCHEDULER_add_now (&do_error, handle);
     return;
   }
-  GNUNET_REST_jsonapi_object_delete (json_obj);
+  GNUNET_JSONAPI_document_delete (json_obj);
 
   handle->add_qe = GNUNET_NAMESTORE_records_lookup (handle->ns_handle,
                                                     &handle->zone_pkey,
@@ -764,12 +808,91 @@ namestore_create_cont (struct RestConnectionDataHandle *con,
                                                     &create_new_record_cont, handle );
 }
 
+static void
+namestore_zkey_response (void *cls,
+                         const struct GNUNET_CRYPTO_EcdsaPrivateKey *zone,
+                         const char *label,
+                         unsigned int rd_count,
+                         const struct GNUNET_GNSRECORD_Data *rd)
+{
+  struct RequestHandle *handle = cls;
+  struct MHD_Response *resp;
+  struct GNUNET_JSONAPI_Document *json_obj;
+  struct GNUNET_JSONAPI_Resource *json_res;
+  json_t *name_json;
+  char* result;
 
+  handle->reverse_qe = NULL;
+  json_obj = GNUNET_JSONAPI_document_new ();
+  if (NULL != label)
+  {
+    name_json = json_string (label);
+    json_res = GNUNET_JSONAPI_resource_new (GNUNET_REST_JSONAPI_NAMESTORE_REVINFO,
+                                            handle->zkey_str);
+    GNUNET_JSONAPI_resource_add_attr (json_res,
+                                      GNUNET_REST_JSONAPI_NAMESTORE_NAME,
+                                      name_json);
+    GNUNET_JSONAPI_document_resource_add (json_obj, json_res);
+    json_decref (name_json);
+  }
+  //Handle response
+  if (GNUNET_SYSERR == GNUNET_JSONAPI_document_serialize (json_obj, &result))
+  {
+    GNUNET_JSONAPI_document_delete (json_obj);
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+  resp = GNUNET_REST_create_response (result);
+  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
+  GNUNET_JSONAPI_document_delete (json_obj);
+  GNUNET_free (result);
+  GNUNET_SCHEDULER_add_now (&cleanup_handle_delayed, handle);
+  return;
 
+}
 
+static void
+namestore_zkey_cont (struct GNUNET_REST_RequestHandle *con,
+                     const char *url,
+                     void *cls)
+{
+  struct RequestHandle *handle = cls;
+  struct GNUNET_HashCode key;
+  struct GNUNET_CRYPTO_EcdsaPublicKey pubkey;
+
+  GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_NAMESTORE_ZKEY,
+                      strlen (GNUNET_REST_JSONAPI_NAMESTORE_ZKEY),
+                      &key);
+  if ( GNUNET_NO ==
+       GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->url_param_map,
+                                               &key) )
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "No zkey given %s\n", handle->url);
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+  handle->zkey_str = GNUNET_CONTAINER_multihashmap_get (handle->rest_handle->url_param_map,
+                                                        &key);
+  if (GNUNET_OK !=
+      GNUNET_CRYPTO_ecdsa_public_key_from_string (handle->zkey_str,
+                                                  strlen (handle->zkey_str),
+                                                  &pubkey))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Zkey invalid %s\n", handle->zkey_str);
+    GNUNET_SCHEDULER_add_now (&do_error, handle);
+    return;
+  }
+  handle->reverse_qe = GNUNET_NAMESTORE_zone_to_name (handle->ns_handle,
+                                                      &handle->zone_pkey,
+                                                      &pubkey,
+                                                      &namestore_zkey_response,
+                                                      handle);
+}
 
 static void
-namestore_info_cont (struct RestConnectionDataHandle *con,
+namestore_info_cont (struct GNUNET_REST_RequestHandle *con,
                      const char *url,
                      void *cls)
 {
@@ -788,6 +911,31 @@ get_name_from_url (const char* url)
   return (char*)url + strlen (GNUNET_REST_API_NS_NAMESTORE) + 1;
 }
 
+/**
+ * Respond to OPTIONS request
+ *
+ * @param con_handle the connection handle
+ * @param url the url
+ * @param cls the RequestHandle
+ */
+static void
+options_cont (struct GNUNET_REST_RequestHandle *con_handle,
+              const char* url,
+              void *cls)
+{
+  struct MHD_Response *resp;
+  struct RequestHandle *handle = cls;
+
+  //For now, independent of path return all options
+  resp = GNUNET_REST_create_response (NULL);
+  MHD_add_response_header (resp,
+                           "Access-Control-Allow-Methods",
+                           allow_methods);
+  handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
+  cleanup_handle (handle);
+  return;
+}
+
 /**
  * Function called with the result from the check if the namestore
  * service is actually running.  If it is, we start the actual
@@ -801,11 +949,14 @@ testservice_task (void *cls,
                   int result)
 {
   struct RequestHandle *handle = cls;
-  static const struct GNUNET_REST_RestConnectionHandler handlers[] = {
+  struct GNUNET_REST_RequestHandlerError err;
+  static const struct GNUNET_REST_RequestHandler handlers[] = {
+    {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_NAMESTORE_ZKEY, &namestore_zkey_cont}, //reverse
     {MHD_HTTP_METHOD_GET, GNUNET_REST_API_NS_NAMESTORE, &namestore_info_cont}, //list
     {MHD_HTTP_METHOD_POST, GNUNET_REST_API_NS_NAMESTORE, &namestore_create_cont}, //create
     //    {MHD_HTTP_METHOD_PUT, GNUNET_REST_API_NS_NAMESTORE, &namestore_edit_cont}, //update. TODO this shoul be PATCH
     {MHD_HTTP_METHOD_DELETE, GNUNET_REST_API_NS_NAMESTORE, &namestore_delete_cont}, //delete
+    {MHD_HTTP_METHOD_OPTIONS, GNUNET_REST_API_NS_NAMESTORE, &options_cont},
     GNUNET_REST_HANDLER_END
   };
 
@@ -825,8 +976,14 @@ testservice_task (void *cls,
     return;
   }
 
-  if (GNUNET_NO == GNUNET_REST_handle_request (handle->conndata_handle, handlers, handle))
+  if (GNUNET_OK != GNUNET_JSONAPI_handle_request (handle->rest_handle,
+                                                  handlers,
+                                                  &err,
+                                                  handle))
+  {
+    handle->response_code = err.error_code;
     GNUNET_SCHEDULER_add_now (&do_error, (void*) handle);
+  }
 
 }
 
@@ -853,7 +1010,7 @@ identity_cb (void *cls,
                   _("Ego `%s' not known to identity service\n"),
                   handle->ego_name);
     }
-    resp = GNUNET_REST_create_json_response (NULL);
+    resp = GNUNET_REST_create_response (NULL);
     handle->proc (handle->proc_cls, resp, MHD_HTTP_NOT_FOUND);
     cleanup_handle (handle);
     return;
@@ -878,7 +1035,7 @@ default_ego_cb (void *cls,
   {
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
                 _("No default ego configured in identity service\n"));
-    resp = GNUNET_REST_create_json_response (NULL);
+    resp = GNUNET_REST_create_response (NULL);
     handle->proc (handle->proc_cls, resp, MHD_HTTP_NOT_FOUND);
     cleanup_handle (handle);
     return;
@@ -918,7 +1075,7 @@ testservice_id_task (void *cls, int result)
   {
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
                 _("Identity service is not running\n"));
-    resp = GNUNET_REST_create_json_response (NULL);
+    resp = GNUNET_REST_create_response (NULL);
     handle->proc (handle->proc_cls, resp, MHD_HTTP_NOT_FOUND);
     cleanup_handle (handle);
     return;
@@ -927,40 +1084,39 @@ testservice_id_task (void *cls, int result)
   GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_NAMESTORE_EGO,
                       strlen (GNUNET_REST_JSONAPI_NAMESTORE_EGO),
                       &key);
-  if ( GNUNET_YES == 
-       GNUNET_CONTAINER_multihashmap_contains (handle->conndata_handle->url_param_map,
+  if ( GNUNET_YES ==
+       GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->url_param_map,
                                                &key) )
   {
-    ego = GNUNET_CONTAINER_multihashmap_get (handle->conndata_handle->url_param_map,
+    ego = GNUNET_CONTAINER_multihashmap_get (handle->rest_handle->url_param_map,
                                              &key);
   }
 
-  type = GNUNET_GNSRECORD_TYPE_ANY;
+  handle->type = GNUNET_GNSRECORD_TYPE_ANY;
   GNUNET_CRYPTO_hash (GNUNET_REST_JSONAPI_NAMESTORE_RECORD_TYPE,
                       strlen (GNUNET_REST_JSONAPI_NAMESTORE_RECORD_TYPE),
                       &key);
-  if ( GNUNET_YES == 
-       GNUNET_CONTAINER_multihashmap_contains (handle->conndata_handle->url_param_map,
+  if ( GNUNET_YES ==
+       GNUNET_CONTAINER_multihashmap_contains (handle->rest_handle->url_param_map,
                                                &key) )
   {
-    type = GNUNET_CONTAINER_multihashmap_get (handle->conndata_handle->url_param_map,
+    type = GNUNET_CONTAINER_multihashmap_get (handle->rest_handle->url_param_map,
                                               &key);
+
+    handle->type = GNUNET_GNSRECORD_typename_to_number (type);
   }
-  handle->type = GNUNET_GNSRECORD_typename_to_number (type);
   name = get_name_from_url (handle->url);
   if (NULL != ego)
-    GNUNET_asprintf (&handle->ego_name, "%s", ego);
+    handle->ego_name = GNUNET_strdup (ego);
   if (NULL != name)
-    GNUNET_asprintf (&handle->name, "%s", name);
-  GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s\n", handle->ego_name);
+    handle->name = GNUNET_strdup (name);
   if (NULL == handle->ego_name)
   {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "%s\n", handle->ego_name);
     handle->identity_handle = GNUNET_IDENTITY_connect (handle->cfg, &id_connect_cb, handle);
     if (NULL == handle->identity_handle)
     {
       GNUNET_log (GNUNET_ERROR_TYPE_ERROR, _("Cannot connect to identity service\n"));
-      resp = GNUNET_REST_create_json_response (NULL);
+      resp = GNUNET_REST_create_response (NULL);
       handle->proc (handle->proc_cls, resp, MHD_HTTP_NOT_FOUND);
       cleanup_handle (handle);
     }
@@ -984,7 +1140,7 @@ testservice_id_task (void *cls, int result)
  * @return GNUNET_OK if request accepted
  */
 static void
-rest_identity_process_request(struct RestConnectionDataHandle *conndata_handle,
+rest_identity_process_request(struct GNUNET_REST_RequestHandle *rest_handle,
                               GNUNET_REST_ResultProcessor proc,
                               void *proc_cls)
 {
@@ -993,10 +1149,8 @@ rest_identity_process_request(struct RestConnectionDataHandle *conndata_handle,
   handle->timeout = GNUNET_TIME_UNIT_FOREVER_REL;
   handle->proc_cls = proc_cls;
   handle->proc = proc;
-  handle->conndata_handle = conndata_handle;
-  handle->data = conndata_handle->data;
-  handle->data_size = conndata_handle->data_size;
-  GNUNET_asprintf (&handle->url, "%s", conndata_handle->url);
+  handle->rest_handle = rest_handle;
+  handle->url = GNUNET_strdup (rest_handle->url);
   if (handle->url[strlen (handle->url)-1] == '/')
     handle->url[strlen (handle->url)-1] = '\0';
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
@@ -1008,10 +1162,8 @@ rest_identity_process_request(struct RestConnectionDataHandle *conndata_handle,
                               &testservice_id_task,
                               handle);
   handle->timeout_task = GNUNET_SCHEDULER_add_delayed (handle->timeout,
-                                                       &do_error,
+                                                       &do_timeout,
                                                        handle);
-
-
 }
 
 /**
@@ -1035,6 +1187,13 @@ libgnunet_plugin_rest_namestore_init (void *cls)
   api->cls = &plugin;
   api->name = GNUNET_REST_API_NS_NAMESTORE;
   api->process_request = &rest_identity_process_request;
+  GNUNET_asprintf (&allow_methods,
+                   "%s, %s, %s, %s, %s",
+                   MHD_HTTP_METHOD_GET,
+                   MHD_HTTP_METHOD_POST,
+                   MHD_HTTP_METHOD_PUT,
+                   MHD_HTTP_METHOD_DELETE,
+                   MHD_HTTP_METHOD_OPTIONS);
   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
               _("Namestore REST API initialized\n"));
   return api;
@@ -1055,6 +1214,7 @@ libgnunet_plugin_rest_namestore_done (void *cls)
 
   plugin->cfg = NULL;
   GNUNET_free (api);
+  GNUNET_free_non_null (allow_methods);
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
               "Namestore REST plugin is finished\n");
   return NULL;