API calls now get parsed through a grammar using boost::spirit::qi
This commit is contained in:
		
							parent
							
								
									837e91f56d
								
							
						
					
					
						commit
						4a89cfee3d
					
				| @ -25,16 +25,14 @@ public: | ||||
| 		reply.status = http::Reply::ok; | ||||
| 		reply.content.append("<html><head><title>Hello World Demonstration Document</title></head><body><h1>Hello, World!</h1>"); | ||||
| 		std::stringstream content; | ||||
| 		content << "Number of parameters: " << routeParameters.parameters.size() << "<br>"; | ||||
| 		for(unsigned i = 0; i < routeParameters.parameters.size(); i++) { | ||||
| 			content << routeParameters.parameters[i] << "<br>"; | ||||
| 		} | ||||
| 		content << "Number Of Options: " << routeParameters.options.Size() << "<br>"; | ||||
| 		RouteParameters::OptionsIterator optionsIT = routeParameters.options.begin(); | ||||
| 		for(;optionsIT != routeParameters.options.end(); optionsIT++) { | ||||
| 		    content << "param  = " << optionsIT->first  << ": "; | ||||
| 		    content << "option = " << optionsIT->second << "<br>"; | ||||
| 		} | ||||
|         content << "Number of locations: " << routeParameters.coordinates.size() << "<br>\n"; | ||||
|         for(unsigned i = 0; i < routeParameters.coordinates.size(); ++i) { | ||||
|             content << "  [" << i << "] " << routeParameters.coordinates[i].lat/100000. << "," << routeParameters.coordinates[i].lon/100000. << "<br>\n"; | ||||
|         } | ||||
|         content << "Number of hints: " << routeParameters.hints.size() << "<br>\n"; | ||||
|         for(unsigned i = 0; i < routeParameters.hints.size(); ++i) { | ||||
|             content << "  [" << i << "] " << routeParameters.hints[i] << "<br>\n"; | ||||
|         } | ||||
| 		reply.content.append(content.str()); | ||||
| 		reply.content.append("</body></html>"); | ||||
| 	} | ||||
|  | ||||
| @ -41,21 +41,11 @@ public: | ||||
|     std::string GetVersionString() const { return std::string("0.3 (DL)"); } | ||||
|     void HandleRequest(const RouteParameters & routeParameters, http::Reply& reply) { | ||||
|         //check number of parameters
 | ||||
|         if(!routeParameters.viaPoints.size()) { | ||||
|         if(!routeParameters.coordinates.size()) { | ||||
|             reply = http::Reply::stockReply(http::Reply::badRequest); | ||||
|             return; | ||||
|         } | ||||
|         std::vector<std::string> textCoord; | ||||
|         stringSplit (routeParameters.viaPoints[0], ',', textCoord); | ||||
|         if(textCoord.size() != 2) { | ||||
|             reply = http::Reply::stockReply(http::Reply::badRequest); | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         int lat = 100000.*atof(textCoord[0].c_str()); | ||||
|         int lon = 100000.*atof(textCoord[1].c_str()); | ||||
|         _Coordinate myCoordinate(lat, lon); | ||||
|         if(false == checkCoord(myCoordinate)) { | ||||
|         if(false == checkCoord(routeParameters.coordinates[0])) { | ||||
|             reply = http::Reply::stockReply(http::Reply::badRequest); | ||||
|             return; | ||||
|         } | ||||
| @ -65,15 +55,15 @@ public: | ||||
|         std::string JSONParameter, tmp; | ||||
|         //json
 | ||||
| 
 | ||||
|         JSONParameter = routeParameters.options.Find("jsonp"); | ||||
|         if("" != JSONParameter) { | ||||
| //        JSONParameter = routeParameters.options.Find("jsonp");
 | ||||
|         if("" != routeParameters.jsonpParameter) { | ||||
|             reply.content += JSONParameter; | ||||
|             reply.content += "("; | ||||
|         } | ||||
|         reply.status = http::Reply::ok; | ||||
|         reply.content += ("{"); | ||||
|         reply.content += ("\"version\":0.3,"); | ||||
|         if(!nodeHelpDesk->FindNearestNodeCoordForLatLon(myCoordinate, result)) { | ||||
|         if(!nodeHelpDesk->FindNearestNodeCoordForLatLon(routeParameters.coordinates[0], result)) { | ||||
|             reply.content += ("\"status\":207,"); | ||||
|             reply.content += ("\"mapped_coordinate\":[]"); | ||||
|         } else { | ||||
|  | ||||
| @ -29,7 +29,6 @@ or see http://www.gnu.org/licenses/agpl.txt. | ||||
| #include "../Server/DataStructures/QueryObjectsStorage.h" | ||||
| 
 | ||||
| #include "../DataStructures/NodeInformationHelpDesk.h" | ||||
| #include "../DataStructures/HashTable.h" | ||||
| #include "../Util/StringUtil.h" | ||||
| 
 | ||||
| /*
 | ||||
| @ -47,43 +46,25 @@ public: | ||||
|     std::string GetVersionString() const { return std::string("0.3 (DL)"); } | ||||
|     void HandleRequest(const RouteParameters & routeParameters, http::Reply& reply) { | ||||
|         //check number of parameters
 | ||||
|         if(!routeParameters.viaPoints.size()) { | ||||
|         if(!routeParameters.coordinates.size()) { | ||||
|             reply = http::Reply::stockReply(http::Reply::badRequest); | ||||
|             return; | ||||
|         } | ||||
|         std::vector<std::string> textCoord; | ||||
|         stringSplit (routeParameters.viaPoints[0], ',', textCoord); | ||||
|         if(textCoord.size() != 2) { | ||||
|         	reply = http::Reply::stockReply(http::Reply::badRequest); | ||||
|         	return; | ||||
|         } | ||||
| 
 | ||||
|         int lat = 100000.*atof(textCoord[0].c_str()); | ||||
|         int lon = 100000.*atof(textCoord[1].c_str()); | ||||
|         _Coordinate myCoordinate(lat, lon); | ||||
|         if(false == checkCoord(myCoordinate)) { | ||||
|         if(false == checkCoord(routeParameters.coordinates[0])) { | ||||
|             reply = http::Reply::stockReply(http::Reply::badRequest); | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         unsigned zoomLevel = 18; | ||||
|         if(routeParameters.options.Find("z") != ""){ | ||||
|             zoomLevel = atoi(routeParameters.options.Find("z").c_str()); | ||||
|             if(18 < zoomLevel) | ||||
|                 zoomLevel = 18; | ||||
|         } | ||||
| 
 | ||||
|         //query to helpdesk
 | ||||
|         PhantomNode result; | ||||
|         nodeHelpDesk->FindPhantomNodeForCoordinate(myCoordinate, result, zoomLevel); | ||||
|         nodeHelpDesk->FindPhantomNodeForCoordinate(routeParameters.coordinates[0], result, routeParameters.zoomLevel); | ||||
| 
 | ||||
|         std::string tmp; | ||||
|         std::string JSONParameter; | ||||
|         //json
 | ||||
| 
 | ||||
|         JSONParameter = routeParameters.options.Find("jsonp"); | ||||
|         if("" != JSONParameter) { | ||||
|             reply.content += JSONParameter; | ||||
|         if("" != routeParameters.jsonpParameter) { | ||||
|             reply.content += routeParameters.jsonpParameter; | ||||
|             reply.content += "("; | ||||
|         } | ||||
| 
 | ||||
|  | ||||
| @ -23,14 +23,73 @@ or see http://www.gnu.org/licenses/agpl.txt. | ||||
| 
 | ||||
| #include <string> | ||||
| #include <vector> | ||||
| #include "../DataStructures/HashTable.h" | ||||
| 
 | ||||
| #include <boost/fusion/sequence/intrinsic.hpp> | ||||
| 
 | ||||
| #include "../DataStructures/Coordinate.h" | ||||
| 
 | ||||
| struct RouteParameters { | ||||
|     RouteParameters() : zoomLevel(18), printInstructions(false), geometry(true), compression(true), checkSum(-1) {} | ||||
|     short zoomLevel; | ||||
|     bool printInstructions; | ||||
|     bool geometry; | ||||
|     bool compression; | ||||
|     int checkSum; | ||||
|     std::string service; | ||||
|     std::string outputFormat; | ||||
|     std::string jsonpParameter; | ||||
|     std::string language; | ||||
|     std::vector<std::string> hints; | ||||
|     std::vector<std::string> parameters; | ||||
|     std::vector<std::string> viaPoints; | ||||
|     HashTable<std::string, std::string> options; | ||||
|     std::vector<_Coordinate> coordinates; | ||||
|     typedef HashTable<std::string, std::string>::MyIterator OptionsIterator; | ||||
| 
 | ||||
|     void setZoomLevel(const short i) { | ||||
|         if (18 > i && 0 < i) | ||||
|             zoomLevel = i; | ||||
|     } | ||||
| 
 | ||||
|     void setChecksum(const int c) { | ||||
|         checkSum = c; | ||||
|     } | ||||
| 
 | ||||
|     void setInstructionFlag(const bool b) { | ||||
|         printInstructions = b; | ||||
|     } | ||||
| 
 | ||||
|     void printService( const std::string & s) { | ||||
|         service = s; | ||||
|     } | ||||
| 
 | ||||
|     void setOutputFormat(const std::string & s) { | ||||
|         outputFormat = s; | ||||
|     } | ||||
| 
 | ||||
|     void setJSONpParameter(const std::string & s) { | ||||
|         jsonpParameter = s; | ||||
|     } | ||||
| 
 | ||||
|     void addHint(const std::string & s) { | ||||
|         hints.push_back(s); | ||||
|     } | ||||
| 
 | ||||
|     void setLanguage(const std::string & s) { | ||||
|         language = s; | ||||
|     } | ||||
| 
 | ||||
|     void setGeometryFlag(const bool b) { | ||||
|         geometry = b; | ||||
|     } | ||||
| 
 | ||||
|     void setCompressionFlag(const bool b) { | ||||
|         compression = b; | ||||
|     } | ||||
| 
 | ||||
|     void addCoordinate(boost::fusion::vector < double, double > arg_) { | ||||
|         int lat = 100000.*boost::fusion::at_c < 0 > (arg_); | ||||
|         int lon = 100000.*boost::fusion::at_c < 1 > (arg_); | ||||
|         _Coordinate myCoordinate(lat, lon); | ||||
|         coordinates.push_back(_Coordinate(lat, lon)); | ||||
|     } | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
|  | ||||
| @ -37,9 +37,8 @@ public: | ||||
|         std::string JSONParameter; | ||||
| 
 | ||||
|         //json
 | ||||
|         JSONParameter = routeParameters.options.Find("jsonp"); | ||||
|         if("" != JSONParameter) { | ||||
|             reply.content += JSONParameter; | ||||
|         if("" != routeParameters.jsonpParameter) { | ||||
|             reply.content += routeParameters.jsonpParameter; | ||||
|             reply.content += "("; | ||||
|         } | ||||
| 
 | ||||
|  | ||||
| @ -74,37 +74,21 @@ public: | ||||
|     std::string GetVersionString() const { return std::string("0.3 (DL)"); } | ||||
|     void HandleRequest(const RouteParameters & routeParameters, http::Reply& reply) { | ||||
|         //check number of parameters
 | ||||
|         if( 2 > routeParameters.viaPoints.size() ) { | ||||
|         if( 2 > routeParameters.coordinates.size() ) { | ||||
|             reply = http::Reply::stockReply(http::Reply::badRequest); | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         unsigned zoomLevel = 18; | ||||
|         if(routeParameters.options.Find("z") != ""){ | ||||
|             zoomLevel = atoi(routeParameters.options.Find("z").c_str()); | ||||
|             if(18 < zoomLevel) | ||||
|                 zoomLevel = 18; | ||||
|         } | ||||
| 
 | ||||
|         RawRouteData rawRoute; | ||||
|         rawRoute.checkSum = nodeHelpDesk->GetCheckSum(); | ||||
|         bool checksumOK = ((unsigned)atoi(routeParameters.options.Find("checksum").c_str()) == rawRoute.checkSum); | ||||
|         bool checksumOK = (routeParameters.checkSum == rawRoute.checkSum); | ||||
|         std::vector<std::string> textCoord; | ||||
|         for(unsigned i = 0; i < routeParameters.viaPoints.size(); ++i) { | ||||
|             textCoord.resize(0); | ||||
|             stringSplit (routeParameters.viaPoints[i], ',', textCoord); | ||||
|             if(textCoord.size() != 2) { | ||||
|         for(unsigned i = 0; i < routeParameters.coordinates.size(); ++i) { | ||||
|             if(false == checkCoord(routeParameters.coordinates[i])) { | ||||
|                 reply = http::Reply::stockReply(http::Reply::badRequest); | ||||
|                 return; | ||||
|             } | ||||
|             int vialat = static_cast<int>(100000.*atof(textCoord[0].c_str())); | ||||
|             int vialon = static_cast<int>(100000.*atof(textCoord[1].c_str())); | ||||
|             _Coordinate viaCoord(vialat, vialon); | ||||
|             if(false == checkCoord(viaCoord)) { | ||||
|                 reply = http::Reply::stockReply(http::Reply::badRequest); | ||||
|                 return; | ||||
|             } | ||||
|             rawRoute.rawViaNodeCoordinates.push_back(viaCoord); | ||||
|             rawRoute.rawViaNodeCoordinates.push_back(routeParameters.coordinates[i]); | ||||
|         } | ||||
|         std::vector<PhantomNode> phantomNodeVector(rawRoute.rawViaNodeCoordinates.size()); | ||||
|         for(unsigned i = 0; i < rawRoute.rawViaNodeCoordinates.size(); ++i) { | ||||
| @ -117,9 +101,8 @@ public: | ||||
|                 } | ||||
|             } | ||||
| //            INFO("Brute force lookup of coordinate " << i);
 | ||||
|             searchEngine->FindPhantomNodeForCoordinate( rawRoute.rawViaNodeCoordinates[i], phantomNodeVector[i], zoomLevel); | ||||
|             searchEngine->FindPhantomNodeForCoordinate( rawRoute.rawViaNodeCoordinates[i], phantomNodeVector[i], routeParameters.zoomLevel); | ||||
|         } | ||||
|         //unsigned distance = 0;
 | ||||
| 
 | ||||
|         for(unsigned i = 0; i < phantomNodeVector.size()-1; ++i) { | ||||
|             PhantomNodes segmentPhantomNodes; | ||||
| @ -134,21 +117,6 @@ public: | ||||
|         } else { | ||||
|             searchEngine->shortestPath(rawRoute.segmentEndCoordinates, rawRoute); | ||||
|         } | ||||
| //        std::cout << "latitude,longitude" << std::endl;
 | ||||
| //        for(unsigned i = 0; i < rawRoute.computedShortestPath.size(); ++i) {
 | ||||
| //            _Coordinate current;
 | ||||
| //            searchEngine->GetCoordinatesForNodeID(rawRoute.computedShortestPath[i].node, current);
 | ||||
| //            std::cout << current.lat/100000. << "," << current.lon/100000. << std::endl;
 | ||||
| //        }
 | ||||
| //        std::cout << std::endl;
 | ||||
| //
 | ||||
| //        std::cout << "latitude,longitude" << std::endl;
 | ||||
| //        for(unsigned i = 0; i < rawRoute.computedAlternativePath.size(); ++i) {
 | ||||
| //            _Coordinate current;
 | ||||
| //            searchEngine->GetCoordinatesForNodeID(rawRoute.computedAlternativePath[i].node, current);
 | ||||
| //            std::cout << current.lat/100000. << "," << current.lon/100000. << std::endl;
 | ||||
| //        }
 | ||||
| //        std::cout << std::endl;
 | ||||
| 
 | ||||
| 
 | ||||
|         if(INT_MAX == rawRoute.lengthOfShortestPath ) { | ||||
| @ -158,24 +126,18 @@ public: | ||||
| 
 | ||||
|         //TODO: Move to member as smart pointer
 | ||||
|         BaseDescriptor<SearchEngine<QueryEdge::EdgeData, StaticGraph<QueryEdge::EdgeData> > > * desc; | ||||
|         std::string JSONParameter = routeParameters.options.Find("jsonp"); | ||||
|         if("" != JSONParameter) { | ||||
|             reply.content += JSONParameter; | ||||
|         if("" != routeParameters.jsonpParameter) { | ||||
|             reply.content += routeParameters.jsonpParameter; | ||||
|             reply.content += "("; | ||||
|         } | ||||
| 
 | ||||
|         _DescriptorConfig descriptorConfig; | ||||
|         unsigned descriptorType = descriptorTable[routeParameters.options.Find("output")]; | ||||
|         descriptorConfig.z = zoomLevel; | ||||
|         if(routeParameters.options.Find("instructions") == "false") { | ||||
|             descriptorConfig.instructions = false; | ||||
|         } | ||||
|         if(routeParameters.options.Find("geometry") == "false" ) { | ||||
|             descriptorConfig.geometry = false; | ||||
|         } | ||||
|         if("cmp" == routeParameters.options.Find("no") || "cmp6" == routeParameters.options.Find("no")  ) { | ||||
|             descriptorConfig.encodeGeometry = false; | ||||
|         } | ||||
|         unsigned descriptorType = descriptorTable[routeParameters.outputFormat]; | ||||
|         descriptorConfig.z = routeParameters.zoomLevel; | ||||
|         descriptorConfig.instructions = routeParameters.printInstructions; | ||||
|         descriptorConfig.geometry = routeParameters.geometry; | ||||
|         descriptorConfig.encodeGeometry = routeParameters.compression; | ||||
| 
 | ||||
|         switch(descriptorType){ | ||||
|         case 0: | ||||
|             desc = new JSONDescriptor<SearchEngine<QueryEdge::EdgeData, StaticGraph<QueryEdge::EdgeData> > >(); | ||||
| @ -200,7 +162,7 @@ public: | ||||
|         desc->SetConfig(descriptorConfig); | ||||
| 
 | ||||
|         desc->Run(reply, rawRoute, phantomNodes, *searchEngine); | ||||
|         if("" != JSONParameter) { | ||||
|         if("" != routeParameters.jsonpParameter) { | ||||
|             reply.content += ")\n"; | ||||
|         } | ||||
|         reply.headers.resize(3); | ||||
| @ -210,7 +172,7 @@ public: | ||||
|         reply.headers[0].value = tmp; | ||||
|         switch(descriptorType){ | ||||
|         case 0: | ||||
|             if("" != JSONParameter){ | ||||
|             if("" != routeParameters.jsonpParameter){ | ||||
|                 reply.headers[1].name = "Content-Type"; | ||||
|                 reply.headers[1].value = "text/javascript"; | ||||
|                 reply.headers[2].name = "Content-Disposition"; | ||||
| @ -231,7 +193,7 @@ public: | ||||
| 
 | ||||
|             break; | ||||
|         default: | ||||
|             if("" != JSONParameter){ | ||||
|             if("" != routeParameters.jsonpParameter){ | ||||
|                 reply.headers[1].name = "Content-Type"; | ||||
|                 reply.headers[1].value = "text/javascript"; | ||||
|                 reply.headers[2].name = "Content-Disposition"; | ||||
|  | ||||
							
								
								
									
										59
									
								
								Server/APIGrammar.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								Server/APIGrammar.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,59 @@ | ||||
| /*
 | ||||
|     open source routing machine | ||||
|     Copyright (C) Dennis Luxen, others 2010 | ||||
| 
 | ||||
| This program is free software; you can redistribute it and/or modify | ||||
| it under the terms of the GNU AFFERO General Public License as published by | ||||
| the Free Software Foundation; either version 3 of the License, or | ||||
| any later version. | ||||
| 
 | ||||
| This program is distributed in the hope that it will be useful, | ||||
| but WITHOUT ANY WARRANTY; without even the implied warranty of | ||||
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||||
| GNU General Public License for more details. | ||||
| 
 | ||||
| You should have received a copy of the GNU Affero General Public License | ||||
| along with this program; if not, write to the Free Software | ||||
| Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA | ||||
| or see http://www.gnu.org/licenses/agpl.txt.
 | ||||
|  */ | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| #ifndef APIGRAMMAR_H_ | ||||
| #define APIGRAMMAR_H_ | ||||
| 
 | ||||
| #include <boost/bind.hpp> | ||||
| #include <boost/spirit/include/qi.hpp> | ||||
| #include <boost/spirit/include/qi_action.hpp> | ||||
| 
 | ||||
| namespace qi = boost::spirit::qi; | ||||
| 
 | ||||
| template <typename Iterator, class HandlerT> | ||||
| struct APIGrammar : qi::grammar<Iterator> { | ||||
|     APIGrammar(HandlerT * h) : APIGrammar::base_type(api_call), handler(h) { | ||||
|         api_call = qi::lit('/') >> string[boost::bind(&HandlerT::printService, handler, ::_1)] >> ('?') >> query; | ||||
|         query    = (*(zoom | output | jsonp | checksum | location | hint | compressed_geometry | language | instruction) ) ; | ||||
| 
 | ||||
|         zoom        = (-qi::lit('&')) >> qi::lit('z')            >> '=' >> qi::short_[boost::bind(&HandlerT::setZoomLevel, handler, ::_1)]; | ||||
|         output      = (-qi::lit('&')) >> qi::lit("output")       >> '=' >> string[boost::bind(&HandlerT::setOutputFormat, handler, ::_1)]; | ||||
|         jsonp       = (-qi::lit('&')) >> qi::lit("jsonp")        >> '=' >> stringwithDot[boost::bind(&HandlerT::setJSONpParameter, handler, ::_1)]; | ||||
|         checksum    = (-qi::lit('&')) >> qi::lit("checksum")     >> '=' >> qi::int_[boost::bind(&HandlerT::setChecksum, handler, ::_1)]; | ||||
|         instruction = (-qi::lit('&')) >> qi::lit("instructions") >> '=' >> qi::bool_[boost::bind(&HandlerT::setInstructionFlag, handler, ::_1)]; | ||||
|         geometry    = (-qi::lit('&')) >> qi::lit("geometry")     >> '=' >> qi::bool_[boost::bind(&HandlerT::setGeometryFlag, handler, ::_1)]; | ||||
|         cmp         = (-qi::lit('&')) >> qi::lit("compression")  >> '=' >> qi::bool_[boost::bind(&HandlerT::setCompressionFlag, handler, ::_1)]; | ||||
|         location    = (-qi::lit('&')) >> qi::lit("loc")          >> '=' >> (qi::double_ >> qi::lit(',') >> qi::double_)[boost::bind(&HandlerT::addCoordinate, handler, ::_1)]; | ||||
|         hint        = (-qi::lit('&')) >> qi::lit("hint")         >> '=' >> stringwithDot[boost::bind(&HandlerT::addHint, handler, ::_1)]; | ||||
|         language    = (-qi::lit('&')) >> qi::lit("hl")           >> '=' >> string[boost::bind(&HandlerT::setLanguage, handler, ::_1)]; | ||||
| 
 | ||||
|         string        = +(qi::char_("a-zA-Z")); | ||||
|         stringwithDot = +(qi::char_("a-zA-Z0-9_.-")); | ||||
|     } | ||||
|     qi::rule<Iterator> api_call, query; | ||||
|     qi::rule<Iterator, std::string()> service, zoom, output, string, jsonp, checksum, location, hint, compressed_geometry, stringwithDot, language, instruction, geometry, cmp; | ||||
| 
 | ||||
|     HandlerT * handler; | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
| #endif /* APIGRAMMAR_H_ */ | ||||
| @ -28,6 +28,7 @@ or see http://www.gnu.org/licenses/agpl.txt. | ||||
| #include <boost/lexical_cast.hpp> | ||||
| #include <boost/noncopyable.hpp> | ||||
| 
 | ||||
| #include "APIGrammar.h" | ||||
| #include "BasicDatastructures.h" | ||||
| #include "../DataStructures/HashTable.h" | ||||
| #include "../Plugins/BasePlugin.h" | ||||
| @ -51,56 +52,45 @@ public: | ||||
|     void handle_request(const Request& req, Reply& rep){ | ||||
|         //parse command
 | ||||
|         std::string request(req.uri); | ||||
|         time_t ltime; | ||||
|         struct tm *Tm; | ||||
| 
 | ||||
|         ltime=time(NULL); | ||||
|         Tm=localtime(<ime); | ||||
|         { //This block logs the current request to std out. should be moved to a logging component
 | ||||
|             time_t ltime; | ||||
|             struct tm *Tm; | ||||
| 
 | ||||
|         INFO((Tm->tm_mday < 10 ? "0" : "" )  << Tm->tm_mday << "-" << (Tm->tm_mon+1 < 10 ? "0" : "" )  << (Tm->tm_mon+1) << "-" << 1900+Tm->tm_year << " " << (Tm->tm_hour < 10 ? "0" : "" ) << Tm->tm_hour << ":" << (Tm->tm_min < 10 ? "0" : "" ) << Tm->tm_min << ":" << (Tm->tm_sec < 10 ? "0" : "" ) << Tm->tm_sec << " " << | ||||
|                 req.endpoint.to_string() << " " << req.referrer << ( 0 == req.referrer.length() ? "- " :" ") << req.agent << ( 0 == req.agent.length() ? "- " :" ") << request ); | ||||
|         std::size_t firstAmpPosition = request.find_first_of("?"); | ||||
|         //DEBUG("[debug] looking for handler for command: " << command);
 | ||||
|             ltime=time(NULL); | ||||
|             Tm=localtime(<ime); | ||||
| 
 | ||||
|             INFO((Tm->tm_mday < 10 ? "0" : "" )  << Tm->tm_mday << "-" << (Tm->tm_mon+1 < 10 ? "0" : "" )  << (Tm->tm_mon+1) << "-" << 1900+Tm->tm_year << " " << (Tm->tm_hour < 10 ? "0" : "" ) << Tm->tm_hour << ":" << (Tm->tm_min < 10 ? "0" : "" ) << Tm->tm_min << ":" << (Tm->tm_sec < 10 ? "0" : "" ) << Tm->tm_sec << " " << | ||||
|                     req.endpoint.to_string() << " " << req.referrer << ( 0 == req.referrer.length() ? "- " :" ") << req.agent << ( 0 == req.agent.length() ? "- " :" ") << req.uri ); | ||||
|         } | ||||
|         try { | ||||
|             std::string command = request.substr(1,firstAmpPosition-1); | ||||
|             if(pluginMap.Holds(command)) { | ||||
|             RouteParameters routeParameters; | ||||
|             APIGrammar<std::string::iterator, RouteParameters> apiParser(&routeParameters); | ||||
| 
 | ||||
|                 RouteParameters routeParameters; | ||||
|                 std::stringstream ss(( firstAmpPosition == std::string::npos ? "" : request.substr(firstAmpPosition+1) )); | ||||
|                 std::string item; | ||||
|                 while(std::getline(ss, item, '&')) { | ||||
|                     size_t found = item.find('='); | ||||
|                     if(found == std::string::npos) { | ||||
|                         routeParameters.parameters.push_back(item); | ||||
|                     } else { | ||||
|                         std::string p = item.substr(0, found); | ||||
|                         std::transform(p.begin(), p.end(), p.begin(), (int(*)(int)) std::tolower); | ||||
|                         std::string o = item.substr(found+1); | ||||
|                         if("jsonp" != p && "hint" != p) | ||||
|                             std::transform(o.begin(), o.end(), o.begin(), (int(*)(int)) std::tolower); | ||||
|                         if("loc" == p) { | ||||
|                             if(25 >= routeParameters.viaPoints.size()) { | ||||
|                                 routeParameters.viaPoints.push_back(o); | ||||
|                             } | ||||
|                         } else if("hint" == p) { | ||||
|                             routeParameters.hints.resize(routeParameters.viaPoints.size()); | ||||
|                             if(routeParameters.viaPoints.size()) | ||||
|                                 routeParameters.hints.back() = o; | ||||
|                         } else { | ||||
|                             routeParameters.options.Set(p, o); | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|                 //				std::cout << "[debug] found handler for '" << command << "' at version: " << pluginMap.Find(command)->GetVersionString() << std::endl;
 | ||||
|                 //				std::cout << "[debug] remaining parameters: " << parameters.size() << std::endl;
 | ||||
|                 rep.status = Reply::ok; | ||||
|                 _pluginVector[pluginMap.Find(command)]->HandleRequest(routeParameters, rep ); | ||||
| 
 | ||||
|                 //				std::cout << rep.content << std::endl;
 | ||||
|             std::string::iterator it = request.begin(); | ||||
|             bool result = boost::spirit::qi::parse(it, request.end(), apiParser);    // returns true if successful
 | ||||
|             if (!result || (it != request.end()) ) { | ||||
|                 rep = http::Reply::stockReply(http::Reply::badRequest); | ||||
|                 std::stringstream content; | ||||
|                 int position = std::distance(request.begin(), it); | ||||
|                 content << "Input seems to be malformed close to position " << position << "<br>"; | ||||
|                 content << "<pre>"; | ||||
|                 content << req.uri << "<br>"; | ||||
|                 for(unsigned i = 0, end = std::distance(request.begin(), it); i < end; ++i) | ||||
|                     content << " "; | ||||
|                 content << "^" << "<br>"; | ||||
|                 content << "</pre>"; | ||||
|                 rep.content += content.str(); | ||||
|             } else { | ||||
|                 rep = Reply::stockReply(Reply::badRequest); | ||||
|                 //Finished parsing, lets call the right plugin to handle the request
 | ||||
|                 if(pluginMap.Holds(routeParameters.service)) { | ||||
|                     rep.status = Reply::ok; | ||||
|                     _pluginVector[pluginMap.Find(routeParameters.service)]->HandleRequest(routeParameters, rep ); | ||||
|                 } else { | ||||
|                     rep = Reply::stockReply(Reply::badRequest); | ||||
|                 } | ||||
|                 return; | ||||
|             } | ||||
|             return; | ||||
|         } catch(std::exception& e) { | ||||
|             rep = Reply::stockReply(Reply::internalServerError); | ||||
|             std::cerr << "[server error] code: " << e.what() << ", uri: " << req.uri << std::endl; | ||||
| @ -112,7 +102,7 @@ public: | ||||
|         std::cout << "[handler] registering plugin " << plugin->GetDescriptor() << std::endl; | ||||
|         pluginMap.Add(plugin->GetDescriptor(), _pluginCount); | ||||
|         _pluginVector.push_back(plugin); | ||||
|         _pluginCount++; | ||||
|         ++_pluginCount; | ||||
|     } | ||||
| 
 | ||||
| private: | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user