This commit is contained in:
yhirose 2017-12-02 10:24:41 -05:00
parent 90f9cd40f9
commit 28ba178fee
2 changed files with 113 additions and 16 deletions

View File

@ -155,6 +155,7 @@ private:
bool dispatch_request(Request& req, Response& res, Handlers& handlers); bool dispatch_request(Request& req, Response& res, Handlers& handlers);
bool read_request_line(Stream& strm, Request& req); bool read_request_line(Stream& strm, Request& req);
void write_response(Stream& strm, const Request& req, Response& res);
virtual bool read_and_close_socket(socket_t sock); virtual bool read_and_close_socket(socket_t sock);
@ -270,6 +271,10 @@ inline bool socket_gets(Stream& strm, char* buf, int bufsiz)
} }
} }
if (i == bufsiz) {
return false;
}
buf[i++] = byte; buf[i++] = byte;
if (byte == '\n') { if (byte == '\n') {
@ -277,6 +282,10 @@ inline bool socket_gets(Stream& strm, char* buf, int bufsiz)
} }
} }
if (i == bufsiz) {
return false;
}
buf[i] = '\0'; buf[i] = '\0';
return true; return true;
} }
@ -288,7 +297,13 @@ inline void socket_printf(Stream& strm, const char* fmt, const Args& ...args)
auto n = snprintf(buf, BUFSIZ, fmt, args...); auto n = snprintf(buf, BUFSIZ, fmt, args...);
if (n > 0) { if (n > 0) {
if (n >= BUFSIZ) { if (n >= BUFSIZ) {
// TODO: buffer size is not large enough... std::vector<char> glowable_buf(BUFSIZ);
while (n >= glowable_buf.size()) {
glowable_buf.resize(glowable_buf.size() * 2);
n = snprintf(&glowable_buf[0], glowable_buf.size(), fmt, args...);
}
strm.write(&glowable_buf[0], n);
} else { } else {
strm.write(buf, n); strm.write(buf, n);
} }
@ -564,7 +579,9 @@ bool read_content(Stream& strm, T& x, bool allow_no_content_length, Progress pro
return false; return false;
} }
r += r_incr; r += r_incr;
progress(r, len); if (progress) {
progress(r, len);
}
} }
} else if (allow_no_content_length) { } else if (allow_no_content_length) {
for (;;) { for (;;) {
@ -979,6 +996,21 @@ inline bool Server::read_request_line(Stream& strm, Request& req)
return false; return false;
} }
inline void Server::write_response(Stream& strm, const Request& req, Response& res)
{
assert(res.status != -1);
if (400 <= res.status && error_handler_) {
error_handler_(req, res);
}
detail::write_response(strm, req, res);
if (logger_) {
logger_(req, res);
}
}
inline bool Server::handle_file_request(Request& req, Response& res) inline bool Server::handle_file_request(Request& req, Response& res)
{ {
if (!base_dir_.empty() && detail::is_valid_path(req.path)) { if (!base_dir_.empty() && detail::is_valid_path(req.path)) {
@ -1035,17 +1067,19 @@ inline void Server::process_request(Stream& strm)
Request req; Request req;
Response res; Response res;
if (!read_request_line(strm, req) || if (!read_request_line(strm, req) || !detail::read_headers(strm, req.headers)) {
!detail::read_headers(strm, req.headers)) { res.status = 400;
// TODO: write_response(strm, req, res);
return; return;
} }
if (req.method == "POST") { if (req.method == "POST") {
if (!detail::read_content(strm, req, false)) { if (!detail::read_content(strm, req, false)) {
// TODO: res.status = 400;
write_response(strm, req, res);
return; return;
} }
static std::string type = "application/x-www-form-urlencoded"; static std::string type = "application/x-www-form-urlencoded";
if (!req.get_header_value("Content-Type").compare(0, type.size(), type)) { if (!req.get_header_value("Content-Type").compare(0, type.size(), type)) {
detail::parse_query_text(req.body, req.params); detail::parse_query_text(req.body, req.params);
@ -1059,17 +1093,8 @@ inline void Server::process_request(Stream& strm)
} else { } else {
res.status = 404; res.status = 404;
} }
assert(res.status != -1);
if (400 <= res.status && error_handler_) { write_response(strm, req, res);
error_handler_(req, res);
}
detail::write_response(strm, req, res);
if (logger_) {
logger_(req, res);
}
} }
inline bool Server::read_and_close_socket(socket_t sock) inline bool Server::read_and_close_socket(socket_t sock)
@ -1130,6 +1155,7 @@ inline bool Client::process_request(Stream& strm, const Request& req, Response&
!detail::read_headers(strm, res.headers)) { !detail::read_headers(strm, res.headers)) {
return false; return false;
} }
if (req.method != "HEAD") { if (req.method != "HEAD") {
if (!detail::read_content(strm, res, true, req.progress)) { if (!detail::read_content(strm, res, true, req.progress)) {
return false; return false;

View File

@ -329,6 +329,77 @@ TEST_F(ServerTest, InvalidBaseDir)
EXPECT_EQ(true, svr_.set_base_dir(".")); EXPECT_EQ(true, svr_.set_base_dir("."));
} }
TEST_F(ServerTest, EmptyRequest)
{
auto res = cli_.get("");
ASSERT_TRUE(res != nullptr);
EXPECT_EQ(400, res->status);
}
TEST_F(ServerTest, LongRequest)
{
auto res = cli_.get("/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/__ok__");
ASSERT_TRUE(res != nullptr);
EXPECT_EQ(404, res->status);
}
TEST_F(ServerTest, TooLongRequest)
{
auto res = cli_.get("/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/TooLongRequest/__ng___");
ASSERT_TRUE(res != nullptr);
EXPECT_EQ(400, res->status);
}
TEST_F(ServerTest, LongHeader)
{
Request req;
req.method = "GET";
req.path = "/hi";
std::string host_and_port;
host_and_port += HOST;
host_and_port += ":";
host_and_port += std::to_string(PORT);
req.set_header("Host", host_and_port.c_str());
req.set_header("Accept", "*/*");
req.set_header("User-Agent", "cpp-httplib/0.1");
req.set_header("Header-Name", "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
auto res = std::make_shared<Response>();
auto ret = cli_.send(req, *res);
ASSERT_TRUE(ret);
EXPECT_EQ(200, res->status);
}
TEST_F(ServerTest, TooLongHeader)
{
Request req;
req.method = "GET";
req.path = "/hi";
std::string host_and_port;
host_and_port += HOST;
host_and_port += ":";
host_and_port += std::to_string(PORT);
req.set_header("Host", host_and_port.c_str());
req.set_header("Accept", "*/*");
req.set_header("User-Agent", "cpp-httplib/0.1");
req.set_header("Header-Name", "@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
auto res = std::make_shared<Response>();
auto ret = cli_.send(req, *res);
ASSERT_TRUE(ret);
EXPECT_EQ(400, res->status);
}
class ServerTestWithAI_PASSIVE : public ::testing::Test { class ServerTestWithAI_PASSIVE : public ::testing::Test {
protected: protected:
ServerTestWithAI_PASSIVE() ServerTestWithAI_PASSIVE()