comparison UnitTestsSources/RestApi.cpp @ 966:886652370ff2

accelerating REST API matching
author Sebastien Jodogne <s.jodogne@gmail.com>
date Fri, 27 Jun 2014 15:33:22 +0200
parents 84513f2ee1f3
children
comparison
equal deleted inserted replaced
965:d724ac031080 966:886652370ff2
136 136
137 ASSERT_FALSE(uri.Match(args, trail, "/coucou/moi/f")); 137 ASSERT_FALSE(uri.Match(args, trail, "/coucou/moi/f"));
138 ASSERT_TRUE(uri.Match(args, trail, "/coucou/moi/d/")); 138 ASSERT_TRUE(uri.Match(args, trail, "/coucou/moi/d/"));
139 ASSERT_FALSE(uri.Match(args, trail, "/a/moi/d")); 139 ASSERT_FALSE(uri.Match(args, trail, "/a/moi/d"));
140 ASSERT_FALSE(uri.Match(args, trail, "/coucou/moi")); 140 ASSERT_FALSE(uri.Match(args, trail, "/coucou/moi"));
141
142 ASSERT_EQ(3u, uri.GetLevelCount());
143 ASSERT_TRUE(uri.IsUniversalTrailing());
144
145 ASSERT_EQ("coucou", uri.GetLevelName(0));
146 ASSERT_THROW(uri.GetWildcardName(0), OrthancException);
147
148 ASSERT_EQ("abc", uri.GetWildcardName(1));
149 ASSERT_THROW(uri.GetLevelName(1), OrthancException);
150
151 ASSERT_EQ("d", uri.GetLevelName(2));
152 ASSERT_THROW(uri.GetWildcardName(2), OrthancException);
141 } 153 }
142 154
143 { 155 {
144 RestApiPath uri("/coucou/{abc}/d"); 156 RestApiPath uri("/coucou/{abc}/d");
145 ASSERT_FALSE(uri.Match(args, trail, "/coucou/moi/d/e/f/g")); 157 ASSERT_FALSE(uri.Match(args, trail, "/coucou/moi/d/e/f/g"));
146 ASSERT_TRUE(uri.Match(args, trail, "/coucou/moi/d")); 158 ASSERT_TRUE(uri.Match(args, trail, "/coucou/moi/d"));
147 ASSERT_EQ(1u, args.size()); 159 ASSERT_EQ(1u, args.size());
148 ASSERT_EQ(0u, trail.size()); 160 ASSERT_EQ(0u, trail.size());
149 ASSERT_EQ("moi", args["abc"]); 161 ASSERT_EQ("moi", args["abc"]);
162
163 ASSERT_EQ(3u, uri.GetLevelCount());
164 ASSERT_FALSE(uri.IsUniversalTrailing());
165
166 ASSERT_EQ("coucou", uri.GetLevelName(0));
167 ASSERT_THROW(uri.GetWildcardName(0), OrthancException);
168
169 ASSERT_EQ("abc", uri.GetWildcardName(1));
170 ASSERT_THROW(uri.GetLevelName(1), OrthancException);
171
172 ASSERT_EQ("d", uri.GetLevelName(2));
173 ASSERT_THROW(uri.GetWildcardName(2), OrthancException);
150 } 174 }
151 175
152 { 176 {
153 RestApiPath uri("/*"); 177 RestApiPath uri("/*");
154 ASSERT_TRUE(uri.Match(args, trail, "/a/b/c")); 178 ASSERT_TRUE(uri.Match(args, trail, "/a/b/c"));
155 ASSERT_EQ(0u, args.size()); 179 ASSERT_EQ(0u, args.size());
156 ASSERT_EQ(3u, trail.size()); 180 ASSERT_EQ(3u, trail.size());
157 ASSERT_EQ("a", trail[0]); 181 ASSERT_EQ("a", trail[0]);
158 ASSERT_EQ("b", trail[1]); 182 ASSERT_EQ("b", trail[1]);
159 ASSERT_EQ("c", trail[2]); 183 ASSERT_EQ("c", trail[2]);
184
185 ASSERT_EQ(0u, uri.GetLevelCount());
186 ASSERT_TRUE(uri.IsUniversalTrailing());
160 } 187 }
161 } 188 }
189
190
191
192
193
194
195 namespace Orthanc
196 {
197 class RestApiResource
198 {
199 private:
200 struct Handlers
201 {
202 std::list<RestApi::GetHandler> getHandlers_;
203 std::list<RestApi::PutHandler> putHandlers_;
204 std::list<RestApi::PostHandler> postHandlers_;
205 std::list<RestApi::DeleteHandler> deleteHandlers_;
206
207 void Register(RestApi::GetHandler handler)
208 {
209 getHandlers_.push_back(handler);
210 }
211
212 void Register(RestApi::PutHandler handler)
213 {
214 putHandlers_.push_back(handler);
215 }
216
217 void Register(RestApi::PostHandler handler)
218 {
219 postHandlers_.push_back(handler);
220 }
221
222 void Register(RestApi::DeleteHandler handler)
223 {
224 deleteHandlers_.push_back(handler);
225 }
226 };
227
228
229 typedef std::map<std::string, RestApiResource*> Children;
230
231 Children children_;
232 Children wildcardChildren_;
233 Handlers handlers_;
234 Handlers universalHandlers_;
235
236
237 static RestApiResource& AddChild(Children& children,
238 const std::string& name)
239 {
240 Children::iterator it = children.find(name);
241
242 if (it == children.end())
243 {
244 // Create new child
245 RestApiResource *child = new RestApiResource;
246 children[name] = child;
247 return *child;
248 }
249 else
250 {
251 return *it->second;
252 }
253 }
254
255
256 static void DeleteChildren(Children& children)
257 {
258 for (Children::iterator it = children.begin();
259 it != children.end(); it++)
260 {
261 delete it->second;
262 }
263 }
264
265
266
267
268 template <typename Handler>
269 void RegisterInternal(const RestApiPath& path,
270 Handler handler,
271 size_t level)
272 {
273 if (path.GetLevelCount() == level)
274 {
275 if (path.IsUniversalTrailing())
276 {
277 universalHandlers_.Register(handler);
278 }
279 else
280 {
281 handlers_.Register(handler);
282 }
283 }
284 else if (path.IsWildcardLevel(level))
285 {
286 AddChild(wildcardChildren_, path.GetWildcardName(level));
287 }
288 }
289
290
291 public:
292 ~RestApiResource()
293 {
294 DeleteChildren(children_);
295 DeleteChildren(wildcardChildren_);
296 }
297
298 void Register(const RestApiPath& path,
299 RestApi::GetHandler handler)
300 {
301 RegisterInternal(path, handler, 0);
302 }
303 };
304
305 }
306
307
308
309 static void Toto(RestApi::GetCall& get)
310 {
311 }
312
313
314 TEST(RestApi, RestApiResource)
315 {
316 RestApiResource root;
317
318 root.Register(RestApiPath("/hello/world/test"), Toto);
319 }