]>
Commit | Line | Data |
---|---|---|
3a7c594c AS |
1 | /* |
2 | * Copyright (C) 2017 Andreas Steffen | |
3 | * HSR Hochschule fuer Technik Rapperswil | |
4 | * | |
5 | * This program is free software; you can redistribute it and/or modify it | |
6 | * under the terms of the GNU General Public License as published by the | |
7 | * Free Software Foundation; either version 2 of the License, or (at your | |
8 | * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. | |
9 | * | |
10 | * This program is distributed in the hope that it will be useful, but | |
11 | * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY | |
12 | * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
13 | * for more details. | |
14 | */ | |
15 | ||
8ba6bf51 AS |
16 | #ifdef USE_JSON |
17 | ||
3a7c594c AS |
18 | #define _GNU_SOURCE |
19 | #include <stdio.h> | |
20 | ||
8ba6bf51 | 21 | #include "rest.h" |
3a7c594c | 22 | |
8ba6bf51 | 23 | typedef struct private_rest_t private_rest_t; |
3a7c594c AS |
24 | |
25 | /** | |
8ba6bf51 | 26 | * Private data of an rest_t object. |
3a7c594c | 27 | */ |
8ba6bf51 | 28 | struct private_rest_t { |
3a7c594c AS |
29 | |
30 | /** | |
8ba6bf51 | 31 | * Public members of rest_t |
3a7c594c | 32 | */ |
8ba6bf51 | 33 | rest_t public; |
3a7c594c AS |
34 | |
35 | /** | |
36 | * URI of REST API | |
37 | */ | |
38 | char *uri; | |
39 | ||
40 | /** | |
41 | * Timeout of REST API connection | |
42 | */ | |
43 | u_int timeout; | |
44 | ||
45 | }; | |
46 | ||
8ba6bf51 AS |
47 | METHOD(rest_t, get, status_t, |
48 | private_rest_t *this, char *command, json_object **jresponse) | |
49 | { | |
50 | struct json_tokener *tokener; | |
51 | chunk_t response = chunk_empty; | |
52 | status_t status; | |
53 | char *uri; | |
54 | ||
55 | if (asprintf(&uri, "%s%s",this->uri, command) < 0) | |
56 | { | |
57 | return FAILED; | |
58 | } | |
59 | ||
60 | status = lib->fetcher->fetch(lib->fetcher, uri, &response, | |
61 | FETCH_TIMEOUT, this->timeout, | |
62 | FETCH_END); | |
63 | free(uri); | |
64 | ||
65 | if (status == SUCCESS && jresponse) | |
66 | { | |
67 | /* Parse HTTP response into a JSON object */ | |
68 | tokener = json_tokener_new(); | |
69 | *jresponse = json_tokener_parse_ex(tokener, response.ptr, response.len); | |
70 | json_tokener_free(tokener); | |
71 | } | |
72 | free(response.ptr); | |
73 | ||
74 | return status; | |
75 | } | |
76 | ||
77 | #define HTTP_STATUS_CODE_NOT_FOUND 404 | |
3a7c594c AS |
78 | #define HTTP_STATUS_CODE_PRECONDITION_FAILED 412 |
79 | ||
8ba6bf51 AS |
80 | METHOD(rest_t, post, status_t, |
81 | private_rest_t *this, char *command, json_object *jrequest, | |
3a7c594c AS |
82 | json_object **jresponse) |
83 | { | |
84 | struct json_tokener *tokener; | |
85 | chunk_t data, response = chunk_empty; | |
86 | status_t status; | |
87 | char *uri; | |
88 | int code; | |
89 | ||
90 | if (asprintf(&uri, "%s%s",this->uri, command) < 0) | |
91 | { | |
92 | return FAILED; | |
93 | } | |
94 | data = chunk_from_str((char*)json_object_to_json_string(jrequest)); | |
95 | ||
96 | status = lib->fetcher->fetch(lib->fetcher, uri, &response, | |
97 | FETCH_TIMEOUT, this->timeout, | |
98 | FETCH_REQUEST_DATA, data, | |
99 | FETCH_REQUEST_TYPE, "application/json; charset=utf-8", | |
100 | FETCH_REQUEST_HEADER, "Accept: application/json", | |
101 | FETCH_REQUEST_HEADER, "Expect:", | |
102 | FETCH_RESPONSE_CODE, &code, | |
103 | FETCH_END); | |
104 | free(uri); | |
105 | ||
106 | if (status != SUCCESS) | |
107 | { | |
8ba6bf51 | 108 | switch (code) |
3a7c594c | 109 | { |
8ba6bf51 AS |
110 | case HTTP_STATUS_CODE_NOT_FOUND: |
111 | status = NOT_FOUND; | |
112 | break; | |
113 | case HTTP_STATUS_CODE_PRECONDITION_FAILED: | |
114 | if (!response.ptr) | |
115 | { | |
116 | return FAILED; | |
117 | } | |
118 | if (jresponse) | |
119 | { | |
120 | /* Parse HTTP response into a JSON object */ | |
121 | tokener = json_tokener_new(); | |
122 | *jresponse = json_tokener_parse_ex(tokener, response.ptr, | |
123 | response.len); | |
124 | json_tokener_free(tokener); | |
125 | } | |
126 | status = NEED_MORE; | |
127 | break; | |
128 | default: | |
129 | DBG2(DBG_IMV, "REST http request failed with status code: %d", | |
130 | code); | |
131 | status = FAILED; | |
132 | break; | |
3a7c594c AS |
133 | } |
134 | } | |
135 | free(response.ptr); | |
136 | ||
137 | return status; | |
138 | } | |
139 | ||
8ba6bf51 AS |
140 | METHOD(rest_t, destroy, void, |
141 | private_rest_t *this) | |
3a7c594c AS |
142 | { |
143 | free(this->uri); | |
144 | free(this); | |
145 | } | |
146 | ||
147 | /** | |
148 | * Described in header. | |
149 | */ | |
8ba6bf51 | 150 | rest_t *rest_create(char *uri, u_int timeout) |
3a7c594c | 151 | { |
8ba6bf51 | 152 | private_rest_t *this; |
3a7c594c AS |
153 | |
154 | INIT(this, | |
155 | .public = { | |
8ba6bf51 | 156 | .get = _get, |
3a7c594c AS |
157 | .post = _post, |
158 | .destroy = _destroy, | |
159 | }, | |
160 | .uri = strdup(uri), | |
161 | .timeout = timeout, | |
162 | ); | |
163 | ||
164 | return &this->public; | |
165 | } | |
166 | ||
8ba6bf51 | 167 | #endif /* USE_JSON */ |