Skip to content

Commit 01b0cdc

Browse files
committed
Request format checking improved
1 parent 0ae7037 commit 01b0cdc

File tree

5 files changed

+26
-16
lines changed

5 files changed

+26
-16
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ This project is a basic HTTP server written in C++98.
44

55
| Functionality | Description | External info
66
| --- | --- | --- |
7-
| HTTP | HTTP/1.1 | [RFC 2616](https://datatracker.ietf.org/doc/html/rfc2616) |
7+
| HTTP | HTTP/1.1 | [RFC 2616](https://datatracker.ietf.org/doc/html/rfc2616) / [RFC 9110](https://datatracker.ietf.org/doc/html/rfc9110#section-9.3.7) / [RFC 9112](https://datatracker.ietf.org/doc/html/rfc9112#name-chunked-transfer-coding) |
88
| CGI | CGI/1.1 (Tested with php-cgi, using wordpress, and python cgi) | [RFC 3875](https://datatracker.ietf.org/doc/html/rfc3875) |
99
| Implemented methods | GET / HEAD / OPTIONS / POST / PUT / DELETE | [RFC 2616 section 5.1.1](https://datatracker.ietf.org/doc/html/rfc2616#section-5.1.1) |
1010
| Basic cookie support | Tested with wordpress | [RFC 2109](https://datatracker.ietf.org/doc/html/rfc2109) |

include/utils/utils.hpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,19 +16,21 @@
1616

1717
#include "colors.hpp"
1818

19+
#define WHITESPACE " \f\n\r\t\v"
20+
1921
// Trims start and end of a string
2022
// @param str The string to trim
2123
// @param chars The characters to trim
2224
// @return The trimmed string
2325
// @exception No custom exceptions
24-
std::string trim(const std::string& str, std::string chars = " \f\n\r\t\v");
26+
std::string trim(const std::string& str, std::string chars = WHITESPACE);
2527

2628
// Trim the start of a string
2729
// @param str The string to trim
2830
// @param chars The characters to trim
2931
// @return The trimmed string
3032
// @exception No custom exceptions
31-
std::string& trimStart(std::string& str, std::string chars = " \f\n\r\t\v");
33+
std::string& trimStart(std::string& str, std::string chars = WHITESPACE);
3234

3335
std::string trimStart(const std::string& str, std::string chars);
3436

src/http/Http.cpp

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,11 @@ Http::~Http() {
2525
void Http::OnRequestRecv(std::string msg) {
2626
accessLog_g.write("HTTP status: '" + msg + "'", VERBOSE);
2727

28-
const std::string &delim = getReadDelimiter();
29-
if (startsWith(msg, delim)) return;
30-
_request = Request();
28+
// https://datatracker.ietf.org/doc/html/rfc9112#section-2.2-6
29+
if (msg.empty()) return;
3130

32-
msg.erase(msg.size() - delim.size(), delim.size());
31+
_request = Request();
3332
bool parseRet = _request.parseRequestLine(msg);
34-
3533
_log = toString<Address &>(client) + ": " + _request.getMethod() + " " +
3634
_request.getUri().generate() + " " + _request.getVersion() + " -> " +
3735
toString<Address &>(host);
@@ -60,6 +58,7 @@ void Http::OnRequestRecv(std::string msg) {
6058
void Http::OnHeadRecv(std::string msg) {
6159
accessLog_g.write("HTTP head: '" + msg + "'", VERBOSE);
6260

61+
// https://datatracker.ietf.org/doc/html/rfc9112#section-2.2-8
6362
if (_request.parseHeaderFields(msg))
6463
processError("400", "Bad Request", true);
6564
else {
@@ -98,7 +97,7 @@ void Http::OnChunkSizeRecv(std::string msg) {
9897
void Http::OnTrailerRecv(std::string msg) {
9998
accessLog_g.write("HTTP trailer: '" + msg + "'", VERBOSE);
10099

101-
if (msg == getReadDelimiter()) {
100+
if (msg.empty()) {
102101
if (_request.isMethod("PUT"))
103102
getPutResponse(_uri);
104103
else if (_request.isMethod("POST")) {

src/http/Request.cpp

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -74,22 +74,31 @@ int Request::parseRequestLine(std::string line) {
7474
if (requestLineTokens.size() != 3) return 1;
7575
_method = requestLineTokens[0];
7676
_version = requestLineTokens[2];
77+
78+
// https://datatracker.ietf.org/doc/html/rfc9112#name-method and
79+
// https://datatracker.ietf.org/doc/html/rfc9112#name-http-version
80+
if (_method.find_first_of(WHITESPACE) != std::string::npos ||
81+
_version.find_first_of(WHITESPACE) != std::string::npos)
82+
return 1;
7783
if (!startsWith(_version, "HTTP/")) return 1;
7884
return _uri.load(requestLineTokens[1]);
7985
}
8086

8187
int Request::parseHeaderFields(std::string fields) {
82-
size_t end = fields.find("\r\n");
83-
84-
while (end != 0 && end != std::string::npos) {
88+
size_t end;
89+
while (true) {
90+
end = fields.find("\r\n");
91+
if (end == std::string::npos) end = fields.size();
8592
std::string line = fields.substr(0, end);
8693
size_t colon = line.find(":");
8794
if (colon == std::string::npos) return 1;
95+
8896
std::string key = line.substr(0, colon);
97+
if (key.find_first_of(WHITESPACE) != std::string::npos) return 1;
98+
8999
std::string value = line.substr(colon + 1);
90100
setHeaderField(key, value);
91101
fields.erase(0, line.size() + 2);
92-
end = fields.find("\r\n");
102+
if (fields.empty()) return 0;
93103
}
94-
return 0;
95104
}

src/poll/AConnection.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -338,7 +338,7 @@ void AConnection::passReadBuffer(struct pollfd &pollfd) {
338338
while (pollfd.events & POLLIN) {
339339
pos = _readBuffer.find(readDelimiter);
340340
if (pos == std::string::npos) break;
341-
pos += readDelimiter.size();
341+
size_t tmpReadDelim = readDelimiter.size();
342342

343343
switch (_readState) {
344344
case REQUEST_LINE:
@@ -362,7 +362,7 @@ void AConnection::passReadBuffer(struct pollfd &pollfd) {
362362
default:
363363
throw std::runtime_error("passReadBuffer(): Undefined read state");
364364
}
365-
_readBuffer.erase(0, pos);
365+
_readBuffer.erase(0, pos + tmpReadDelim);
366366
}
367367
}
368368

0 commit comments

Comments
 (0)