routing.hpp (f23b729676559f539790580930b1ff3b0c05805b) routing.hpp (81ce609e30274435b4f8c3fc65340c6b6b153b0c)
1#pragma once
2
3#include "common.hpp"
4#include "error_messages.hpp"
5#include "http_request.hpp"
6#include "http_response.hpp"
7#include "logging.hpp"
8#include "privileges.hpp"

--- 403 unchanged lines hidden (view full) ---

412 self_t& methods(boost::beast::http::verb method)
413 {
414 self_t* self = static_cast<self_t*>(this);
415 self->methodsBitfield = 1U << static_cast<size_t>(method);
416 return *self;
417 }
418
419 template <typename... MethodArgs>
1#pragma once
2
3#include "common.hpp"
4#include "error_messages.hpp"
5#include "http_request.hpp"
6#include "http_response.hpp"
7#include "logging.hpp"
8#include "privileges.hpp"

--- 403 unchanged lines hidden (view full) ---

412 self_t& methods(boost::beast::http::verb method)
413 {
414 self_t* self = static_cast<self_t*>(this);
415 self->methodsBitfield = 1U << static_cast<size_t>(method);
416 return *self;
417 }
418
419 template <typename... MethodArgs>
420 self_t& methods(boost::beast::http::verb method, MethodArgs... args_method)
420 self_t& methods(boost::beast::http::verb method, MethodArgs... argsMethod)
421 {
422 self_t* self = static_cast<self_t*>(this);
421 {
422 self_t* self = static_cast<self_t*>(this);
423 methods(args_method...);
423 methods(argsMethod...);
424 self->methodsBitfield |= 1U << static_cast<size_t>(method);
425 return *self;
426 }
427
428 template <typename... MethodArgs>
429 self_t& privileges(std::initializer_list<const char*> l)
430 {
431 self_t* self = static_cast<self_t*>(this);

--- 285 unchanged lines hidden (view full) ---

717 if (!head()->isSimpleNode())
718 {
719 throw std::runtime_error(
720 "Internal error: Trie header should be simple!");
721 }
722 optimize();
723 }
724
424 self->methodsBitfield |= 1U << static_cast<size_t>(method);
425 return *self;
426 }
427
428 template <typename... MethodArgs>
429 self_t& privileges(std::initializer_list<const char*> l)
430 {
431 self_t* self = static_cast<self_t*>(this);

--- 285 unchanged lines hidden (view full) ---

717 if (!head()->isSimpleNode())
718 {
719 throw std::runtime_error(
720 "Internal error: Trie header should be simple!");
721 }
722 optimize();
723 }
724
725 void findRouteIndexes(const std::string& req_url,
726 std::vector<unsigned>& route_indexes,
725 void findRouteIndexes(const std::string& reqUrl,
726 std::vector<unsigned>& routeIndexes,
727 const Node* node = nullptr, unsigned pos = 0) const
728 {
729 if (node == nullptr)
730 {
731 node = head();
732 }
733 for (const std::pair<std::string, unsigned>& kv : node->children)
734 {
735 const std::string& fragment = kv.first;
736 const Node* child = &nodes[kv.second];
727 const Node* node = nullptr, unsigned pos = 0) const
728 {
729 if (node == nullptr)
730 {
731 node = head();
732 }
733 for (const std::pair<std::string, unsigned>& kv : node->children)
734 {
735 const std::string& fragment = kv.first;
736 const Node* child = &nodes[kv.second];
737 if (pos >= req_url.size())
737 if (pos >= reqUrl.size())
738 {
739 if (child->ruleIndex != 0 && fragment != "/")
740 {
738 {
739 if (child->ruleIndex != 0 && fragment != "/")
740 {
741 route_indexes.push_back(child->ruleIndex);
741 routeIndexes.push_back(child->ruleIndex);
742 }
742 }
743 findRouteIndexes(req_url, route_indexes, child,
743 findRouteIndexes(reqUrl, routeIndexes, child,
744 static_cast<unsigned>(pos + fragment.size()));
745 }
746 else
747 {
744 static_cast<unsigned>(pos + fragment.size()));
745 }
746 else
747 {
748 if (req_url.compare(pos, fragment.size(), fragment) == 0)
748 if (reqUrl.compare(pos, fragment.size(), fragment) == 0)
749 {
750 findRouteIndexes(
749 {
750 findRouteIndexes(
751 req_url, route_indexes, child,
751 reqUrl, routeIndexes, child,
752 static_cast<unsigned>(pos + fragment.size()));
753 }
754 }
755 }
756 }
757
758 std::pair<unsigned, RoutingParams>
752 static_cast<unsigned>(pos + fragment.size()));
753 }
754 }
755 }
756 }
757
758 std::pair<unsigned, RoutingParams>
759 find(const std::string_view req_url, const Node* node = nullptr,
759 find(const std::string_view reqUrl, const Node* node = nullptr,
760 size_t pos = 0, RoutingParams* params = nullptr) const
761 {
762 RoutingParams empty;
763 if (params == nullptr)
764 {
765 params = &empty;
766 }
767
768 unsigned found{};
769 RoutingParams matchParams;
770
771 if (node == nullptr)
772 {
773 node = head();
774 }
760 size_t pos = 0, RoutingParams* params = nullptr) const
761 {
762 RoutingParams empty;
763 if (params == nullptr)
764 {
765 params = &empty;
766 }
767
768 unsigned found{};
769 RoutingParams matchParams;
770
771 if (node == nullptr)
772 {
773 node = head();
774 }
775 if (pos == req_url.size())
775 if (pos == reqUrl.size())
776 {
777 return {node->ruleIndex, *params};
778 }
779
780 auto updateFound =
781 [&found, &matchParams](std::pair<unsigned, RoutingParams>& ret) {
782 if (ret.first && (!found || found > ret.first))
783 {
784 found = ret.first;
785 matchParams = std::move(ret.second);
786 }
787 };
788
789 if (node->paramChildrens[static_cast<size_t>(ParamType::INT)])
790 {
776 {
777 return {node->ruleIndex, *params};
778 }
779
780 auto updateFound =
781 [&found, &matchParams](std::pair<unsigned, RoutingParams>& ret) {
782 if (ret.first && (!found || found > ret.first))
783 {
784 found = ret.first;
785 matchParams = std::move(ret.second);
786 }
787 };
788
789 if (node->paramChildrens[static_cast<size_t>(ParamType::INT)])
790 {
791 char c = req_url[pos];
791 char c = reqUrl[pos];
792 if ((c >= '0' && c <= '9') || c == '+' || c == '-')
793 {
794 char* eptr;
795 errno = 0;
796 long long int value =
792 if ((c >= '0' && c <= '9') || c == '+' || c == '-')
793 {
794 char* eptr;
795 errno = 0;
796 long long int value =
797 std::strtoll(req_url.data() + pos, &eptr, 10);
798 if (errno != ERANGE && eptr != req_url.data() + pos)
797 std::strtoll(reqUrl.data() + pos, &eptr, 10);
798 if (errno != ERANGE && eptr != reqUrl.data() + pos)
799 {
800 params->intParams.push_back(value);
799 {
800 params->intParams.push_back(value);
801 std::pair<unsigned, RoutingParams> ret = find(
802 req_url,
803 &nodes[node->paramChildrens[static_cast<size_t>(
804 ParamType::INT)]],
805 static_cast<size_t>(eptr - req_url.data()), params);
801 std::pair<unsigned, RoutingParams> ret =
802 find(reqUrl,
803 &nodes[node->paramChildrens[static_cast<size_t>(
804 ParamType::INT)]],
805 static_cast<size_t>(eptr - reqUrl.data()), params);
806 updateFound(ret);
807 params->intParams.pop_back();
808 }
809 }
810 }
811
812 if (node->paramChildrens[static_cast<size_t>(ParamType::UINT)])
813 {
806 updateFound(ret);
807 params->intParams.pop_back();
808 }
809 }
810 }
811
812 if (node->paramChildrens[static_cast<size_t>(ParamType::UINT)])
813 {
814 char c = req_url[pos];
814 char c = reqUrl[pos];
815 if ((c >= '0' && c <= '9') || c == '+')
816 {
817 char* eptr;
818 errno = 0;
819 unsigned long long int value =
815 if ((c >= '0' && c <= '9') || c == '+')
816 {
817 char* eptr;
818 errno = 0;
819 unsigned long long int value =
820 std::strtoull(req_url.data() + pos, &eptr, 10);
821 if (errno != ERANGE && eptr != req_url.data() + pos)
820 std::strtoull(reqUrl.data() + pos, &eptr, 10);
821 if (errno != ERANGE && eptr != reqUrl.data() + pos)
822 {
823 params->uintParams.push_back(value);
822 {
823 params->uintParams.push_back(value);
824 std::pair<unsigned, RoutingParams> ret = find(
825 req_url,
826 &nodes[node->paramChildrens[static_cast<size_t>(
827 ParamType::UINT)]],
828 static_cast<size_t>(eptr - req_url.data()), params);
824 std::pair<unsigned, RoutingParams> ret =
825 find(reqUrl,
826 &nodes[node->paramChildrens[static_cast<size_t>(
827 ParamType::UINT)]],
828 static_cast<size_t>(eptr - reqUrl.data()), params);
829 updateFound(ret);
830 params->uintParams.pop_back();
831 }
832 }
833 }
834
835 if (node->paramChildrens[static_cast<size_t>(ParamType::DOUBLE)])
836 {
829 updateFound(ret);
830 params->uintParams.pop_back();
831 }
832 }
833 }
834
835 if (node->paramChildrens[static_cast<size_t>(ParamType::DOUBLE)])
836 {
837 char c = req_url[pos];
837 char c = reqUrl[pos];
838 if ((c >= '0' && c <= '9') || c == '+' || c == '-' || c == '.')
839 {
840 char* eptr;
841 errno = 0;
838 if ((c >= '0' && c <= '9') || c == '+' || c == '-' || c == '.')
839 {
840 char* eptr;
841 errno = 0;
842 double value = std::strtod(req_url.data() + pos, &eptr);
843 if (errno != ERANGE && eptr != req_url.data() + pos)
842 double value = std::strtod(reqUrl.data() + pos, &eptr);
843 if (errno != ERANGE && eptr != reqUrl.data() + pos)
844 {
845 params->doubleParams.push_back(value);
844 {
845 params->doubleParams.push_back(value);
846 std::pair<unsigned, RoutingParams> ret = find(
847 req_url,
848 &nodes[node->paramChildrens[static_cast<size_t>(
849 ParamType::DOUBLE)]],
850 static_cast<size_t>(eptr - req_url.data()), params);
846 std::pair<unsigned, RoutingParams> ret =
847 find(reqUrl,
848 &nodes[node->paramChildrens[static_cast<size_t>(
849 ParamType::DOUBLE)]],
850 static_cast<size_t>(eptr - reqUrl.data()), params);
851 updateFound(ret);
852 params->doubleParams.pop_back();
853 }
854 }
855 }
856
857 if (node->paramChildrens[static_cast<size_t>(ParamType::STRING)])
858 {
859 size_t epos = pos;
851 updateFound(ret);
852 params->doubleParams.pop_back();
853 }
854 }
855 }
856
857 if (node->paramChildrens[static_cast<size_t>(ParamType::STRING)])
858 {
859 size_t epos = pos;
860 for (; epos < req_url.size(); epos++)
860 for (; epos < reqUrl.size(); epos++)
861 {
861 {
862 if (req_url[epos] == '/')
862 if (reqUrl[epos] == '/')
863 {
864 break;
865 }
866 }
867
868 if (epos != pos)
869 {
870 params->stringParams.emplace_back(
863 {
864 break;
865 }
866 }
867
868 if (epos != pos)
869 {
870 params->stringParams.emplace_back(
871 req_url.substr(pos, epos - pos));
871 reqUrl.substr(pos, epos - pos));
872 std::pair<unsigned, RoutingParams> ret =
872 std::pair<unsigned, RoutingParams> ret =
873 find(req_url,
873 find(reqUrl,
874 &nodes[node->paramChildrens[static_cast<size_t>(
875 ParamType::STRING)]],
876 epos, params);
877 updateFound(ret);
878 params->stringParams.pop_back();
879 }
880 }
881
882 if (node->paramChildrens[static_cast<size_t>(ParamType::PATH)])
883 {
874 &nodes[node->paramChildrens[static_cast<size_t>(
875 ParamType::STRING)]],
876 epos, params);
877 updateFound(ret);
878 params->stringParams.pop_back();
879 }
880 }
881
882 if (node->paramChildrens[static_cast<size_t>(ParamType::PATH)])
883 {
884 size_t epos = req_url.size();
884 size_t epos = reqUrl.size();
885
886 if (epos != pos)
887 {
888 params->stringParams.emplace_back(
885
886 if (epos != pos)
887 {
888 params->stringParams.emplace_back(
889 req_url.substr(pos, epos - pos));
889 reqUrl.substr(pos, epos - pos));
890 std::pair<unsigned, RoutingParams> ret =
890 std::pair<unsigned, RoutingParams> ret =
891 find(req_url,
891 find(reqUrl,
892 &nodes[node->paramChildrens[static_cast<size_t>(
893 ParamType::PATH)]],
894 epos, params);
895 updateFound(ret);
896 params->stringParams.pop_back();
897 }
898 }
899
900 for (const std::pair<std::string, unsigned>& kv : node->children)
901 {
902 const std::string& fragment = kv.first;
903 const Node* child = &nodes[kv.second];
904
892 &nodes[node->paramChildrens[static_cast<size_t>(
893 ParamType::PATH)]],
894 epos, params);
895 updateFound(ret);
896 params->stringParams.pop_back();
897 }
898 }
899
900 for (const std::pair<std::string, unsigned>& kv : node->children)
901 {
902 const std::string& fragment = kv.first;
903 const Node* child = &nodes[kv.second];
904
905 if (req_url.compare(pos, fragment.size(), fragment) == 0)
905 if (reqUrl.compare(pos, fragment.size(), fragment) == 0)
906 {
907 std::pair<unsigned, RoutingParams> ret =
906 {
907 std::pair<unsigned, RoutingParams> ret =
908 find(req_url, child, pos + fragment.size(), params);
908 find(reqUrl, child, pos + fragment.size(), params);
909 updateFound(ret);
910 }
911 }
912
913 return {found, matchParams};
914 }
915
916 void add(const std::string& url, unsigned ruleIndex)

--- 537 unchanged lines hidden ---
909 updateFound(ret);
910 }
911 }
912
913 return {found, matchParams};
914 }
915
916 void add(const std::string& url, unsigned ruleIndex)

--- 537 unchanged lines hidden ---