Skip to content

Commit bd7ac07

Browse files
feature: max_body_size check and fixing is_done()
1 parent f095996 commit bd7ac07

File tree

3 files changed

+45
-6
lines changed

3 files changed

+45
-6
lines changed

src/handler/upload_handler.cpp

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,8 @@ UploadHandler::UploadHandler(const std::string& path, const RouteConfig& rc, con
1818
req_(req),
1919
out_off_(0),
2020
bytes_written_(0),
21-
fd_(-1)
21+
fd_(-1),
22+
eof_(false)
2223

2324
{
2425
if (req.content_length == 0) {
@@ -60,20 +61,28 @@ size_t UploadHandler::read_output(char* buf, size_t n)
6061
size_t UploadHandler::write_input(const char* buf, size_t n)
6162
{
6263
ssize_t bytes = write(fd_, buf, n);
64+
if (bytes == 0) {
65+
// should never happen ?
66+
}
6367
if (bytes < 0) {
6468
if (out_buf_.empty()) {
6569
set_error(HttpResponse::kStatusDiskFull);
6670
}
67-
bytes_written_ = req_.content_length; // to ensure needs_input returns false
71+
eof_ = true; // to ensure needs_input returns false
6872
return 0;
6973
}
7074
bytes_written_ += bytes;
71-
if (bytes_written_ < req_.content_length) {
75+
if (bytes_written_ < rc_.shared.max_body_size && bytes_written_ < req_.content_length) {
7276
return (bytes);
7377
}
78+
if (bytes_written_ >= rc_.shared.max_body_size) {
79+
if (out_buf_.empty())
80+
set_error(HttpResponse::kStatusBadRequest);
81+
}
7482
if (out_buf_.empty()) {
7583
res_ = HttpResponse::make_response_headers_only(HttpResponse::kStatusCreated, "", 0, req_);
7684
out_buf_ = res_.to_string();
85+
eof_ = true;
7786
}
7887
return (0);
7988
}
@@ -82,4 +91,5 @@ void UploadHandler::set_error(const HttpResponse::Status code)
8291
{
8392
res_ = HttpResponse::make_error(code, rc_.shared.error_pages, req_);
8493
out_buf_ = res_.to_string();
94+
eof_ = true;
8595
}

src/handler/upload_handler.hpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ class UploadHandler : public Handler {
2020
virtual bool is_regular_file() const { return true; }
2121
virtual bool has_output() const { return out_off_ < out_buf_.size(); }
2222
virtual bool needs_input() const { return bytes_written_ < req_.content_length; }
23-
virtual bool is_done() const { return out_off_ >= out_buf_.size(); }
23+
virtual bool is_done() const { return eof_ && out_off_ >= out_buf_.size(); }
2424

2525
virtual int cgi_read_fd() const { return -1; }
2626
virtual int cgi_write_fd() const { return -1; }
@@ -44,6 +44,7 @@ class UploadHandler : public Handler {
4444
// other handler specifc variables
4545
size_t bytes_written_;
4646
int fd_;
47+
bool eof_;
4748
};
4849

4950
#endif

tests/upload_handler_unittest.cpp

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,17 +3,30 @@
33

44
#include <cstdio>
55

6-
static void write_all(Handler& handler, const std::string& content)
6+
static size_t write_all(Handler& handler, const std::string& content)
77
{
88
size_t written = 0;
99

10-
while (handler.needs_input()) {
10+
while (!handler.is_done() && handler.needs_input()) {
1111
size_t n = handler.write_input(content.c_str() + written, content.size() - written);
1212
written += n;
1313

1414
if ((n == 0 && handler.needs_input()))
1515
break;
1616
}
17+
return written;
18+
}
19+
20+
UTEST(UploadHandlerTest, is_done_upload_ongoing)
21+
{
22+
std::string upload_path = "www/example/needs_input_upload_ongoing.txt";
23+
std::string content = "some content to be written to the file";
24+
RouteConfig rc;
25+
HttpRequest req;
26+
req.content_length = content.size();
27+
UploadHandler handler(upload_path, rc, req);
28+
ASSERT_FALSE(handler.is_done());
29+
std::remove(upload_path.c_str());
1730
}
1831

1932
UTEST(UploadHandlerTest, needs_input_upload_ongoing)
@@ -135,3 +148,18 @@ UTEST(UploadHandlerTest, return_507)
135148
{
136149
UTEST_SKIP("TODO: Test Disk full without making your machine explode");
137150
}
151+
152+
UTEST(UploadHandlerTest, max_body_size)
153+
{
154+
std::string upload_path = "www/example/needs_input_upload_done.txt";
155+
std::string content = "some content to be written to the file";
156+
RouteConfig rc;
157+
rc.shared.max_body_size = 5;
158+
HttpRequest req;
159+
req.content_length = content.size();
160+
ASSERT_TRUE(req.content_length > rc.shared.max_body_size);
161+
UploadHandler handler(upload_path, rc, req);
162+
size_t n = write_all(handler, content);
163+
ASSERT_TRUE(n < req.content_length);
164+
std::remove(upload_path.c_str());
165+
}

0 commit comments

Comments
 (0)