aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMartin Schanzenbach <mschanzenbach@posteo.de>2015-03-25 15:58:38 +0000
committerMartin Schanzenbach <mschanzenbach@posteo.de>2015-03-25 15:58:38 +0000
commit08cd39e74d35cec73f54de9826961a97d8a8ea0d (patch)
treef85511b479dc9480427dffaaaa5425ebc221c87c /src
parent00f87691363acaf94f533793654e610e46bf4e1d (diff)
downloadgnunet-08cd39e74d35cec73f54de9826961a97d8a8ea0d.tar.gz
gnunet-08cd39e74d35cec73f54de9826961a97d8a8ea0d.zip
-start a lib for REST and json:api
Diffstat (limited to 'src')
-rw-r--r--src/identity/Makefile.am1
-rw-r--r--src/identity/plugin_rest_identity.c123
-rw-r--r--src/include/gnunet_rest_lib.h156
-rw-r--r--src/include/gnunet_rest_plugin.h1
-rw-r--r--src/rest/Makefile.am12
-rw-r--r--src/rest/rest.c299
6 files changed, 502 insertions, 90 deletions
diff --git a/src/identity/Makefile.am b/src/identity/Makefile.am
index 6aabddd39..b0e7645b0 100644
--- a/src/identity/Makefile.am
+++ b/src/identity/Makefile.am
@@ -32,6 +32,7 @@ libgnunet_plugin_rest_identity_la_SOURCES = \
32 plugin_rest_identity.c 32 plugin_rest_identity.c
33libgnunet_plugin_rest_identity_la_LIBADD = \ 33libgnunet_plugin_rest_identity_la_LIBADD = \
34 $(top_builddir)/src/identity/libgnunetidentity.la \ 34 $(top_builddir)/src/identity/libgnunetidentity.la \
35 $(top_builddir)/src/rest/libgnunetrest.la \
35 $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) \ 36 $(top_builddir)/src/util/libgnunetutil.la $(XLIBS) \
36 $(LTLIBINTL) -ljansson -lmicrohttpd 37 $(LTLIBINTL) -ljansson -lmicrohttpd
37libgnunet_plugin_rest_identity_la_LDFLAGS = \ 38libgnunet_plugin_rest_identity_la_LDFLAGS = \
diff --git a/src/identity/plugin_rest_identity.c b/src/identity/plugin_rest_identity.c
index 1bc5f6fea..ea611128d 100644
--- a/src/identity/plugin_rest_identity.c
+++ b/src/identity/plugin_rest_identity.c
@@ -27,6 +27,7 @@
27#include "platform.h" 27#include "platform.h"
28#include "gnunet_rest_plugin.h" 28#include "gnunet_rest_plugin.h"
29#include "gnunet_identity_service.h" 29#include "gnunet_identity_service.h"
30#include "gnunet_rest_lib.h"
30#include "microhttpd.h" 31#include "microhttpd.h"
31#include <jansson.h> 32#include <jansson.h>
32 33
@@ -40,9 +41,9 @@
40 41
41#define URL_PARAM_SUBSYS "service" 42#define URL_PARAM_SUBSYS "service"
42 43
43#define JSON_API_TYPE_EGO "ego" 44#define GNUNET_REST_JSONAPI_IDENTITY_EGO "ego"
44 45
45#define JSON_API_TYPE_DATA "data" 46#define GNUNET_REST_JSONAPI_IDENTITY_KEY "key"
46 47
47/** 48/**
48 * @brief struct returned by the initialization function of the plugin 49 * @brief struct returned by the initialization function of the plugin
@@ -168,27 +169,6 @@ struct RequestHandle
168 169
169}; 170};
170 171
171/**
172 * Create s JSON Response for MHD
173 *
174 * @param data the JSON to return (can be NULL)
175 * @return a MHD_Response handle
176 */
177struct MHD_Response*
178create_json_response (const char *data)
179{
180 size_t len;
181 if (NULL == data)
182 len = 0;
183 else
184 len = strlen (data);
185 struct MHD_Response *resp = MHD_create_response_from_buffer (len,
186 (void*)data,
187 MHD_RESPMEM_MUST_COPY);
188 MHD_add_response_header (resp,MHD_HTTP_HEADER_CONTENT_TYPE,"application/json");
189 return resp;
190}
191
192 172
193/** 173/**
194 * Cleanup lookup handle 174 * Cleanup lookup handle
@@ -236,7 +216,7 @@ do_error (void *cls,
236 const struct GNUNET_SCHEDULER_TaskContext *tc) 216 const struct GNUNET_SCHEDULER_TaskContext *tc)
237{ 217{
238 struct RequestHandle *handle = cls; 218 struct RequestHandle *handle = cls;
239 struct MHD_Response *resp = create_json_response (NULL); 219 struct MHD_Response *resp = GNUNET_REST_create_json_response (NULL);
240 handle->proc (handle->proc_cls, resp, MHD_HTTP_BAD_REQUEST); 220 handle->proc (handle->proc_cls, resp, MHD_HTTP_BAD_REQUEST);
241 cleanup_handle (handle); 221 cleanup_handle (handle);
242} 222}
@@ -277,7 +257,7 @@ get_ego_for_subsys (void *cls,
277 ego_json = json_object (); 257 ego_json = json_object ();
278 keystring = GNUNET_CRYPTO_ecdsa_public_key_to_string (&ego_entry->pk); 258 keystring = GNUNET_CRYPTO_ecdsa_public_key_to_string (&ego_entry->pk);
279 json_object_set_new (ego_json, "id", json_string (ego_entry->identifier)); 259 json_object_set_new (ego_json, "id", json_string (ego_entry->identifier));
280 json_object_set_new (ego_json, "type", json_string (JSON_API_TYPE_EGO)); 260 json_object_set_new (ego_json, "type", json_string (GNUNET_REST_JSONAPI_IDENTITY_EGO));
281 json_object_set_new (ego_json, "key", json_string (keystring)); 261 json_object_set_new (ego_json, "key", json_string (keystring));
282 GNUNET_free (keystring); 262 GNUNET_free (keystring);
283 break; 263 break;
@@ -288,43 +268,18 @@ get_ego_for_subsys (void *cls,
288 GNUNET_SCHEDULER_add_now (&do_error, handle); 268 GNUNET_SCHEDULER_add_now (&do_error, handle);
289 return; 269 return;
290 } 270 }
291 json_object_set (root_json, JSON_API_TYPE_DATA, ego_json); 271 json_object_set (root_json, GNUNET_REST_JSONAPI_KEY_DATA, ego_json);
292 result_str = json_dumps (root_json, JSON_COMPACT); 272 result_str = json_dumps (root_json, JSON_COMPACT);
293 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result_str); 273 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result_str);
294 json_decref (ego_json); 274 json_decref (ego_json);
295 json_decref (root_json); 275 json_decref (root_json);
296 resp = create_json_response (result_str); 276 resp = GNUNET_REST_create_json_response (result_str);
297 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK); 277 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
298 GNUNET_free (result_str); 278 GNUNET_free (result_str);
299 cleanup_handle (handle); 279 cleanup_handle (handle);
300} 280}
301 281
302/** 282/**
303 * Validate the namespace of the requested url
304 * TODO move this to a lib
305 *
306 * @param url the url
307 * @param ns the namespace
308 */
309int
310check_namespace (const char *url, const char *ns)
311{
312 if (0 != strncmp (EGO_NAMESPACE, url, strlen (EGO_NAMESPACE)))
313 {
314 return GNUNET_NO;
315 }
316
317 if ((strlen (EGO_NAMESPACE) < strlen (url)) &&
318 (url[strlen (EGO_NAMESPACE)] != '/'))
319 {
320 return GNUNET_NO;
321 }
322 return GNUNET_YES;
323
324
325}
326
327/**
328 * Create a response with requested ego(s) 283 * Create a response with requested ego(s)
329 * 284 *
330 * @param handle the RequestHandle 285 * @param handle the RequestHandle
@@ -339,18 +294,19 @@ ego_info_response (struct RequestHandle *handle)
339 struct EgoEntry *ego_entry; 294 struct EgoEntry *ego_entry;
340 struct GNUNET_HashCode key; 295 struct GNUNET_HashCode key;
341 struct MHD_Response *resp; 296 struct MHD_Response *resp;
342 json_t *ego_arr; 297 struct JsonApiResponse *json_response;
343 json_t *ego_json; 298 struct JsonApiResource *json_resource;
344 json_t *root_json; 299 json_t *key_str;
345 300
346 if (GNUNET_NO == check_namespace (handle->url, EGO_NAMESPACE)) 301 if (GNUNET_NO == GNUNET_REST_namespace_match (handle->url, EGO_NAMESPACE))
347 { 302 {
348 resp = create_json_response (NULL); 303 resp = GNUNET_REST_create_json_response (NULL);
349 handle->proc (handle->proc_cls, resp, MHD_HTTP_BAD_REQUEST); 304 handle->proc (handle->proc_cls, resp, MHD_HTTP_BAD_REQUEST);
350 cleanup_handle (handle); 305 cleanup_handle (handle);
351 GNUNET_break (0); 306 GNUNET_break (0);
352 return; 307 return;
353 } 308 }
309 json_response = GNUNET_REST_jsonapi_response_new ();
354 if ( (strlen (EGO_NAMESPACE) == strlen (handle->url) )) { 310 if ( (strlen (EGO_NAMESPACE) == strlen (handle->url) )) {
355 GNUNET_CRYPTO_hash (URL_PARAM_SUBSYS, strlen (URL_PARAM_SUBSYS), &key); 311 GNUNET_CRYPTO_hash (URL_PARAM_SUBSYS, strlen (URL_PARAM_SUBSYS), &key);
356 if ( GNUNET_YES == 312 if ( GNUNET_YES ==
@@ -371,8 +327,7 @@ ego_info_response (struct RequestHandle *handle)
371 } 327 }
372 } 328 }
373 } 329 }
374 ego_arr = json_array (); 330 json_response = GNUNET_REST_jsonapi_response_new ();
375 root_json = json_object ();
376 egoname = &handle->url[strlen (EGO_NAMESPACE)+1]; 331 egoname = &handle->url[strlen (EGO_NAMESPACE)+1];
377 332
378 if (strlen (EGO_NAMESPACE) == strlen (handle->url)) 333 if (strlen (EGO_NAMESPACE) == strlen (handle->url))
@@ -387,36 +342,24 @@ ego_info_response (struct RequestHandle *handle)
387 { 342 {
388 if ( (NULL != egoname) && (0 != strcmp (egoname, ego_entry->identifier)) ) 343 if ( (NULL != egoname) && (0 != strcmp (egoname, ego_entry->identifier)) )
389 continue; 344 continue;
390 ego_json = json_object ();
391 keystring = GNUNET_CRYPTO_ecdsa_public_key_to_string (&ego_entry->pk); 345 keystring = GNUNET_CRYPTO_ecdsa_public_key_to_string (&ego_entry->pk);
392 json_object_set_new (ego_json, "id", json_string (ego_entry->identifier)); 346 json_resource = GNUNET_REST_jsonapi_resource_new (GNUNET_REST_JSONAPI_IDENTITY_EGO, ego_entry->identifier);
393 json_object_set_new (ego_json, "key", json_string (keystring)); 347 key_str = json_string (keystring);
394 json_object_set_new (ego_json, "type", json_string (JSON_API_TYPE_EGO)); 348 GNUNET_REST_jsonapi_resource_add_attr (json_resource,
349 GNUNET_REST_JSONAPI_IDENTITY_KEY,
350 key_str);
351 json_decref (key_str);
395 GNUNET_free (keystring); 352 GNUNET_free (keystring);
396 if (NULL == egoname) 353 GNUNET_REST_jsonapi_response_resource_add (json_response, json_resource);
397 {
398 json_array_append (ego_arr, ego_json);
399 json_decref (ego_json);
400 }
401 else
402 break;
403 } 354 }
404 if (NULL == egoname)
405 json_object_set (root_json, "egos", ego_arr);
406 else
407 json_object_set (root_json, "ego", ego_json);
408 355
409 result_str = json_dumps (root_json, JSON_COMPACT); 356 GNUNET_REST_jsonapi_data_serialize (json_response, &result_str);
410 json_decref (ego_arr);
411 if (NULL != egoname)
412 json_decref (ego_json);
413 357
414 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result_str); 358 GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Result %s\n", result_str);
415 resp = create_json_response (result_str); 359 resp = GNUNET_REST_create_json_response (result_str);
416 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK); 360 handle->proc (handle->proc_cls, resp, MHD_HTTP_OK);
417 GNUNET_free (result_str); 361 GNUNET_free (result_str);
418 cleanup_handle (handle); 362 cleanup_handle (handle);
419
420} 363}
421 364
422static void 365static void
@@ -431,7 +374,7 @@ do_finished (void *cls, const char *emsg)
431 GNUNET_SCHEDULER_add_now (&do_error, handle); 374 GNUNET_SCHEDULER_add_now (&do_error, handle);
432 return; 375 return;
433 } 376 }
434 resp = create_json_response (NULL); 377 resp = GNUNET_REST_create_json_response (NULL);
435 handle->proc (handle->proc_cls, resp, MHD_HTTP_NO_CONTENT); 378 handle->proc (handle->proc_cls, resp, MHD_HTTP_NO_CONTENT);
436 cleanup_handle (handle); 379 cleanup_handle (handle);
437} 380}
@@ -448,7 +391,7 @@ set_finished (void *cls, const char *emsg)
448 GNUNET_SCHEDULER_add_now (&do_error, handle); 391 GNUNET_SCHEDULER_add_now (&do_error, handle);
449 return; 392 return;
450 } 393 }
451 resp = create_json_response (NULL); 394 resp = GNUNET_REST_create_json_response (NULL);
452 handle->proc (handle->proc_cls, resp, MHD_HTTP_NO_CONTENT); 395 handle->proc (handle->proc_cls, resp, MHD_HTTP_NO_CONTENT);
453 cleanup_handle (handle); 396 cleanup_handle (handle);
454} 397}
@@ -465,7 +408,7 @@ create_finished (void *cls, const char *emsg)
465 GNUNET_SCHEDULER_add_now (&do_error, handle); 408 GNUNET_SCHEDULER_add_now (&do_error, handle);
466 return; 409 return;
467 } 410 }
468 resp = create_json_response (NULL); 411 resp = GNUNET_REST_create_json_response (NULL);
469 handle->proc (handle->proc_cls, resp, MHD_HTTP_NO_CONTENT); 412 handle->proc (handle->proc_cls, resp, MHD_HTTP_NO_CONTENT);
470 cleanup_handle (handle); 413 cleanup_handle (handle);
471} 414}
@@ -503,7 +446,7 @@ ego_create_cont (struct RequestHandle *handle)
503 GNUNET_SCHEDULER_add_now (&do_error, handle); 446 GNUNET_SCHEDULER_add_now (&do_error, handle);
504 return; 447 return;
505 } 448 }
506 data_json = json_object_get (root_json, JSON_API_TYPE_DATA); 449 data_json = json_object_get (root_json, GNUNET_REST_JSONAPI_KEY_DATA);
507 if ((NULL == data_json) || !json_is_object (data_json)) 450 if ((NULL == data_json) || !json_is_object (data_json))
508 { 451 {
509 GNUNET_SCHEDULER_add_now (&do_error, handle); 452 GNUNET_SCHEDULER_add_now (&do_error, handle);
@@ -511,11 +454,11 @@ ego_create_cont (struct RequestHandle *handle)
511 } 454 }
512 type_json = json_object_get (data_json, "type"); 455 type_json = json_object_get (data_json, "type");
513 if (!json_is_string (type_json) || 456 if (!json_is_string (type_json) ||
514 (0 != strcmp (JSON_API_TYPE_EGO, json_string_value (type_json)))) 457 (0 != strcmp (GNUNET_REST_JSONAPI_IDENTITY_EGO, json_string_value (type_json))))
515 { 458 {
516 json_decref (data_json); 459 json_decref (data_json);
517 json_decref (root_json); 460 json_decref (root_json);
518 resp = create_json_response (NULL); 461 resp = GNUNET_REST_create_json_response (NULL);
519 handle->proc (handle->proc_cls, resp, MHD_HTTP_CONFLICT); 462 handle->proc (handle->proc_cls, resp, MHD_HTTP_CONFLICT);
520 cleanup_handle (handle); 463 cleanup_handle (handle);
521 return; 464 return;
@@ -540,7 +483,7 @@ ego_create_cont (struct RequestHandle *handle)
540 json_decref (egoname_json); 483 json_decref (egoname_json);
541 json_decref (data_json); 484 json_decref (data_json);
542 json_decref (root_json); 485 json_decref (root_json);
543 resp = create_json_response (NULL); 486 resp = GNUNET_REST_create_json_response (NULL);
544 handle->proc (handle->proc_cls, resp, MHD_HTTP_CONFLICT); 487 handle->proc (handle->proc_cls, resp, MHD_HTTP_CONFLICT);
545 cleanup_handle (handle); 488 cleanup_handle (handle);
546 return; 489 return;
@@ -591,7 +534,7 @@ subsys_set_cont (struct RequestHandle *handle)
591 } 534 }
592 if (GNUNET_NO == ego_exists) 535 if (GNUNET_NO == ego_exists)
593 { 536 {
594 resp = create_json_response (NULL); 537 resp = GNUNET_REST_create_json_response (NULL);
595 handle->proc (handle->proc_cls, resp, MHD_HTTP_NOT_FOUND); 538 handle->proc (handle->proc_cls, resp, MHD_HTTP_NOT_FOUND);
596 cleanup_handle (handle); 539 cleanup_handle (handle);
597 return; 540 return;
@@ -632,7 +575,7 @@ subsys_set_cont (struct RequestHandle *handle)
632 575
633 type_json = json_object_get (data_json, "type"); 576 type_json = json_object_get (data_json, "type");
634 if (!json_is_string (type_json) || 577 if (!json_is_string (type_json) ||
635 (0 != strcmp (JSON_API_TYPE_EGO, json_string_value (type_json)))) 578 (0 != strcmp (GNUNET_REST_JSONAPI_IDENTITY_EGO, json_string_value (type_json))))
636 { 579 {
637 json_decref (root_json); 580 json_decref (root_json);
638 json_decref (data_json); 581 json_decref (data_json);
@@ -687,7 +630,7 @@ ego_delete_cont (struct RequestHandle *handle)
687 } 630 }
688 if (GNUNET_NO == ego_exists) 631 if (GNUNET_NO == ego_exists)
689 { 632 {
690 resp = create_json_response (NULL); 633 resp = GNUNET_REST_create_json_response (NULL);
691 handle->proc (handle->proc_cls, resp, MHD_HTTP_NOT_FOUND); 634 handle->proc (handle->proc_cls, resp, MHD_HTTP_NOT_FOUND);
692 cleanup_handle (handle); 635 cleanup_handle (handle);
693 return; 636 return;
diff --git a/src/include/gnunet_rest_lib.h b/src/include/gnunet_rest_lib.h
new file mode 100644
index 000000000..19a0168e5
--- /dev/null
+++ b/src/include/gnunet_rest_lib.h
@@ -0,0 +1,156 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2010-2015 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19 */
20
21/**
22 * @file include/gnunet_rest_lib.h
23 * @brief API for helper library to parse/create REST
24 * @author Martin Schanzenbach
25 */
26#ifndef GNUNET_REST_LIB_H
27#define GNUNET_REST_LIB_H
28
29#include "gnunet_util_lib.h"
30#include "microhttpd.h"
31#include <jansson.h>
32
33#define GNUNET_REST_JSONAPI_KEY_DATA "data"
34
35#define GNUNET_REST_JSONAPI_KEY_ID "id"
36
37#define GNUNET_REST_JSONAPI_KEY_TYPE "type"
38
39/**
40 * Resource structs for JSON API
41 */
42struct JsonApiResource;
43
44/**
45 * Responses for JSON API
46 */
47struct JsonApiResponse;
48
49/**
50 * Create a JSON API resource
51 *
52 * @param type the JSON API resource type
53 * @param id the JSON API resource id
54 * @return a new JSON API resource or NULL on error.
55 */
56struct JsonApiResource*
57GNUNET_REST_jsonapi_resource_new (const char *type, const char *id);
58
59/**
60 * Delete a JSON API resource
61 *
62 * @param res the JSON resource
63 * @param result Pointer where the resource should be stored
64 */
65void
66GNUNET_REST_jsonapi_resource_delete (struct JsonApiResource *resource);
67
68/**
69 * Add a JSON API attribute
70 *
71 * @param res the JSON resource
72 * @param key the key for the attribute
73 * @param json the json_t attribute to add
74 * @return #GNUNET_OK if added successfully
75 * #GNUNET_SYSERR if not
76 */
77int
78GNUNET_REST_jsonapi_resource_add_attr (const struct JsonApiResource *resource,
79 const char* key,
80 json_t *json);
81
82/**
83 * Create a JSON API primary data
84 *
85 * @param type the JSON API resource type
86 * @param id the JSON API resource id
87 * @return a new JSON API resource or NULL on error.
88 */
89struct JsonApiResponse*
90GNUNET_REST_jsonapi_response_new ();
91
92/**
93 * Delete a JSON API primary data
94 *
95 * @param type the JSON API resource type
96 * @param id the JSON API resource id
97 * @return a new JSON API resource or NULL on error.
98 */
99void
100GNUNET_REST_jsonapi_response_delete (struct JsonApiResponse *resp);
101
102/**
103 * Add a JSON API resource to primary data
104 *
105 * @param data The JSON API data to add to
106 * @param res the JSON API resource to add
107 * @return the new number of resources
108 */
109void
110GNUNET_REST_jsonapi_response_resource_add (struct JsonApiResponse *resp,
111 struct JsonApiResource *res);
112
113/**
114 * Add a JSON API resource to primary data
115 *
116 * @param resp The JSON API data to add to
117 * @param res the JSON API resource to add
118 * @return the new number of resources
119 */
120void
121GNUNET_REST_jsonapi_data_resource_remove (struct JsonApiResponse *resp,
122 struct JsonApiResource *res);
123
124/**
125 * String serialze jsonapi primary data
126 *
127 * @param data the JSON API primary data
128 * @param result where to store the result
129 * @return GNUNET_SYSERR on error else GNUNET_OK
130 */
131int
132GNUNET_REST_jsonapi_data_serialize (const struct JsonApiResponse *resp,
133 char **result);
134
135/**
136 * Check if namespace is in URL.
137 *
138 * @param url URL to check
139 * @param namespace namespace to check against
140 * @retun GNUNET_YES if namespace matches
141 */
142int
143GNUNET_REST_namespace_match (const char *url, const char *namespace);
144
145/**
146 * Create JSON API MHD response
147 *
148 * @param data JSON result
149 * @retun MHD response
150 */
151 struct MHD_Response*
152GNUNET_REST_create_json_response (const char *data);
153
154
155
156#endif
diff --git a/src/include/gnunet_rest_plugin.h b/src/include/gnunet_rest_plugin.h
index 1d5a2db59..e085ccf32 100644
--- a/src/include/gnunet_rest_plugin.h
+++ b/src/include/gnunet_rest_plugin.h
@@ -37,6 +37,7 @@ extern "C"
37#endif 37#endif
38#endif 38#endif
39 39
40
40/** 41/**
41 * Iterator called on obtained result for a REST result. 42 * Iterator called on obtained result for a REST result.
42 * 43 *
diff --git a/src/rest/Makefile.am b/src/rest/Makefile.am
index 00021cce2..8ea87fc6a 100644
--- a/src/rest/Makefile.am
+++ b/src/rest/Makefile.am
@@ -20,6 +20,9 @@ if USE_COVERAGE
20 XLIBS = -lgcov 20 XLIBS = -lgcov
21endif 21endif
22 22
23lib_LTLIBRARIES = \
24 libgnunetrest.la
25
23libexec_PROGRAMS = \ 26libexec_PROGRAMS = \
24 gnunet-rest-server 27 gnunet-rest-server
25 28
@@ -29,3 +32,12 @@ gnunet_rest_server_SOURCES = \
29gnunet_rest_server_LDADD = \ 32gnunet_rest_server_LDADD = \
30 $(top_builddir)/src/util/libgnunetutil.la \ 33 $(top_builddir)/src/util/libgnunetutil.la \
31 $(GN_LIBINTL) -lmicrohttpd 34 $(GN_LIBINTL) -lmicrohttpd
35
36libgnunetrest_la_SOURCES = \
37 rest.c
38libgnunetrest_la_LIBADD = \
39 $(top_builddir)/src/util/libgnunetutil.la $(XLIB) \
40 $(GN_LIBINTL) -lmicrohttpd -ljansson
41libgnunetrest_la_LDFLAGS = \
42 $(GN_LIB_LDFLAGS) \
43 -version-info 0:0:0
diff --git a/src/rest/rest.c b/src/rest/rest.c
new file mode 100644
index 000000000..0b843ec61
--- /dev/null
+++ b/src/rest/rest.c
@@ -0,0 +1,299 @@
1/*
2 This file is part of GNUnet
3 Copyright (C) 2010-2015 Christian Grothoff (and other contributing authors)
4
5 GNUnet is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published
7 by the Free Software Foundation; either version 3, or (at your
8 option) any later version.
9
10 GNUnet is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with GNUnet; see the file COPYING. If not, write to the
17 Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 Boston, MA 02111-1307, USA.
19 */
20
21/**
22 * @file rest/rest.c
23 * @brief helper library to create JSON REST Objects and handle REST
24 * responses/requests.
25 * @author Martin Schanzenbach
26 */
27#include "platform.h"
28#include "gnunet_util_lib.h"
29#include "gnunet_rest_lib.h"
30#include "microhttpd.h"
31#include <jansson.h>
32
33
34struct JsonApiResource
35{
36 /**
37 * DLL
38 */
39 struct JsonApiResource *next;
40
41 /**
42 * DLL
43 */
44 struct JsonApiResource *prev;
45
46 /**
47 * Resource content
48 */
49 json_t *res_obj;
50};
51
52
53struct JsonApiResponse
54{
55 /**
56 * DLL Resource
57 */
58 struct JsonApiResource *res_list_head;
59
60 /**
61 * DLL Resource
62 */
63 struct JsonApiResource *res_list_tail;
64
65 /**
66 * num resources
67 */
68 int res_count;
69};
70
71/**
72 * JSON API
73 */
74
75/**
76 * Create a JSON API resource
77 *
78 * @param type the JSON API resource type
79 * @param id the JSON API resource id
80 * @return a new JSON API resource or NULL on error.
81 */
82struct JsonApiResource*
83GNUNET_REST_jsonapi_resource_new (const char *type, const char *id)
84{
85 struct JsonApiResource *res;
86
87 if ( (NULL == type) || (0 == strlen (type)) )
88 return NULL;
89 if ( (NULL == id) || (0 == strlen (id)) )
90 return NULL;
91
92 res = GNUNET_new (struct JsonApiResource);
93
94 res->res_obj = json_object ();
95
96 json_object_set_new (res->res_obj, GNUNET_REST_JSONAPI_KEY_ID, json_string (id));
97 json_object_set_new (res->res_obj, GNUNET_REST_JSONAPI_KEY_TYPE, json_string (type));
98
99 return res;
100}
101
102/**
103 * Delete a JSON API resource
104 *
105 * @param res the JSON resource
106 * @param result Pointer where the resource should be stored
107 */
108void
109GNUNET_REST_jsonapi_resource_delete (struct JsonApiResource *resource)
110{
111 json_decref (resource->res_obj);
112 GNUNET_free (resource);
113}
114
115/**
116 * Add a JSON API attribute
117 *
118 * @param res the JSON resource
119 * @param key the key for the attribute
120 * @param json the json_t attribute to add
121 * @return #GNUNET_OK if added successfully
122 * #GNUNET_SYSERR if not
123 */
124int
125GNUNET_REST_jsonapi_resource_add_attr (const struct JsonApiResource *resource,
126 const char* key,
127 json_t *json)
128{
129 if ( (NULL == resource) ||
130 (NULL == key) ||
131 (NULL == json) )
132 return GNUNET_SYSERR;
133 json_object_set (resource->res_obj, key, json);
134 return GNUNET_OK;
135}
136
137
138
139
140/**
141 * Create a JSON API primary data
142 *
143 * @param type the JSON API resource type
144 * @param id the JSON API resource id
145 * @return a new JSON API resource or NULL on error.
146 */
147struct JsonApiResponse*
148GNUNET_REST_jsonapi_response_new ()
149{
150 struct JsonApiResponse *result;
151
152 result = GNUNET_new (struct JsonApiResponse);
153 result->res_count = 0;
154 return result;
155}
156
157/**
158 * Delete a JSON API primary data
159 *
160 * @param type the JSON API resource type
161 * @param id the JSON API resource id
162 * @return a new JSON API resource or NULL on error.
163 */
164void
165GNUNET_REST_jsonapi_response_delete (struct JsonApiResponse *resp)
166{
167 struct JsonApiResource *res;
168
169 for (res = resp->res_list_head;
170 res != NULL;
171 res = res->next)
172 GNUNET_REST_jsonapi_resource_delete (res);
173 GNUNET_free (resp);
174}
175
176/**
177 * Add a JSON API resource to primary data
178 *
179 * @param data The JSON API data to add to
180 * @param res the JSON API resource to add
181 * @return the new number of resources
182 */
183void
184GNUNET_REST_jsonapi_response_resource_add (struct JsonApiResponse *resp,
185 struct JsonApiResource *res)
186{
187 GNUNET_CONTAINER_DLL_insert (resp->res_list_head,
188 resp->res_list_tail,
189 res);
190
191 resp->res_count++;
192}
193
194/**
195 * Add a JSON API resource to primary data
196 *
197 * @param data The JSON API data to add to
198 * @param res the JSON API resource to add
199 * @return the new number of resources
200 */
201void
202GNUNET_REST_jsonapi_data_resource_remove (struct JsonApiResponse *resp,
203 struct JsonApiResource *res)
204{
205 GNUNET_CONTAINER_DLL_remove (resp->res_list_head,
206 resp->res_list_tail,
207 res);
208 resp->res_count--;
209}
210
211/**
212 * String serialze jsonapi primary data
213 *
214 * @param data the JSON API primary data
215 * @param result where to store the result
216 * @return GNUNET_SYSERR on error else GNUNET_OK
217 */
218int
219GNUNET_REST_jsonapi_data_serialize (const struct JsonApiResponse *resp,
220 char **result)
221{
222 struct JsonApiResource *res;
223 json_t *root_json;
224 json_t *res_arr;
225
226 if ( (NULL == resp) ||
227 (0 == resp->res_count) )
228 return GNUNET_SYSERR;
229
230 root_json = json_object ();
231
232 if (1 == resp->res_count)
233 {
234 json_object_set (root_json, GNUNET_REST_JSONAPI_KEY_DATA, resp->res_list_head->res_obj);
235 }
236 else
237 {
238 res_arr = json_array ();
239 for (res = resp->res_list_head;
240 res != NULL;
241 res = res->next)
242 {
243 json_array_append (res_arr, res->res_obj);
244 }
245 json_object_set (root_json, GNUNET_REST_JSONAPI_KEY_DATA, res_arr);
246 }
247 *result = json_dumps (root_json, JSON_COMPACT);
248 return GNUNET_OK;
249}
250
251/**
252 * REST Utilities
253 */
254
255/**
256 * Check if namespace is in URL.
257 *
258 * @param url URL to check
259 * @param namespace namespace to check against
260 * @retun GNUNET_YES if namespace matches
261 */
262int
263GNUNET_REST_namespace_match (const char *url, const char *namespace)
264{
265 if (0 != strncmp (namespace, url, strlen (namespace)))
266 return GNUNET_NO;
267
268 if ((strlen (namespace) < strlen (url)) &&
269 (url[strlen (namespace)] != '/'))
270 return GNUNET_NO;
271
272 return GNUNET_YES;
273}
274
275/**
276 * Create JSON API MHD response
277 *
278 * @param data JSON result
279 * @retun MHD response
280 */
281 struct MHD_Response*
282GNUNET_REST_create_json_response (const char *data)
283{
284 struct MHD_Response *resp;
285 size_t len;
286
287 if (NULL == data)
288 len = 0;
289 else
290 len = strlen (data);
291 resp = MHD_create_response_from_buffer (len,
292 (void*)data,
293 MHD_RESPMEM_MUST_COPY);
294 MHD_add_response_header (resp,MHD_HTTP_HEADER_CONTENT_TYPE,"application/json");
295 return resp;
296
297}
298
299/* end of rest.c */