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.";
|
||||
});
|
||||
|
||||
// a request to /path should be forwarded to /path/
|
||||
CROW_ROUTE(app, "/path/")
|
||||
([](){
|
||||
return "Trailing slash test case..";
|
||||
});
|
||||
|
||||
// simple json response
|
||||
CROW_ROUTE(app, "/json")
|
||||
([]{
|
||||
|
@ -276,6 +276,8 @@ namespace crow
|
||||
friend class Router;
|
||||
};
|
||||
|
||||
const int RULE_SPECIAL_REDIRECT_SLASH = 1;
|
||||
|
||||
class Trie
|
||||
{
|
||||
public:
|
||||
@ -607,14 +609,28 @@ public:
|
||||
class Router
|
||||
{
|
||||
public:
|
||||
Router() : rules_(1) {}
|
||||
Router() : rules_(2)
|
||||
{
|
||||
}
|
||||
|
||||
template <uint64_t N>
|
||||
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>;
|
||||
auto ruleObject = new RuleT(rule);
|
||||
rules_.emplace_back(ruleObject);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
@ -633,6 +649,7 @@ public:
|
||||
auto found = trie_.find(req.url);
|
||||
|
||||
unsigned rule_index = found.first;
|
||||
CROW_LOG_DEBUG << "???" << rule_index;
|
||||
|
||||
if (!rule_index)
|
||||
{
|
||||
@ -645,6 +662,24 @@ public:
|
||||
if (rule_index >= rules_.size())
|
||||
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)
|
||||
{
|
||||
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");
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
SimpleApp app;
|
||||
|
Loading…
Reference in New Issue
Block a user