mirror of
https://github.com/CrowCpp/Crow.git
synced 2024-06-07 21:10:44 +00:00
fix #27 : handling routes with trailing slash
This commit is contained in:
parent
b5942c4dda
commit
07042b55fd
File diff suppressed because it is too large
Load Diff
@ -56,6 +56,12 @@ int main()
|
|||||||
return "About Crow example.";
|
return "About Crow example.";
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// a request to /path should be forwarded to /path/
|
||||||
|
CROW_ROUTE(app, "/path/")
|
||||||
|
([](){
|
||||||
|
return "Trailing slash test case..";
|
||||||
|
});
|
||||||
|
|
||||||
// simple json response
|
// simple json response
|
||||||
CROW_ROUTE(app, "/json")
|
CROW_ROUTE(app, "/json")
|
||||||
([]{
|
([]{
|
||||||
|
@ -276,6 +276,8 @@ namespace crow
|
|||||||
friend class Router;
|
friend class Router;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const int RULE_SPECIAL_REDIRECT_SLASH = 1;
|
||||||
|
|
||||||
class Trie
|
class Trie
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -607,14 +609,28 @@ public:
|
|||||||
class Router
|
class Router
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Router() : rules_(1) {}
|
Router() : rules_(2)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
template <uint64_t N>
|
template <uint64_t N>
|
||||||
typename black_magic::arguments<N>::type::template rebind<TaggedRule>& new_rule_tagged(const std::string& rule)
|
typename black_magic::arguments<N>::type::template rebind<TaggedRule>& new_rule_tagged(const std::string& rule)
|
||||||
{
|
{
|
||||||
using RuleT = typename black_magic::arguments<N>::type::template rebind<TaggedRule>;
|
using RuleT = typename black_magic::arguments<N>::type::template rebind<TaggedRule>;
|
||||||
auto ruleObject = new RuleT(rule);
|
auto ruleObject = new RuleT(rule);
|
||||||
rules_.emplace_back(ruleObject);
|
rules_.emplace_back(ruleObject);
|
||||||
|
|
||||||
trie_.add(rule, rules_.size() - 1);
|
trie_.add(rule, rules_.size() - 1);
|
||||||
|
|
||||||
|
// directory case:
|
||||||
|
// request to `/about' url matches `/about/' rule
|
||||||
|
if (rule.size() > 1 && rule.back() == '/')
|
||||||
|
{
|
||||||
|
std::string rule_without_trailing_slash = rule;
|
||||||
|
rule_without_trailing_slash.pop_back();
|
||||||
|
trie_.add(rule_without_trailing_slash, RULE_SPECIAL_REDIRECT_SLASH);
|
||||||
|
}
|
||||||
|
|
||||||
return *ruleObject;
|
return *ruleObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -633,6 +649,7 @@ public:
|
|||||||
auto found = trie_.find(req.url);
|
auto found = trie_.find(req.url);
|
||||||
|
|
||||||
unsigned rule_index = found.first;
|
unsigned rule_index = found.first;
|
||||||
|
CROW_LOG_DEBUG << "???" << rule_index;
|
||||||
|
|
||||||
if (!rule_index)
|
if (!rule_index)
|
||||||
{
|
{
|
||||||
@ -645,6 +662,24 @@ public:
|
|||||||
if (rule_index >= rules_.size())
|
if (rule_index >= rules_.size())
|
||||||
throw std::runtime_error("Trie internal structure corrupted!");
|
throw std::runtime_error("Trie internal structure corrupted!");
|
||||||
|
|
||||||
|
if (rule_index == RULE_SPECIAL_REDIRECT_SLASH)
|
||||||
|
{
|
||||||
|
CROW_LOG_INFO << "Redirecting to a url with trailing slash: " << req.url;
|
||||||
|
res = response(301);
|
||||||
|
|
||||||
|
// TODO absolute url building
|
||||||
|
if (req.get_header_value("Host").empty())
|
||||||
|
{
|
||||||
|
res.add_header("Location", req.url + "/");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
res.add_header("Location", "http://" + req.get_header_value("Host") + req.url + "/");
|
||||||
|
}
|
||||||
|
res.end();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if ((rules_[rule_index]->methods() & (1<<(uint32_t)req.method)) == 0)
|
if ((rules_[rule_index]->methods() & (1<<(uint32_t)req.method)) == 0)
|
||||||
{
|
{
|
||||||
CROW_LOG_DEBUG << "Rule found but method mismatch: " << req.url << " with " << method_name(req.method) << "(" << (uint32_t)req.method << ") / " << rules_[rule_index]->methods();
|
CROW_LOG_DEBUG << "Rule found but method mismatch: " << req.url << " with " << method_name(req.method) << "(" << (uint32_t)req.method << ") / " << rules_[rule_index]->methods();
|
||||||
|
@ -116,6 +116,59 @@ TEST(ParameterTagging)
|
|||||||
static_assert(std::is_same<black_magic::S<uint64_t, double, int64_t>, black_magic::arguments<6*6+6*3+2>::type>::value, "tag to type container");
|
static_assert(std::is_same<black_magic::S<uint64_t, double, int64_t>, black_magic::arguments<6*6+6*3+2>::type>::value, "tag to type container");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(PathRouting)
|
||||||
|
{
|
||||||
|
SimpleApp app;
|
||||||
|
|
||||||
|
CROW_ROUTE(app, "/file")
|
||||||
|
([]{
|
||||||
|
return "file";
|
||||||
|
});
|
||||||
|
|
||||||
|
CROW_ROUTE(app, "/path/")
|
||||||
|
([]{
|
||||||
|
return "path";
|
||||||
|
});
|
||||||
|
|
||||||
|
{
|
||||||
|
request req;
|
||||||
|
response res;
|
||||||
|
|
||||||
|
req.url = "/file";
|
||||||
|
|
||||||
|
app.handle(req, res);
|
||||||
|
|
||||||
|
ASSERT_EQUAL(200, res.code);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
request req;
|
||||||
|
response res;
|
||||||
|
|
||||||
|
req.url = "/file/";
|
||||||
|
|
||||||
|
app.handle(req, res);
|
||||||
|
ASSERT_EQUAL(404, res.code);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
request req;
|
||||||
|
response res;
|
||||||
|
|
||||||
|
req.url = "/path";
|
||||||
|
|
||||||
|
app.handle(req, res);
|
||||||
|
ASSERT_NOTEQUAL(404, res.code);
|
||||||
|
}
|
||||||
|
{
|
||||||
|
request req;
|
||||||
|
response res;
|
||||||
|
|
||||||
|
req.url = "/path/";
|
||||||
|
|
||||||
|
app.handle(req, res);
|
||||||
|
ASSERT_EQUAL(200, res.code);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
TEST(RoutingTest)
|
TEST(RoutingTest)
|
||||||
{
|
{
|
||||||
SimpleApp app;
|
SimpleApp app;
|
||||||
|
Loading…
Reference in New Issue
Block a user