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 }