Mercurial > hg > orthanc
annotate Core/RestApi/RestApi.cpp @ 898:7000fc86fe62 plugins
improved plugin api
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Wed, 18 Jun 2014 09:18:28 +0200 |
parents | 7e8cde5905fd |
children | 7d88f3f4a3b3 |
rev | line source |
---|---|
209 | 1 /** |
2 * Orthanc - A Lightweight, RESTful DICOM Store | |
689 | 3 * Copyright (C) 2012-2014 Medical Physics Department, CHU of Liege, |
209 | 4 * Belgium |
5 * | |
6 * This program is free software: you can redistribute it and/or | |
7 * modify it under the terms of the GNU General Public License as | |
8 * published by the Free Software Foundation, either version 3 of the | |
9 * License, or (at your option) any later version. | |
10 * | |
11 * In addition, as a special exception, the copyright holders of this | |
12 * program give permission to link the code of its release with the | |
13 * OpenSSL project's "OpenSSL" library (or with modified versions of it | |
14 * that use the same license as the "OpenSSL" library), and distribute | |
15 * the linked executables. You must obey the GNU General Public License | |
16 * in all respects for all of the code used other than "OpenSSL". If you | |
17 * modify file(s) with this exception, you may extend this exception to | |
18 * your version of the file(s), but you are not obligated to do so. If | |
19 * you do not wish to do so, delete this exception statement from your | |
20 * version. If you delete this exception statement from all source files | |
21 * in the program, then also delete it here. | |
22 * | |
23 * This program is distributed in the hope that it will be useful, but | |
24 * WITHOUT ANY WARRANTY; without even the implied warranty of | |
25 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
26 * General Public License for more details. | |
27 * | |
28 * You should have received a copy of the GNU General Public License | |
29 * along with this program. If not, see <http://www.gnu.org/licenses/>. | |
30 **/ | |
31 | |
32 | |
824
a811bdf8b8eb
precompiled headers
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
689
diff
changeset
|
33 #include "../PrecompiledHeaders.h" |
209 | 34 #include "RestApi.h" |
35 | |
249 | 36 #include <stdlib.h> // To define "_exit()" under Windows |
210
96b7918a6a18
start of the refactoring of the Orthanc REST API
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
209
diff
changeset
|
37 #include <glog/logging.h> |
96b7918a6a18
start of the refactoring of the Orthanc REST API
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
209
diff
changeset
|
38 |
209 | 39 namespace Orthanc |
40 { | |
331
5a96dac27959
base class for rest calls made public
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
304
diff
changeset
|
41 bool RestApi::Call::ParseJsonRequestInternal(Json::Value& result, |
5a96dac27959
base class for rest calls made public
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
304
diff
changeset
|
42 const char* request) |
304 | 43 { |
44 result.clear(); | |
45 Json::Reader reader; | |
46 return reader.parse(request, result); | |
47 } | |
48 | |
49 | |
50 bool RestApi::GetCall::ParseJsonRequest(Json::Value& result) const | |
51 { | |
52 result.clear(); | |
53 | |
54 for (HttpHandler::Arguments::const_iterator | |
659 | 55 it = getArguments_.begin(); it != getArguments_.end(); ++it) |
304 | 56 { |
335 | 57 result[it->first] = it->second; |
304 | 58 } |
59 | |
60 return true; | |
61 } | |
62 | |
63 | |
209 | 64 bool RestApi::IsGetAccepted(const UriComponents& uri) |
65 { | |
66 for (GetHandlers::const_iterator it = getHandlers_.begin(); | |
656 | 67 it != getHandlers_.end(); ++it) |
209 | 68 { |
69 if (it->first->Match(uri)) | |
70 { | |
71 return true; | |
72 } | |
73 } | |
74 | |
75 return false; | |
76 } | |
77 | |
78 bool RestApi::IsPutAccepted(const UriComponents& uri) | |
79 { | |
80 for (PutHandlers::const_iterator it = putHandlers_.begin(); | |
656 | 81 it != putHandlers_.end(); ++it) |
209 | 82 { |
83 if (it->first->Match(uri)) | |
84 { | |
85 return true; | |
86 } | |
87 } | |
88 | |
89 return false; | |
90 } | |
91 | |
92 bool RestApi::IsPostAccepted(const UriComponents& uri) | |
93 { | |
94 for (PostHandlers::const_iterator it = postHandlers_.begin(); | |
656 | 95 it != postHandlers_.end(); ++it) |
209 | 96 { |
97 if (it->first->Match(uri)) | |
98 { | |
99 return true; | |
100 } | |
101 } | |
102 | |
103 return false; | |
104 } | |
105 | |
106 bool RestApi::IsDeleteAccepted(const UriComponents& uri) | |
107 { | |
108 for (DeleteHandlers::const_iterator it = deleteHandlers_.begin(); | |
656 | 109 it != deleteHandlers_.end(); ++it) |
209 | 110 { |
111 if (it->first->Match(uri)) | |
112 { | |
113 return true; | |
114 } | |
115 } | |
116 | |
117 return false; | |
118 } | |
119 | |
120 static void AddMethod(std::string& target, | |
121 const std::string& method) | |
122 { | |
123 if (target.size() > 0) | |
124 target += "," + method; | |
125 else | |
126 target = method; | |
127 } | |
128 | |
129 std::string RestApi::GetAcceptedMethods(const UriComponents& uri) | |
130 { | |
131 std::string s; | |
132 | |
133 if (IsGetAccepted(uri)) | |
134 AddMethod(s, "GET"); | |
135 | |
136 if (IsPutAccepted(uri)) | |
137 AddMethod(s, "PUT"); | |
138 | |
139 if (IsPostAccepted(uri)) | |
140 AddMethod(s, "POST"); | |
141 | |
142 if (IsDeleteAccepted(uri)) | |
143 AddMethod(s, "DELETE"); | |
144 | |
145 return s; | |
146 } | |
147 | |
148 RestApi::~RestApi() | |
149 { | |
150 for (GetHandlers::iterator it = getHandlers_.begin(); | |
656 | 151 it != getHandlers_.end(); ++it) |
209 | 152 { |
153 delete it->first; | |
154 } | |
155 | |
156 for (PutHandlers::iterator it = putHandlers_.begin(); | |
656 | 157 it != putHandlers_.end(); ++it) |
209 | 158 { |
159 delete it->first; | |
160 } | |
161 | |
162 for (PostHandlers::iterator it = postHandlers_.begin(); | |
656 | 163 it != postHandlers_.end(); ++it) |
209 | 164 { |
165 delete it->first; | |
166 } | |
167 | |
168 for (DeleteHandlers::iterator it = deleteHandlers_.begin(); | |
656 | 169 it != deleteHandlers_.end(); ++it) |
209 | 170 { |
171 delete it->first; | |
172 } | |
173 } | |
174 | |
175 bool RestApi::IsServedUri(const UriComponents& uri) | |
176 { | |
177 return (IsGetAccepted(uri) || | |
178 IsPutAccepted(uri) || | |
179 IsPostAccepted(uri) || | |
180 IsDeleteAccepted(uri)); | |
181 } | |
182 | |
895
7e8cde5905fd
allow superposition of REST handlers
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
824
diff
changeset
|
183 bool RestApi::Handle(HttpOutput& output, |
473
c9a5d72f8481
changing the namespace of HTTP enumerations
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
416
diff
changeset
|
184 HttpMethod method, |
209 | 185 const UriComponents& uri, |
186 const Arguments& headers, | |
187 const Arguments& getArguments, | |
188 const std::string& postData) | |
189 { | |
190 bool ok = false; | |
191 RestApiOutput restOutput(output); | |
192 RestApiPath::Components components; | |
193 UriComponents trailing; | |
210
96b7918a6a18
start of the refactoring of the Orthanc REST API
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
209
diff
changeset
|
194 |
473
c9a5d72f8481
changing the namespace of HTTP enumerations
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
416
diff
changeset
|
195 if (method == HttpMethod_Get) |
209 | 196 { |
197 for (GetHandlers::const_iterator it = getHandlers_.begin(); | |
656 | 198 it != getHandlers_.end(); ++it) |
209 | 199 { |
200 if (it->first->Match(components, trailing, uri)) | |
201 { | |
416 | 202 //LOG(INFO) << "REST GET call on: " << Toolbox::FlattenUri(uri); |
209 | 203 ok = true; |
659 | 204 GetCall call(restOutput, *this, headers, components, trailing, uri, getArguments); |
209 | 205 it->second(call); |
206 } | |
207 } | |
208 } | |
473
c9a5d72f8481
changing the namespace of HTTP enumerations
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
416
diff
changeset
|
209 else if (method == HttpMethod_Put) |
209 | 210 { |
211 for (PutHandlers::const_iterator it = putHandlers_.begin(); | |
656 | 212 it != putHandlers_.end(); ++it) |
209 | 213 { |
214 if (it->first->Match(components, trailing, uri)) | |
215 { | |
416 | 216 //LOG(INFO) << "REST PUT call on: " << Toolbox::FlattenUri(uri); |
209 | 217 ok = true; |
659 | 218 PutCall call(restOutput, *this, headers, components, trailing, uri, postData); |
209 | 219 it->second(call); |
220 } | |
221 } | |
222 } | |
473
c9a5d72f8481
changing the namespace of HTTP enumerations
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
416
diff
changeset
|
223 else if (method == HttpMethod_Post) |
209 | 224 { |
225 for (PostHandlers::const_iterator it = postHandlers_.begin(); | |
656 | 226 it != postHandlers_.end(); ++it) |
209 | 227 { |
228 if (it->first->Match(components, trailing, uri)) | |
229 { | |
416 | 230 //LOG(INFO) << "REST POST call on: " << Toolbox::FlattenUri(uri); |
209 | 231 ok = true; |
659 | 232 PostCall call(restOutput, *this, headers, components, trailing, uri, postData); |
209 | 233 it->second(call); |
234 } | |
235 } | |
236 } | |
473
c9a5d72f8481
changing the namespace of HTTP enumerations
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
416
diff
changeset
|
237 else if (method == HttpMethod_Delete) |
209 | 238 { |
239 for (DeleteHandlers::const_iterator it = deleteHandlers_.begin(); | |
656 | 240 it != deleteHandlers_.end(); ++it) |
209 | 241 { |
242 if (it->first->Match(components, trailing, uri)) | |
243 { | |
416 | 244 //LOG(INFO) << "REST DELETE call on: " << Toolbox::FlattenUri(uri); |
209 | 245 ok = true; |
659 | 246 DeleteCall call(restOutput, *this, headers, components, trailing, uri); |
209 | 247 it->second(call); |
248 } | |
249 } | |
250 } | |
251 | |
252 if (!ok) | |
253 { | |
477 | 254 LOG(INFO) << "REST method " << EnumerationToString(method) |
416 | 255 << " not allowed on: " << Toolbox::FlattenUri(uri); |
209 | 256 output.SendMethodNotAllowedError(GetAcceptedMethods(uri)); |
257 } | |
895
7e8cde5905fd
allow superposition of REST handlers
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
824
diff
changeset
|
258 |
7e8cde5905fd
allow superposition of REST handlers
Sebastien Jodogne <s.jodogne@gmail.com>
parents:
824
diff
changeset
|
259 return true; |
209 | 260 } |
261 | |
262 void RestApi::Register(const std::string& path, | |
263 GetHandler handler) | |
264 { | |
265 getHandlers_.push_back(std::make_pair(new RestApiPath(path), handler)); | |
266 } | |
267 | |
268 void RestApi::Register(const std::string& path, | |
269 PutHandler handler) | |
270 { | |
271 putHandlers_.push_back(std::make_pair(new RestApiPath(path), handler)); | |
272 } | |
273 | |
274 void RestApi::Register(const std::string& path, | |
275 PostHandler handler) | |
276 { | |
277 postHandlers_.push_back(std::make_pair(new RestApiPath(path), handler)); | |
278 } | |
279 | |
280 void RestApi::Register(const std::string& path, | |
281 DeleteHandler handler) | |
282 { | |
283 deleteHandlers_.push_back(std::make_pair(new RestApiPath(path), handler)); | |
284 } | |
285 } |