diff options
author | Martin Schanzenbach <mschanzenbach@posteo.de> | 2015-03-25 15:58:38 +0000 |
---|---|---|
committer | Martin Schanzenbach <mschanzenbach@posteo.de> | 2015-03-25 15:58:38 +0000 |
commit | 08cd39e74d35cec73f54de9826961a97d8a8ea0d (patch) | |
tree | f85511b479dc9480427dffaaaa5425ebc221c87c /src/rest | |
parent | 00f87691363acaf94f533793654e610e46bf4e1d (diff) | |
download | gnunet-08cd39e74d35cec73f54de9826961a97d8a8ea0d.tar.gz gnunet-08cd39e74d35cec73f54de9826961a97d8a8ea0d.zip |
-start a lib for REST and json:api
Diffstat (limited to 'src/rest')
-rw-r--r-- | src/rest/Makefile.am | 12 | ||||
-rw-r--r-- | src/rest/rest.c | 299 |
2 files changed, 311 insertions, 0 deletions
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 |
21 | endif | 21 | endif |
22 | 22 | ||
23 | lib_LTLIBRARIES = \ | ||
24 | libgnunetrest.la | ||
25 | |||
23 | libexec_PROGRAMS = \ | 26 | libexec_PROGRAMS = \ |
24 | gnunet-rest-server | 27 | gnunet-rest-server |
25 | 28 | ||
@@ -29,3 +32,12 @@ gnunet_rest_server_SOURCES = \ | |||
29 | gnunet_rest_server_LDADD = \ | 32 | gnunet_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 | |||
36 | libgnunetrest_la_SOURCES = \ | ||
37 | rest.c | ||
38 | libgnunetrest_la_LIBADD = \ | ||
39 | $(top_builddir)/src/util/libgnunetutil.la $(XLIB) \ | ||
40 | $(GN_LIBINTL) -lmicrohttpd -ljansson | ||
41 | libgnunetrest_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 | |||
34 | struct 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 | |||
53 | struct 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 | */ | ||
82 | struct JsonApiResource* | ||
83 | GNUNET_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 | */ | ||
108 | void | ||
109 | GNUNET_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 | */ | ||
124 | int | ||
125 | GNUNET_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 | */ | ||
147 | struct JsonApiResponse* | ||
148 | GNUNET_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 | */ | ||
164 | void | ||
165 | GNUNET_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 | */ | ||
183 | void | ||
184 | GNUNET_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 | */ | ||
201 | void | ||
202 | GNUNET_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 | */ | ||
218 | int | ||
219 | GNUNET_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 | */ | ||
262 | int | ||
263 | GNUNET_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* | ||
282 | GNUNET_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 */ | ||