#include "server/api/url_parser.hpp" #include "engine/polyline_compressor.hpp" #include #include #include #include #include #include BOOST_FUSION_ADAPT_STRUCT(osrm::server::api::ParsedURL, (std::string, service)(unsigned, version)(std::string, profile)(std::string, query)) // Keep impl. TU local namespace { namespace ph = boost::phoenix; namespace qi = boost::spirit::qi; template // struct URLParser final : qi::grammar { URLParser() : URLParser::base_type(start) { using boost::spirit::repository::qi::iter_pos; identifier = qi::char_("a-zA-Z0-9_.~:-"); percent_encoding = qi::char_('%') > qi::uint_parser()[qi::_val = qi::_1]; polyline_chars = qi::char_("a-zA-Z0-9_[]{}@?|\\~`^") | percent_encoding; all_chars = polyline_chars | qi::char_("=,;:&().-"); service = +identifier; version = qi::uint_; profile = +identifier; query = +all_chars; // Example input: /route/v1/driving/7.416351,43.731205;7.420363,43.736189 start = qi::lit('/') > service > qi::lit('/') > qi::lit('v') > version > qi::lit('/') > profile > qi::lit('/') > qi::omit[iter_pos[ph::bind(&osrm::server::api::ParsedURL::prefix_length, qi::_val) = qi::_1 - qi::_r1]] > query; BOOST_SPIRIT_DEBUG_NODES((start)(service)(version)(profile)(query)) } qi::rule start; qi::rule service; qi::rule version; qi::rule profile; qi::rule query; qi::rule identifier; qi::rule all_chars; qi::rule polyline_chars; qi::rule percent_encoding; }; } // namespace namespace osrm::server::api { std::optional parseURL(std::string::iterator &iter, const std::string::iterator end) { using It = std::decay::type; static URLParser const parser; ParsedURL out; try { const auto ok = boost::spirit::qi::parse(iter, end, parser(boost::phoenix::val(iter)), out); if (ok && iter == end) return std::make_optional(out); } catch (const qi::expectation_failure &failure) { // The grammar above using expectation parsers ">" does not automatically increment the // iterator to the failing position. Extract the position from the exception ourselves. iter = failure.first; } return std::nullopt; } } // namespace osrm::server::api