diff options
-rw-r--r-- | icespider/common/routes.ice | 8 | ||||
-rw-r--r-- | icespider/compile/routeCompiler.cpp | 68 | ||||
-rw-r--r-- | icespider/unittests/testCompile.cpp | 44 | ||||
-rw-r--r-- | icespider/unittests/testRoutes.json | 218 |
4 files changed, 160 insertions, 178 deletions
diff --git a/icespider/common/routes.ice b/icespider/common/routes.ice index e238664..e77fed4 100644 --- a/icespider/common/routes.ice +++ b/icespider/common/routes.ice @@ -23,12 +23,12 @@ module IceSpider { dictionary<string, Parameter> Parameters; class OutputSerializer { - string contentType; string serializer; StringSeq params; }; - sequence<OutputSerializer> OutputSerializers; + ["slicer:json:object"] + dictionary<string, OutputSerializer> OutputSerializers; class Operation { string operation; @@ -39,7 +39,6 @@ module IceSpider { dictionary<string, Operation> Operations; class Route { - string name; string path; HttpMethod method = GET; optional(0) string operation; @@ -49,7 +48,8 @@ module IceSpider { OutputSerializers outputSerializers; }; - sequence<Route> Routes; + ["slicer:json:object"] + dictionary<string, Route> Routes; class RouteConfiguration { string name; diff --git a/icespider/compile/routeCompiler.cpp b/icespider/compile/routeCompiler.cpp index 0f603f5..b8b89db 100644 --- a/icespider/compile/routeCompiler.cpp +++ b/icespider/compile/routeCompiler.cpp @@ -97,7 +97,7 @@ namespace IceSpider { for (const auto & o : r->operations) { auto op = findOperation(o.second->operation, us); if (!op) { - throw std::runtime_error("Find operator failed for " + r->name); + throw std::runtime_error("Find operator failed for " + r->path); } for (const auto & p : op->parameters()) { auto po = o.second->paramOverrides.find(p->name()); @@ -116,21 +116,21 @@ namespace IceSpider { RouteCompiler::applyDefaults(RouteConfigurationPtr c, const Units & u) const { for (const auto & r : c->routes) { - if (r->operation) { - r->operations[std::string()] = new Operation(*r->operation, {}); + if (r.second->operation) { + r.second->operations[std::string()] = new Operation(*r.second->operation, {}); } - auto ps = findParameters(r, u); + auto ps = findParameters(r.second, u); for (const auto & p : ps) { - auto defined = r->params.find(p.first); - if (defined != r->params.end()) { + auto defined = r.second->params.find(p.first); + if (defined != r.second->params.end()) { if (!defined->second->key) defined->second->key = defined->first; } else { - defined = r->params.insert({ p.first, new Parameter(ParameterSource::URL, p.first, false, IceUtil::Optional<std::string>(), false) }).first; + defined = r.second->params.insert({ p.first, new Parameter(ParameterSource::URL, p.first, false, IceUtil::Optional<std::string>(), false) }).first; } auto d = defined->second; if (d->source == ParameterSource::URL) { - Path path(r->path); + Path path(r.second->path); d->hasUserSource = std::find_if(path.parts.begin(), path.parts.end(), [d](const auto & pp) { if (auto par = dynamic_cast<PathParameter *>(pp.get())) { return par->name == d->key; @@ -232,12 +232,12 @@ namespace IceSpider { RouteCompiler::registerOutputSerializers(FILE * output, RoutePtr r) const { for (const auto & os : r->outputSerializers) { - auto bs = boost::algorithm::replace_all_copy(os->serializer, ".", "::"); - auto slash = os->contentType.find('/'); + auto bs = boost::algorithm::replace_all_copy(os.second->serializer, ".", "::"); + auto slash = os.first.find('/'); fprintbf(4, output, "addRouteSerializer({ \"%s\", \"%s\" }, new %s::IceSpiderFactory(", - os->contentType.substr(0, slash), os->contentType.substr(slash + 1), bs); - for (auto p = os->params.begin(); p != os->params.end(); ++p) { - if (p != os->params.begin()) { + os.first.substr(0, slash), os.first.substr(slash + 1), bs); + for (auto p = os.second->params.begin(); p != os.second->params.end(); ++p) { + if (p != os.second->params.begin()) { fprintf(output, ", "); } fputs(p->c_str(), output); @@ -250,9 +250,9 @@ namespace IceSpider { RouteCompiler::releaseOutputSerializers(FILE * output, RoutePtr r) const { for (const auto & os : r->outputSerializers) { - auto slash = os->contentType.find('/'); + auto slash = os.first.find('/'); fprintbf(4, output, "removeRouteSerializer({ \"%s\", \"%s\" });\n", - os->contentType.substr(0, slash), os->contentType.substr(slash + 1)); + os.first.substr(0, slash), os.first.substr(slash + 1)); } } @@ -285,20 +285,20 @@ namespace IceSpider { fprintbf(output, "namespace %s {\n", c->name); fprintbf(1, output, "// Implementation classes.\n\n"); for (const auto & r : c->routes) { - std::string methodName = getEnumString(r->method); + std::string methodName = getEnumString(r.second->method); - fprintbf(1, output, "// Route name: %s\n", r->name); - fprintbf(1, output, "// path: %s\n", r->path); - fprintbf(1, output, "class %s : public IceSpider::IRouteHandler {\n", r->name); + fprintbf(1, output, "// Route name: %s\n", r.first); + fprintbf(1, output, "// path: %s\n", r.second->path); + fprintbf(1, output, "class %s : public IceSpider::IRouteHandler {\n", r.first); fprintbf(2, output, "public:\n"); - fprintbf(3, output, "%s(const IceSpider::Core * core) :\n", r->name); - fprintbf(4, output, "IceSpider::IRouteHandler(IceSpider::HttpMethod::%s, \"%s\")", methodName, r->path); - auto proxies = initializeProxies(output, r); - for (const auto & p : r->params) { + fprintbf(3, output, "%s(const IceSpider::Core * core) :\n", r.first); + fprintbf(4, output, "IceSpider::IRouteHandler(IceSpider::HttpMethod::%s, \"%s\")", methodName, r.second->path); + auto proxies = initializeProxies(output, r.second); + for (const auto & p : r.second->params) { if (p.second->hasUserSource) { fprintf(output, ",\n"); if (p.second->source == ParameterSource::URL) { - Path path(r->path); + Path path(r.second->path); unsigned int idx = -1; for (const auto & pp : path.parts) { if (auto par = dynamic_cast<PathParameter *>(pp.get())) { @@ -321,16 +321,16 @@ namespace IceSpider { } fprintf(output, "\n"); fprintbf(3, output, "{\n"); - registerOutputSerializers(output, r); + registerOutputSerializers(output, r.second); fprintbf(3, output, "}\n\n"); - fprintbf(3, output, "~%s()\n", r->name); + fprintbf(3, output, "~%s()\n", r.first); fprintbf(3, output, "{\n"); - releaseOutputSerializers(output, r); + releaseOutputSerializers(output, r.second); fprintbf(3, output, "}\n\n"); fprintbf(3, output, "void execute(IceSpider::IHttpRequest * request) const\n"); fprintbf(3, output, "{\n"); - auto ps = findParameters(r, units); - for (const auto & p : r->params) { + auto ps = findParameters(r.second, units); + for (const auto & p : r.second->params) { if (p.second->hasUserSource) { auto ip = ps.find(p.first)->second; fprintbf(4, output, "auto _p_%s(request->get%sParam<%s>(_p%c_%s)", @@ -351,16 +351,16 @@ namespace IceSpider { fprintbf(0, output, ");\n"); } } - if (r->operation) { - addSingleOperation(output, r, findOperation(*r->operation, units)); + if (r.second->operation) { + addSingleOperation(output, r.second, findOperation(*r.second->operation, units)); } else { - addMashupOperations(output, r, proxies, units); + addMashupOperations(output, r.second, proxies, units); } fprintbf(3, output, "}\n\n"); fprintbf(2, output, "private:\n"); declareProxies(output, proxies); - for (const auto & p : r->params) { + for (const auto & p : r.second->params) { if (p.second->hasUserSource) { if (p.second->source == ParameterSource::URL) { fprintbf(3, output, "const unsigned int _pi_%s;\n", p.first); @@ -381,7 +381,7 @@ namespace IceSpider { fprintbf(output, "} // namespace %s\n\n", c->name); fprintf(output, "// Register route handlers.\n"); for (const auto & r : c->routes) { - fprintbf(output, "FACTORY(%s::%s, IceSpider::RouteHandlerFactory);\n", c->name, r->name); + fprintbf(output, "FACTORY(%s::%s, IceSpider::RouteHandlerFactory);\n", c->name, r.first); } fprintf(output, "\n// End generated code.\n"); } diff --git a/icespider/unittests/testCompile.cpp b/icespider/unittests/testCompile.cpp index 063d691..4fb7827 100644 --- a/icespider/unittests/testCompile.cpp +++ b/icespider/unittests/testCompile.cpp @@ -38,31 +38,25 @@ BOOST_AUTO_TEST_CASE( testLoadConfiguration ) BOOST_REQUIRE_EQUAL("common", cfg->name); BOOST_REQUIRE_EQUAL(10, cfg->routes.size()); - BOOST_REQUIRE_EQUAL("index", cfg->routes[0]->name); - BOOST_REQUIRE_EQUAL("/", cfg->routes[0]->path); - BOOST_REQUIRE_EQUAL(HttpMethod::GET, cfg->routes[0]->method); - BOOST_REQUIRE_EQUAL("TestIceSpider.TestApi.index", cfg->routes[0]->operation); - BOOST_REQUIRE_EQUAL(0, cfg->routes[0]->params.size()); - - BOOST_REQUIRE_EQUAL("item", cfg->routes[1]->name); - BOOST_REQUIRE_EQUAL("/view/{s}/{i}", cfg->routes[1]->path); - BOOST_REQUIRE_EQUAL(2, cfg->routes[1]->params.size()); - - BOOST_REQUIRE_EQUAL("del", cfg->routes[2]->name); - BOOST_REQUIRE_EQUAL(HttpMethod::DELETE, cfg->routes[2]->method); - BOOST_REQUIRE_EQUAL(1, cfg->routes[2]->params.size()); - - BOOST_REQUIRE_EQUAL("update", cfg->routes[3]->name); - BOOST_REQUIRE_EQUAL(HttpMethod::POST, cfg->routes[3]->method); - BOOST_REQUIRE_EQUAL(2, cfg->routes[3]->params.size()); - - BOOST_REQUIRE_EQUAL("mashStruct", cfg->routes[6]->name); - BOOST_REQUIRE_EQUAL(HttpMethod::GET, cfg->routes[6]->method); - BOOST_REQUIRE_EQUAL(3, cfg->routes[6]->params.size()); - - BOOST_REQUIRE_EQUAL("mashClass", cfg->routes[7]->name); - BOOST_REQUIRE_EQUAL(HttpMethod::GET, cfg->routes[7]->method); - BOOST_REQUIRE_EQUAL(3, cfg->routes[7]->params.size()); + BOOST_REQUIRE_EQUAL("/", cfg->routes["index"]->path); + BOOST_REQUIRE_EQUAL(HttpMethod::GET, cfg->routes["index"]->method); + BOOST_REQUIRE_EQUAL("TestIceSpider.TestApi.index", cfg->routes["index"]->operation); + BOOST_REQUIRE_EQUAL(0, cfg->routes["index"]->params.size()); + + BOOST_REQUIRE_EQUAL("/view/{s}/{i}", cfg->routes["item"]->path); + BOOST_REQUIRE_EQUAL(2, cfg->routes["item"]->params.size()); + + BOOST_REQUIRE_EQUAL(HttpMethod::DELETE, cfg->routes["del"]->method); + BOOST_REQUIRE_EQUAL(1, cfg->routes["del"]->params.size()); + + BOOST_REQUIRE_EQUAL(HttpMethod::POST, cfg->routes["update"]->method); + BOOST_REQUIRE_EQUAL(2, cfg->routes["update"]->params.size()); + + BOOST_REQUIRE_EQUAL(HttpMethod::GET, cfg->routes["mashStruct"]->method); + BOOST_REQUIRE_EQUAL(3, cfg->routes["mashStruct"]->params.size()); + + BOOST_REQUIRE_EQUAL(HttpMethod::GET, cfg->routes["mashClass"]->method); + BOOST_REQUIRE_EQUAL(3, cfg->routes["mashClass"]->params.size()); BOOST_REQUIRE_EQUAL(1, cfg->slices.size()); BOOST_REQUIRE_EQUAL("test-api.ice", cfg->slices[0]); diff --git a/icespider/unittests/testRoutes.json b/icespider/unittests/testRoutes.json index 52add90..13a6806 100644 --- a/icespider/unittests/testRoutes.json +++ b/icespider/unittests/testRoutes.json @@ -1,132 +1,120 @@ { "name": "common", "headers": [ "xsltStreamSerializer.h" ], - "routes": [ - { - "name": "index", - "path": "/", - "method": "GET", - "outputSerializers": [ - { - "contentType": "text/html", - "serializer": "IceSpider.XsltStreamSerializer", - "params": [ "\"xslt/transform.xslt\"" ] - } - ], - "operation": "TestIceSpider.TestApi.index" - }, - { - "name": "item", - "path": "/view/{s}/{i}", - "method": "GET", - "operation": "TestIceSpider.TestApi.withParams" - }, - { - "name": "del", - "path": "/{s}", - "method": "DELETE", - "operation": "TestIceSpider.TestApi.returnNothing" - }, - { - "name": "update", - "path": "/{id}", - "method": "POST", - "operation": "TestIceSpider.TestApi.complexParam", - "params": { - "s": { - "source": "URL", - "key": "id", - "isOptional": true + "routes": { + "index": { + "path": "/", + "method": "GET", + "outputSerializers": { + "text/html": { + "serializer": "IceSpider.XsltStreamSerializer", + "params": [ "\"xslt/transform.xslt\"" ] + } }, - "m": { - "source": "Body" + "operation": "TestIceSpider.TestApi.index" + }, + "item": { + "path": "/view/{s}/{i}", + "method": "GET", + "operation": "TestIceSpider.TestApi.withParams" + }, + "del": { + "path": "/{s}", + "method": "DELETE", + "operation": "TestIceSpider.TestApi.returnNothing" + }, + "update": { + "path": "/{id}", + "method": "POST", + "operation": "TestIceSpider.TestApi.complexParam", + "params": { + "s": { + "source": "URL", + "key": "id", + "isOptional": true + }, + "m": { + "source": "Body" + } } - } - }, - { - "name": "defaultItem", - "path": "/item/{s}", - "method": "GET", - "operation": "TestIceSpider.TestApi.withParams", - "params": { - "i": { - "default": "1234" + }, + "defaultItem": { + "path": "/item/{s}", + "method": "GET", + "operation": "TestIceSpider.TestApi.withParams", + "params": { + "i": { + "default": "1234" + } } - } - }, - { - "name": "itemWithDefault", - "path": "/item/{s}/{i}", - "method": "GET", - "operation": "TestIceSpider.TestApi.withParams", - "params": { - "i": { - "default": "1234" + }, + "itemWithDefault":{ + "path": "/item/{s}/{i}", + "method": "GET", + "operation": "TestIceSpider.TestApi.withParams", + "params": { + "i": { + "default": "1234" + } } - } - }, - { - "name": "mashStruct", - "path": "/mashS/{s}/{t}/{i}", - "method": "GET", - "type": "TestIceSpider.Mash1", - "operations": { - "a": { - "operation": "TestIceSpider.TestApi.withParams" - }, - "b": { - "operation": "TestIceSpider.TestApi.withParams", - "paramOverrides": { - "s": "t" + }, + "mashStruct": { + "path": "/mashS/{s}/{t}/{i}", + "method": "GET", + "type": "TestIceSpider.Mash1", + "operations": { + "a": { + "operation": "TestIceSpider.TestApi.withParams" + }, + "b": { + "operation": "TestIceSpider.TestApi.withParams", + "paramOverrides": { + "s": "t" + } } } - } - }, - { - "name": "mashClass", - "path": "/mashC/{s}/{t}/{i}", - "method": "GET", - "type": "TestIceSpider.Mash2", - "operations": { - "a": { - "operation": "TestIceSpider.TestApi.withParams" - }, - "b": { - "operation": "TestIceSpider.TestApi.withParams", - "paramOverrides": { - "s": "t" + }, + "mashClass": { + "path": "/mashC/{s}/{t}/{i}", + "method": "GET", + "type": "TestIceSpider.Mash2", + "operations": { + "a": { + "operation": "TestIceSpider.TestApi.withParams" + }, + "b": { + "operation": "TestIceSpider.TestApi.withParams", + "paramOverrides": { + "s": "t" + } } } - } - }, - { - "name": "override", - "path": "/override", - "method": "GET", - "outputSerializers": [ - { - "contentType": "application/xml", - "serializer": "IceSpider.XsltStreamSerializer", - "params": [ "\"xslt/transform.xslt\"" ] - } - ], - "operation": "TestIceSpider.TestApi.index" - }, - { - "name": "search", - "path": "/search", - "method": "GET", - "operation": "TestIceSpider.TestApi.withParams", - "params": { - "s": { - "source": "QueryString" + }, + "override": { + "path": "/override", + "method": "GET", + "outputSerializers": { + "application/xml": { + "serializer": "IceSpider.XsltStreamSerializer", + "params": [ "\"xslt/transform.xslt\"" ] + } }, - "i": { - "source": "QueryString" + "operation": "TestIceSpider.TestApi.index" + }, + "search": { + "path": "/search", + "method": "GET", + "operation": "TestIceSpider.TestApi.withParams", + "params": { + "s": { + "source": "QueryString" + }, + "i": { + "source": "QueryString" + } } } - } - ], + }, "slices": [ "test-api.ice" ] |