Mercurial > hg > orthanc
comparison Core/RestApi/RestApi.cpp @ 980:f1ff2a2f06cd plugins
use RestApiHierarchy inside RestApi
author | Sebastien Jodogne <s.jodogne@gmail.com> |
---|---|
date | Mon, 30 Jun 2014 17:41:40 +0200 |
parents | 2a9e08136860 |
children | 8d1845feb277 |
comparison
equal
deleted
inserted
replaced
979:624f44047238 | 980:f1ff2a2f06cd |
---|---|
34 #include "RestApi.h" | 34 #include "RestApi.h" |
35 | 35 |
36 #include <stdlib.h> // To define "_exit()" under Windows | 36 #include <stdlib.h> // To define "_exit()" under Windows |
37 #include <glog/logging.h> | 37 #include <glog/logging.h> |
38 | 38 |
39 #include <stdio.h> | |
40 | |
39 namespace Orthanc | 41 namespace Orthanc |
40 { | 42 { |
41 bool RestApi::IsGetAccepted(const UriComponents& uri) | 43 namespace |
42 { | 44 { |
43 for (GetHandlers::const_iterator it = getHandlers_.begin(); | 45 // Anonymous namespace to avoid clashes between compilation modules |
44 it != getHandlers_.end(); ++it) | 46 class HttpHandlerVisitor : public RestApiHierarchy::IVisitor |
45 { | 47 { |
46 if (it->first->Match(uri)) | 48 private: |
49 RestApi& api_; | |
50 HttpOutput& output_; | |
51 HttpMethod method_; | |
52 const HttpHandler::Arguments& headers_; | |
53 const HttpHandler::Arguments& getArguments_; | |
54 const std::string& postData_; | |
55 | |
56 public: | |
57 HttpHandlerVisitor(RestApi& api, | |
58 HttpOutput& output, | |
59 HttpMethod method, | |
60 const HttpHandler::Arguments& headers, | |
61 const HttpHandler::Arguments& getArguments, | |
62 const std::string& postData) : | |
63 api_(api), | |
64 output_(output), | |
65 method_(method), | |
66 headers_(headers), | |
67 getArguments_(getArguments), | |
68 postData_(postData) | |
47 { | 69 { |
48 return true; | |
49 } | 70 } |
50 } | 71 |
51 | 72 virtual bool Visit(const RestApiHierarchy::Resource& resource, |
52 return false; | 73 const UriComponents& uri, |
53 } | 74 const HttpHandler::Arguments& components, |
54 | 75 const UriComponents& trailing) |
55 bool RestApi::IsPutAccepted(const UriComponents& uri) | |
56 { | |
57 for (PutHandlers::const_iterator it = putHandlers_.begin(); | |
58 it != putHandlers_.end(); ++it) | |
59 { | |
60 if (it->first->Match(uri)) | |
61 { | 76 { |
62 return true; | 77 if (resource.HasHandler(method_)) |
78 { | |
79 RestApiOutput output(output_); | |
80 | |
81 switch (method_) | |
82 { | |
83 case HttpMethod_Get: | |
84 { | |
85 RestApiGetCall call(output, api_, headers_, components, trailing, uri, getArguments_); | |
86 resource.Handle(call); | |
87 return true; | |
88 } | |
89 | |
90 case HttpMethod_Post: | |
91 { | |
92 RestApiPostCall call(output, api_, headers_, components, trailing, uri, postData_); | |
93 resource.Handle(call); | |
94 return true; | |
95 } | |
96 | |
97 case HttpMethod_Delete: | |
98 { | |
99 RestApiDeleteCall call(output, api_, headers_, components, trailing, uri); | |
100 resource.Handle(call); | |
101 return true; | |
102 } | |
103 | |
104 case HttpMethod_Put: | |
105 { | |
106 RestApiPutCall call(output, api_, headers_, components, trailing, uri, postData_); | |
107 resource.Handle(call); | |
108 return true; | |
109 } | |
110 | |
111 default: | |
112 return false; | |
113 } | |
114 } | |
115 | |
116 return false; | |
63 } | 117 } |
64 } | 118 }; |
65 | 119 } |
66 return false; | 120 |
67 } | 121 |
68 | |
69 bool RestApi::IsPostAccepted(const UriComponents& uri) | |
70 { | |
71 for (PostHandlers::const_iterator it = postHandlers_.begin(); | |
72 it != postHandlers_.end(); ++it) | |
73 { | |
74 if (it->first->Match(uri)) | |
75 { | |
76 return true; | |
77 } | |
78 } | |
79 | |
80 return false; | |
81 } | |
82 | |
83 bool RestApi::IsDeleteAccepted(const UriComponents& uri) | |
84 { | |
85 for (DeleteHandlers::const_iterator it = deleteHandlers_.begin(); | |
86 it != deleteHandlers_.end(); ++it) | |
87 { | |
88 if (it->first->Match(uri)) | |
89 { | |
90 return true; | |
91 } | |
92 } | |
93 | |
94 return false; | |
95 } | |
96 | 122 |
97 static void AddMethod(std::string& target, | 123 static void AddMethod(std::string& target, |
98 const std::string& method) | 124 const std::string& method) |
99 { | 125 { |
100 if (target.size() > 0) | 126 if (target.size() > 0) |
101 target += "," + method; | 127 target += "," + method; |
102 else | 128 else |
103 target = method; | 129 target = method; |
104 } | 130 } |
105 | 131 |
106 std::string RestApi::GetAcceptedMethods(const UriComponents& uri) | 132 static std::string MethodsToString(const std::set<HttpMethod>& methods) |
107 { | 133 { |
108 std::string s; | 134 std::string s; |
109 | 135 |
110 if (IsGetAccepted(uri)) | 136 if (methods.find(HttpMethod_Get) != methods.end()) |
137 { | |
111 AddMethod(s, "GET"); | 138 AddMethod(s, "GET"); |
112 | 139 } |
113 if (IsPutAccepted(uri)) | 140 |
141 if (methods.find(HttpMethod_Post) != methods.end()) | |
142 { | |
143 AddMethod(s, "POST"); | |
144 } | |
145 | |
146 if (methods.find(HttpMethod_Put) != methods.end()) | |
147 { | |
114 AddMethod(s, "PUT"); | 148 AddMethod(s, "PUT"); |
115 | 149 } |
116 if (IsPostAccepted(uri)) | 150 |
117 AddMethod(s, "POST"); | 151 if (methods.find(HttpMethod_Delete) != methods.end()) |
118 | 152 { |
119 if (IsDeleteAccepted(uri)) | |
120 AddMethod(s, "DELETE"); | 153 AddMethod(s, "DELETE"); |
154 } | |
121 | 155 |
122 return s; | 156 return s; |
123 } | 157 } |
124 | 158 |
125 RestApi::~RestApi() | |
126 { | |
127 for (GetHandlers::iterator it = getHandlers_.begin(); | |
128 it != getHandlers_.end(); ++it) | |
129 { | |
130 delete it->first; | |
131 } | |
132 | |
133 for (PutHandlers::iterator it = putHandlers_.begin(); | |
134 it != putHandlers_.end(); ++it) | |
135 { | |
136 delete it->first; | |
137 } | |
138 | |
139 for (PostHandlers::iterator it = postHandlers_.begin(); | |
140 it != postHandlers_.end(); ++it) | |
141 { | |
142 delete it->first; | |
143 } | |
144 | |
145 for (DeleteHandlers::iterator it = deleteHandlers_.begin(); | |
146 it != deleteHandlers_.end(); ++it) | |
147 { | |
148 delete it->first; | |
149 } | |
150 } | |
151 | 159 |
152 | 160 |
153 bool RestApi::Handle(HttpOutput& output, | 161 bool RestApi::Handle(HttpOutput& output, |
154 HttpMethod method, | 162 HttpMethod method, |
155 const UriComponents& uri, | 163 const UriComponents& uri, |
156 const Arguments& headers, | 164 const Arguments& headers, |
157 const Arguments& getArguments, | 165 const Arguments& getArguments, |
158 const std::string& postData) | 166 const std::string& postData) |
159 { | 167 { |
160 if (!IsGetAccepted(uri) && | 168 HttpHandlerVisitor visitor(*this, output, method, headers, getArguments, postData); |
161 !IsPutAccepted(uri) && | 169 |
162 !IsPostAccepted(uri) && | 170 if (root_.LookupResource(uri, visitor)) |
163 !IsDeleteAccepted(uri)) | 171 { |
164 { | 172 return true; |
165 // This URI is not served by this handler | 173 } |
166 return false; | 174 |
167 } | 175 Json::Value directory; |
168 | 176 if (root_.GetDirectory(directory, uri)) |
169 | 177 { |
170 bool ok = false; | 178 RestApiOutput tmp(output); |
171 RestApiOutput restOutput(output); | 179 tmp.AnswerJson(directory); |
172 HttpHandler::Arguments components; | 180 return true; |
173 UriComponents trailing; | 181 } |
174 | 182 |
175 if (method == HttpMethod_Get) | 183 std::set<HttpMethod> methods; |
176 { | 184 root_.GetAcceptedMethods(methods, uri); |
177 for (GetHandlers::const_iterator it = getHandlers_.begin(); | 185 |
178 it != getHandlers_.end(); ++it) | 186 if (methods.empty()) |
179 { | 187 { |
180 if (it->first->Match(components, trailing, uri)) | 188 return false; // This URI is not served by this REST API |
181 { | 189 } |
182 //LOG(INFO) << "REST GET call on: " << Toolbox::FlattenUri(uri); | 190 else |
183 ok = true; | |
184 RestApiGetCall call(restOutput, *this, headers, components, trailing, uri, getArguments); | |
185 it->second(call); | |
186 } | |
187 } | |
188 } | |
189 else if (method == HttpMethod_Put) | |
190 { | |
191 for (PutHandlers::const_iterator it = putHandlers_.begin(); | |
192 it != putHandlers_.end(); ++it) | |
193 { | |
194 if (it->first->Match(components, trailing, uri)) | |
195 { | |
196 //LOG(INFO) << "REST PUT call on: " << Toolbox::FlattenUri(uri); | |
197 ok = true; | |
198 RestApiPutCall call(restOutput, *this, headers, components, trailing, uri, postData); | |
199 it->second(call); | |
200 } | |
201 } | |
202 } | |
203 else if (method == HttpMethod_Post) | |
204 { | |
205 for (PostHandlers::const_iterator it = postHandlers_.begin(); | |
206 it != postHandlers_.end(); ++it) | |
207 { | |
208 if (it->first->Match(components, trailing, uri)) | |
209 { | |
210 //LOG(INFO) << "REST POST call on: " << Toolbox::FlattenUri(uri); | |
211 ok = true; | |
212 RestApiPostCall call(restOutput, *this, headers, components, trailing, uri, postData); | |
213 it->second(call); | |
214 } | |
215 } | |
216 } | |
217 else if (method == HttpMethod_Delete) | |
218 { | |
219 for (DeleteHandlers::const_iterator it = deleteHandlers_.begin(); | |
220 it != deleteHandlers_.end(); ++it) | |
221 { | |
222 if (it->first->Match(components, trailing, uri)) | |
223 { | |
224 //LOG(INFO) << "REST DELETE call on: " << Toolbox::FlattenUri(uri); | |
225 ok = true; | |
226 RestApiDeleteCall call(restOutput, *this, headers, components, trailing, uri); | |
227 it->second(call); | |
228 } | |
229 } | |
230 } | |
231 | |
232 if (!ok) | |
233 { | 191 { |
234 LOG(INFO) << "REST method " << EnumerationToString(method) | 192 LOG(INFO) << "REST method " << EnumerationToString(method) |
235 << " not allowed on: " << Toolbox::FlattenUri(uri); | 193 << " not allowed on: " << Toolbox::FlattenUri(uri); |
236 output.SendMethodNotAllowedError(GetAcceptedMethods(uri)); | 194 |
237 } | 195 output.SendMethodNotAllowedError(MethodsToString(methods)); |
238 | 196 |
239 return true; | 197 return true; |
198 } | |
240 } | 199 } |
241 | 200 |
242 void RestApi::Register(const std::string& path, | 201 void RestApi::Register(const std::string& path, |
243 RestApiGetCall::Handler handler) | 202 RestApiGetCall::Handler handler) |
244 { | 203 { |
245 root_.Register(path, handler); | 204 root_.Register(path, handler); |
246 getHandlers_.push_back(std::make_pair(new RestApiPath(path), handler)); | |
247 } | 205 } |
248 | 206 |
249 void RestApi::Register(const std::string& path, | 207 void RestApi::Register(const std::string& path, |
250 RestApiPutCall::Handler handler) | 208 RestApiPutCall::Handler handler) |
251 { | 209 { |
252 root_.Register(path, handler); | 210 root_.Register(path, handler); |
253 putHandlers_.push_back(std::make_pair(new RestApiPath(path), handler)); | |
254 } | 211 } |
255 | 212 |
256 void RestApi::Register(const std::string& path, | 213 void RestApi::Register(const std::string& path, |
257 RestApiPostCall::Handler handler) | 214 RestApiPostCall::Handler handler) |
258 { | 215 { |
259 root_.Register(path, handler); | 216 root_.Register(path, handler); |
260 postHandlers_.push_back(std::make_pair(new RestApiPath(path), handler)); | |
261 } | 217 } |
262 | 218 |
263 void RestApi::Register(const std::string& path, | 219 void RestApi::Register(const std::string& path, |
264 RestApiDeleteCall::Handler handler) | 220 RestApiDeleteCall::Handler handler) |
265 { | 221 { |
266 root_.Register(path, handler); | 222 root_.Register(path, handler); |
267 deleteHandlers_.push_back(std::make_pair(new RestApiPath(path), handler)); | |
268 } | 223 } |
269 } | 224 } |