mirror of
https://github.com/CrowCpp/Crow.git
synced 2024-06-07 21:10:44 +00:00
long polling implementation complete
change `res handle(req)' into `void handle(req, res)' connnection::handle is divide into two part: before and after user handler
This commit is contained in:
parent
88cc6079cb
commit
a0c93f5b84
8
Makefile
8
Makefile
@ -8,9 +8,13 @@ FLAGS_DEBUG = -g
|
||||
FLAGS_GCOV = -r
|
||||
endif
|
||||
|
||||
binaries=covtest example
|
||||
binaries=covtest example example_chat
|
||||
|
||||
all: covtest example example_chat
|
||||
|
||||
example_chat: example_chat.cpp settings.h crow.h http_server.h http_connection.h parser.h http_response.h routing.h common.h utility.h json.h datetime.h logging.h mustache.h
|
||||
${CXX} -Wall $(FLAGS_DEBUG) -std=c++1y -o example_chat example_chat.cpp http-parser/http_parser.c -pthread -lboost_system $(FLAGS_BOOST_THREAD) -I http-parser/
|
||||
|
||||
all: covtest example
|
||||
|
||||
example: example.cpp settings.h crow.h http_server.h http_connection.h parser.h http_response.h routing.h common.h utility.h json.h datetime.h logging.h mustache.h
|
||||
${CXX} -Wall $(FLAGS_DEBUG) -O3 -std=c++1y -o example example.cpp http-parser/http_parser.c -pthread -lboost_system $(FLAGS_BOOST_THREAD) -ltcmalloc_minimal -I http-parser/
|
||||
|
5
crow.h
5
crow.h
@ -29,9 +29,9 @@ namespace crow
|
||||
{
|
||||
}
|
||||
|
||||
response handle(const request& req)
|
||||
void handle(const request& req, response& res)
|
||||
{
|
||||
return router_.handle(req);
|
||||
return router_.handle(req, res);
|
||||
}
|
||||
|
||||
template <uint64_t Tag>
|
||||
@ -84,5 +84,6 @@ namespace crow
|
||||
|
||||
Router router_;
|
||||
};
|
||||
using App = Crow;
|
||||
};
|
||||
|
||||
|
@ -46,7 +46,7 @@ int main()
|
||||
([](const crow::request& req, crow::response& res, int a, int b){
|
||||
std::ostringstream os;
|
||||
os << a+b;
|
||||
res.send(os.str());
|
||||
res.write(os.str());
|
||||
res.end();
|
||||
});
|
||||
|
||||
|
80
example_chat.cpp
Normal file
80
example_chat.cpp
Normal file
@ -0,0 +1,80 @@
|
||||
#include "crow.h"
|
||||
#include "json.h"
|
||||
#include "mustache.h"
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
using namespace std;
|
||||
|
||||
vector<string> msgs;
|
||||
vector<crow::response*> ress;
|
||||
|
||||
void broadcast(const string& msg)
|
||||
{
|
||||
msgs.push_back(msg);
|
||||
crow::json::wvalue x;
|
||||
x["msgs"][0] = msgs.back();
|
||||
x["last"] = msgs.size();
|
||||
string body = crow::json::dump(x);
|
||||
for(auto* res:ress)
|
||||
{
|
||||
CROW_LOG_DEBUG << res->p << " replied: " << body;
|
||||
res->end(body);
|
||||
}
|
||||
ress.clear();
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
crow::App app;
|
||||
crow::mustache::set_base(".");
|
||||
|
||||
CROW_ROUTE(app, "/")
|
||||
([]{
|
||||
crow::mustache::context ctx;
|
||||
return crow::mustache::load("example_chat.html").render();
|
||||
});
|
||||
|
||||
CROW_ROUTE(app, "/logs")
|
||||
([]{
|
||||
CROW_LOG_INFO << "logs requested";
|
||||
crow::json::wvalue x;
|
||||
for(int i = max(0, (int)msgs.size()-100); i < (int)msgs.size(); i++)
|
||||
x["msgs"][i] = msgs[i];
|
||||
x["last"] = msgs.size();
|
||||
CROW_LOG_INFO << "logs completed";
|
||||
return x;
|
||||
});
|
||||
|
||||
CROW_ROUTE(app, "/logs/<int>")
|
||||
([](const crow::request& req, crow::response& res, int after){
|
||||
CROW_LOG_INFO << "logs with last " << after;
|
||||
if (after < (int)msgs.size())
|
||||
{
|
||||
crow::json::wvalue x;
|
||||
for(int i = after; i < (int)msgs.size(); i ++)
|
||||
x["msgs"][i-after] = msgs[i];
|
||||
x["last"] = msgs.size();
|
||||
|
||||
res.write(crow::json::dump(x));
|
||||
res.end();
|
||||
}
|
||||
else
|
||||
{
|
||||
ress.push_back(&res);
|
||||
CROW_LOG_DEBUG << res.p << " stored";
|
||||
}
|
||||
});
|
||||
|
||||
CROW_ROUTE(app, "/send")
|
||||
([](const crow::request& req)
|
||||
{
|
||||
CROW_LOG_INFO << "msg from client: " << req.body;
|
||||
broadcast(req.body);
|
||||
return "";
|
||||
});
|
||||
|
||||
app.port(18080)
|
||||
//.multithreaded()
|
||||
.run();
|
||||
}
|
48
example_chat.html
Normal file
48
example_chat.html
Normal file
@ -0,0 +1,48 @@
|
||||
<html>
|
||||
<head>
|
||||
<script src="//code.jquery.com/jquery-1.11.0.min.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<input id="msg" type="text">
|
||||
<button id="send">Send</button>
|
||||
<div id="logs">
|
||||
</div>
|
||||
<script>
|
||||
$(document).ready(function(){
|
||||
$("#send").click(function(){
|
||||
var msg = $("#msg").val();
|
||||
console.log(msg);
|
||||
if (msg.length > 0)
|
||||
$.post("/send", msg);
|
||||
$("#msg").val("");
|
||||
});
|
||||
$("#msg").keyup(function(event){
|
||||
if(event.keyCode == 13){
|
||||
$("#send").click();
|
||||
}
|
||||
});
|
||||
var lastLog = 0;
|
||||
var updateLog;
|
||||
updateLog = function(data)
|
||||
{
|
||||
console.log("recv ");
|
||||
console.log(data);
|
||||
var lastLog = data.last*1;
|
||||
console.log("lastLog: " + lastLog);
|
||||
var s = "";
|
||||
for(var x in data.msgs)
|
||||
{
|
||||
s += data.msgs[x] + "<BR>";
|
||||
}
|
||||
$("#logs").html(s+$("#logs").html());
|
||||
var failFunction;
|
||||
failFunction = function(){
|
||||
$.getJSON("/logs/"+lastLog, updateLog).fail(failFunction);
|
||||
};
|
||||
$.getJSON("/logs/"+lastLog, updateLog).fail(failFunction);
|
||||
}
|
||||
$.getJSON("/logs", updateLog);
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -36,13 +36,15 @@ namespace crow
|
||||
CROW_LOG_DEBUG << "Connection open, total " << connectionCount << ", " << this;
|
||||
#endif
|
||||
}
|
||||
#ifdef CROW_ENABLE_DEBUG
|
||||
|
||||
~Connection()
|
||||
{
|
||||
res.complete_request_handler_ = nullptr;
|
||||
#ifdef CROW_ENABLE_DEBUG
|
||||
connectionCount --;
|
||||
CROW_LOG_DEBUG << "Connection closed, total " << connectionCount << ", " << this;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void start()
|
||||
{
|
||||
@ -66,28 +68,6 @@ namespace crow
|
||||
|
||||
void handle()
|
||||
{
|
||||
static std::unordered_map<int, std::string> statusCodes = {
|
||||
{200, "HTTP/1.1 200 OK\r\n"},
|
||||
{201, "HTTP/1.1 201 Created\r\n"},
|
||||
{202, "HTTP/1.1 202 Accepted\r\n"},
|
||||
{204, "HTTP/1.1 204 No Content\r\n"},
|
||||
|
||||
{300, "HTTP/1.1 300 Multiple Choices\r\n"},
|
||||
{301, "HTTP/1.1 301 Moved Permanently\r\n"},
|
||||
{302, "HTTP/1.1 302 Moved Temporarily\r\n"},
|
||||
{304, "HTTP/1.1 304 Not Modified\r\n"},
|
||||
|
||||
{400, "HTTP/1.1 400 Bad Request\r\n"},
|
||||
{401, "HTTP/1.1 401 Unauthorized\r\n"},
|
||||
{403, "HTTP/1.1 403 Forbidden\r\n"},
|
||||
{404, "HTTP/1.1 404 Not Found\r\n"},
|
||||
|
||||
{500, "HTTP/1.1 500 Internal Server Error\r\n"},
|
||||
{501, "HTTP/1.1 501 Not Implemented\r\n"},
|
||||
{502, "HTTP/1.1 502 Bad Gateway\r\n"},
|
||||
{503, "HTTP/1.1 503 Service Unavailable\r\n"},
|
||||
};
|
||||
|
||||
bool is_invalid_request = false;
|
||||
|
||||
request req = parser_.to_request();
|
||||
@ -109,14 +89,54 @@ namespace crow
|
||||
}
|
||||
}
|
||||
|
||||
CROW_LOG_INFO << "Request: "<< this << " HTTP/" << parser_.http_major << "." << parser_.http_minor << ' '
|
||||
<< method_name(req.method) << " " << req.url;
|
||||
|
||||
|
||||
if (!is_invalid_request)
|
||||
{
|
||||
res = handler_->handle(req);
|
||||
deadline_.cancel();
|
||||
auto self = this->shared_from_this();
|
||||
res.complete_request_handler_ = [self]{ self->complete_request(); };
|
||||
handler_->handle(req, res);
|
||||
}
|
||||
else
|
||||
{
|
||||
complete_request();
|
||||
}
|
||||
}
|
||||
|
||||
CROW_LOG_INFO << "HTTP/" << parser_.http_major << "." << parser_.http_minor << ' '
|
||||
<< method_name(req.method) << " " << req.url
|
||||
<< " " << res.code << ' ' << close_connection_;
|
||||
void complete_request()
|
||||
{
|
||||
CROW_LOG_INFO << "Response: " << this << ' ' << res.code << ' ' << close_connection_;
|
||||
|
||||
if (!socket_.is_open())
|
||||
return;
|
||||
|
||||
auto self = this->shared_from_this();
|
||||
res.complete_request_handler_ = nullptr;
|
||||
|
||||
static std::unordered_map<int, std::string> statusCodes = {
|
||||
{200, "HTTP/1.1 200 OK\r\n"},
|
||||
{201, "HTTP/1.1 201 Created\r\n"},
|
||||
{202, "HTTP/1.1 202 Accepted\r\n"},
|
||||
{204, "HTTP/1.1 204 No Content\r\n"},
|
||||
|
||||
{300, "HTTP/1.1 300 Multiple Choices\r\n"},
|
||||
{301, "HTTP/1.1 301 Moved Permanently\r\n"},
|
||||
{302, "HTTP/1.1 302 Moved Temporarily\r\n"},
|
||||
{304, "HTTP/1.1 304 Not Modified\r\n"},
|
||||
|
||||
{400, "HTTP/1.1 400 Bad Request\r\n"},
|
||||
{401, "HTTP/1.1 401 Unauthorized\r\n"},
|
||||
{403, "HTTP/1.1 403 Forbidden\r\n"},
|
||||
{404, "HTTP/1.1 404 Not Found\r\n"},
|
||||
|
||||
{500, "HTTP/1.1 500 Internal Server Error\r\n"},
|
||||
{501, "HTTP/1.1 501 Not Implemented\r\n"},
|
||||
{502, "HTTP/1.1 502 Bad Gateway\r\n"},
|
||||
{503, "HTTP/1.1 503 Service Unavailable\r\n"},
|
||||
};
|
||||
|
||||
static std::string seperator = ": ";
|
||||
static std::string crlf = "\r\n";
|
||||
@ -186,6 +206,7 @@ namespace crow
|
||||
buffers_.emplace_back(res.body.data(), res.body.size());
|
||||
|
||||
do_write();
|
||||
res.clear();
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -5,8 +5,13 @@
|
||||
|
||||
namespace crow
|
||||
{
|
||||
template <typename T>
|
||||
class Connection;
|
||||
struct response
|
||||
{
|
||||
template <typename T>
|
||||
friend class crow::Connection;
|
||||
|
||||
std::string body;
|
||||
json::wvalue json_value;
|
||||
int code{200};
|
||||
@ -24,22 +29,42 @@ namespace crow
|
||||
*this = std::move(r);
|
||||
}
|
||||
|
||||
response& operator = (const response& r) = delete;
|
||||
|
||||
response& operator = (response&& r)
|
||||
{
|
||||
body = std::move(r.body);
|
||||
json_value = std::move(r.json_value);
|
||||
code = r.code;
|
||||
headers = std::move(r.headers);
|
||||
completed_ = r.completed_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
void send(const std::string& body_part)
|
||||
void clear()
|
||||
{
|
||||
body.clear();
|
||||
json_value.clear();
|
||||
code = 200;
|
||||
headers.clear();
|
||||
completed_ = false;
|
||||
}
|
||||
|
||||
void write(const std::string& body_part)
|
||||
{
|
||||
body += body_part;
|
||||
}
|
||||
|
||||
void end()
|
||||
{
|
||||
if (!completed_)
|
||||
{
|
||||
completed_ = true;
|
||||
if (complete_request_handler_)
|
||||
{
|
||||
complete_request_handler_();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void end(const std::string& body_part)
|
||||
@ -47,5 +72,10 @@ namespace crow
|
||||
body += body_part;
|
||||
end();
|
||||
}
|
||||
|
||||
void* p;
|
||||
private:
|
||||
bool completed_{};
|
||||
std::function<void()> complete_request_handler_;
|
||||
};
|
||||
}
|
||||
|
10
mustache.h
10
mustache.h
@ -282,6 +282,16 @@ namespace crow
|
||||
out.insert(out.size(), body_, fragment.first, fragment.second-fragment.first);
|
||||
}
|
||||
public:
|
||||
std::string render()
|
||||
{
|
||||
context empty_ctx;
|
||||
std::vector<context*> stack;
|
||||
stack.emplace_back(&empty_ctx);
|
||||
|
||||
std::string ret;
|
||||
render_internal(0, fragments_.size()-1, stack, ret, 0);
|
||||
return ret;
|
||||
}
|
||||
std::string render(context& ctx)
|
||||
{
|
||||
std::vector<context*> stack;
|
||||
|
93
routing.h
93
routing.h
@ -24,7 +24,7 @@ namespace crow
|
||||
|
||||
virtual void validate() = 0;
|
||||
|
||||
virtual response handle(const request&, const routing_params&) = 0;
|
||||
virtual void handle(const request&, response&, const routing_params&) = 0;
|
||||
|
||||
protected:
|
||||
|
||||
@ -42,6 +42,7 @@ namespace crow
|
||||
H3& handler_with_req_res;
|
||||
const routing_params& params;
|
||||
const request& req;
|
||||
response& res;
|
||||
};
|
||||
|
||||
template <typename F, int NInt, int NUint, int NDouble, int NString, typename S1, typename S2>
|
||||
@ -52,75 +53,83 @@ namespace crow
|
||||
template <typename F, int NInt, int NUint, int NDouble, int NString, typename ... Args1, typename ... Args2>
|
||||
struct call<F, NInt, NUint, NDouble, NString, black_magic::S<int64_t, Args1...>, black_magic::S<Args2...>>
|
||||
{
|
||||
response operator()(F cparams)
|
||||
void operator()(F cparams)
|
||||
{
|
||||
using pushed = typename black_magic::S<Args2...>::template push_back<call_pair<int64_t, NInt>>;
|
||||
return call<F, NInt+1, NUint, NDouble, NString,
|
||||
black_magic::S<Args1...>, pushed>()(cparams);
|
||||
call<F, NInt+1, NUint, NDouble, NString,
|
||||
black_magic::S<Args1...>, pushed>()(cparams);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename F, int NInt, int NUint, int NDouble, int NString, typename ... Args1, typename ... Args2>
|
||||
struct call<F, NInt, NUint, NDouble, NString, black_magic::S<uint64_t, Args1...>, black_magic::S<Args2...>>
|
||||
{
|
||||
response operator()(F cparams)
|
||||
void operator()(F cparams)
|
||||
{
|
||||
using pushed = typename black_magic::S<Args2...>::template push_back<call_pair<uint64_t, NUint>>;
|
||||
return call<F, NInt, NUint+1, NDouble, NString,
|
||||
black_magic::S<Args1...>, pushed>()(cparams);
|
||||
call<F, NInt, NUint+1, NDouble, NString,
|
||||
black_magic::S<Args1...>, pushed>()(cparams);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename F, int NInt, int NUint, int NDouble, int NString, typename ... Args1, typename ... Args2>
|
||||
struct call<F, NInt, NUint, NDouble, NString, black_magic::S<double, Args1...>, black_magic::S<Args2...>>
|
||||
{
|
||||
response operator()(F cparams)
|
||||
void operator()(F cparams)
|
||||
{
|
||||
using pushed = typename black_magic::S<Args2...>::template push_back<call_pair<double, NDouble>>;
|
||||
return call<F, NInt, NUint, NDouble+1, NString,
|
||||
black_magic::S<Args1...>, pushed>()(cparams);
|
||||
call<F, NInt, NUint, NDouble+1, NString,
|
||||
black_magic::S<Args1...>, pushed>()(cparams);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename F, int NInt, int NUint, int NDouble, int NString, typename ... Args1, typename ... Args2>
|
||||
struct call<F, NInt, NUint, NDouble, NString, black_magic::S<std::string, Args1...>, black_magic::S<Args2...>>
|
||||
{
|
||||
response operator()(F cparams)
|
||||
void operator()(F cparams)
|
||||
{
|
||||
using pushed = typename black_magic::S<Args2...>::template push_back<call_pair<std::string, NString>>;
|
||||
return call<F, NInt, NUint, NDouble, NString+1,
|
||||
black_magic::S<Args1...>, pushed>()(cparams);
|
||||
call<F, NInt, NUint, NDouble, NString+1,
|
||||
black_magic::S<Args1...>, pushed>()(cparams);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename F, int NInt, int NUint, int NDouble, int NString, typename ... Args1>
|
||||
struct call<F, NInt, NUint, NDouble, NString, black_magic::S<>, black_magic::S<Args1...>>
|
||||
{
|
||||
response operator()(F cparams)
|
||||
void operator()(F cparams)
|
||||
{
|
||||
if (cparams.handler)
|
||||
return cparams.handler(
|
||||
{
|
||||
cparams.res = cparams.handler(
|
||||
cparams.params.template get<typename Args1::type>(Args1::pos)...
|
||||
);
|
||||
cparams.res.end();
|
||||
return;
|
||||
}
|
||||
if (cparams.handler_with_req)
|
||||
return cparams.handler_with_req(
|
||||
{
|
||||
cparams.res = cparams.handler_with_req(
|
||||
cparams.req,
|
||||
cparams.params.template get<typename Args1::type>(Args1::pos)...
|
||||
);
|
||||
cparams.res.end();
|
||||
return;
|
||||
}
|
||||
if (cparams.handler_with_req_res)
|
||||
{
|
||||
crow::response res;
|
||||
cparams.handler_with_req_res(
|
||||
cparams.req,
|
||||
res,
|
||||
cparams.res,
|
||||
cparams.params.template get<typename Args1::type>(Args1::pos)...
|
||||
);
|
||||
return res;
|
||||
return;
|
||||
}
|
||||
#ifdef CROW_ENABLE_LOGGING
|
||||
std::cerr << "ERROR cannot find handler" << std::endl;
|
||||
#endif
|
||||
return response(500);
|
||||
// we already found matched url; this is server error
|
||||
cparams.res = response(500);
|
||||
}
|
||||
};
|
||||
public:
|
||||
@ -223,24 +232,23 @@ namespace crow
|
||||
(*this).template operator()<Func>(std::forward(f));
|
||||
}
|
||||
|
||||
response handle(const request& req, const routing_params& params)
|
||||
void handle(const request& req, response& res, const routing_params& params) override
|
||||
{
|
||||
return
|
||||
call<
|
||||
call_params<
|
||||
decltype(handler_),
|
||||
decltype(handler_with_req_),
|
||||
decltype(handler_with_req_res_)>,
|
||||
0, 0, 0, 0,
|
||||
black_magic::S<Args...>,
|
||||
black_magic::S<>
|
||||
>()(
|
||||
call_params<
|
||||
decltype(handler_),
|
||||
decltype(handler_with_req_),
|
||||
decltype(handler_with_req_res_)>
|
||||
{handler_, handler_with_req_, handler_with_req_res_, params, req}
|
||||
);
|
||||
call<
|
||||
call_params<
|
||||
decltype(handler_),
|
||||
decltype(handler_with_req_),
|
||||
decltype(handler_with_req_res_)>,
|
||||
0, 0, 0, 0,
|
||||
black_magic::S<Args...>,
|
||||
black_magic::S<>
|
||||
>()(
|
||||
call_params<
|
||||
decltype(handler_),
|
||||
decltype(handler_with_req_),
|
||||
decltype(handler_with_req_res_)>
|
||||
{handler_, handler_with_req_, handler_with_req_res_, params, req, res}
|
||||
);
|
||||
}
|
||||
|
||||
private:
|
||||
@ -614,21 +622,26 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
response handle(const request& req)
|
||||
void handle(const request& req, response& res)
|
||||
{
|
||||
auto found = trie_.find(req);
|
||||
|
||||
unsigned rule_index = found.first;
|
||||
|
||||
if (!rule_index)
|
||||
return response(404);
|
||||
{
|
||||
CROW_LOG_DEBUG << "Cannot match rules " << req.url;
|
||||
res = response(404);
|
||||
res.end();
|
||||
return;
|
||||
}
|
||||
|
||||
if (rule_index >= rules_.size())
|
||||
throw std::runtime_error("Trie internal structure corrupted!");
|
||||
|
||||
CROW_LOG_DEBUG << "Matched rule '" << ((TaggedRule<>*)rules_[rule_index].get())->rule_ << "'";
|
||||
|
||||
return rules_[rule_index]->handle(req, found.second);
|
||||
rules_[rule_index]->handle(req, res, found.second);
|
||||
}
|
||||
|
||||
void debug_print()
|
||||
|
28
unittest.cpp
28
unittest.cpp
@ -72,9 +72,11 @@ TEST(Rule)
|
||||
|
||||
r.validate();
|
||||
|
||||
response res;
|
||||
|
||||
// executing handler
|
||||
ASSERT_EQUAL(0, x);
|
||||
r.handle(request(), routing_params());
|
||||
r.handle(request(), res, routing_params());
|
||||
ASSERT_EQUAL(1, x);
|
||||
|
||||
// registering handler with request argument
|
||||
@ -84,7 +86,7 @@ TEST(Rule)
|
||||
|
||||
// executing handler
|
||||
ASSERT_EQUAL(1, x);
|
||||
r.handle(request(), routing_params());
|
||||
r.handle(request(), res, routing_params());
|
||||
ASSERT_EQUAL(2, x);
|
||||
}
|
||||
|
||||
@ -143,13 +145,24 @@ TEST(RoutingTest)
|
||||
|
||||
app.validate();
|
||||
//app.debug_print();
|
||||
{
|
||||
request req;
|
||||
response res;
|
||||
|
||||
req.url = "/-1";
|
||||
|
||||
app.handle(req, res);
|
||||
|
||||
ASSERT_EQUAL(404, res.code);
|
||||
}
|
||||
|
||||
{
|
||||
request req;
|
||||
response res;
|
||||
|
||||
req.url = "/0/1001999";
|
||||
|
||||
auto res = app.handle(req);
|
||||
app.handle(req, res);
|
||||
|
||||
ASSERT_EQUAL(200, res.code);
|
||||
|
||||
@ -158,10 +171,11 @@ TEST(RoutingTest)
|
||||
|
||||
{
|
||||
request req;
|
||||
response res;
|
||||
|
||||
req.url = "/1/-100/1999";
|
||||
|
||||
auto res = app.handle(req);
|
||||
app.handle(req, res);
|
||||
|
||||
ASSERT_EQUAL(200, res.code);
|
||||
|
||||
@ -170,11 +184,12 @@ TEST(RoutingTest)
|
||||
}
|
||||
{
|
||||
request req;
|
||||
response res;
|
||||
|
||||
req.url = "/4/5000/3/-2.71828/hellhere";
|
||||
req.headers["TestHeader"] = "Value";
|
||||
|
||||
auto res = app.handle(req);
|
||||
app.handle(req, res);
|
||||
|
||||
ASSERT_EQUAL(200, res.code);
|
||||
|
||||
@ -185,11 +200,12 @@ TEST(RoutingTest)
|
||||
}
|
||||
{
|
||||
request req;
|
||||
response res;
|
||||
|
||||
req.url = "/5/-5/999/3.141592/hello_there/a/b/c/d";
|
||||
req.headers["TestHeader"] = "Value";
|
||||
|
||||
auto res = app.handle(req);
|
||||
app.handle(req, res);
|
||||
|
||||
ASSERT_EQUAL(200, res.code);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user