Skip to content

Commit

Permalink
Further improve custom parser
Browse files Browse the repository at this point in the history
  • Loading branch information
hhvrc committed Jan 27, 2025
1 parent 08eb064 commit 69f71b2
Show file tree
Hide file tree
Showing 2 changed files with 80 additions and 5 deletions.
24 changes: 23 additions & 1 deletion include/external/AsyncWebServer/HttpRequestBodyParser.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,36 @@
#include <string>

class HttpRequestBodyParser {
enum class HttpParseState {
Error = -1,
RequestLine,
Headers,
Body,
Done
};

public:
bool TryParse(std::string_view view);
size_t Consume(std::string_view view);
bool IsBadRequest() const { return _state == HttpParseState::Error; }
bool IsFinished() const { return _state == HttpParseState::Done; }

HttpMethod method() const { return _method; }
HttpVersion version() const { return _version; }
HttpVersion versionMajor() const { return _version.major; }
HttpVersion versionMinor() const { return _version.minor; }
std::string_view url() const { return _url; }
const std::map<std::string, std::string>& queryParams() const { return _queryParams; }
const std::map<std::string, std::string>& headers() const { return _headers; }

private:
bool TryParseRequestLine(std::string_view view);
bool TryParseHeader(std::string_view view);

HttpParseState _state;

HttpMethod _method;
HttpVersion _version;
std::string _url;
std::map<std::string, std::string> _queryParams;
std::map<std::string, std::string> _headers;
}
61 changes: 57 additions & 4 deletions src/external/AsyncWebServer/HttpRequestBodyParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -93,14 +93,54 @@ static bool ParseHttpVersion(std::string_view view, HttpVersion& http_version_ou
return true;
}

bool HttpRequestBodyParser::TryParse(std::string_view view)
size_t HttpRequestBodyParser::Consume(std::string_view view)
{
using namespace std::string_view_literals;

size_t pos = view.find("\r\n"sv);
if (pos == std::string_view::npos) return false; // Need more data
if (_state == HttpParseState::Error) return 0;

if (!TryParseRequestLine(view.substr(0, pos))) return false; // Malformed request
size_t offset = 0;

// Parse the requestline
if (_state == HttpParseState::RequestLine) {
// Find end of requestline
size_t pos = view.find("\r\n"sv);
if (pos == std::string_view::npos) return 0; // Need more data

// Parse requestline
if (!TryParseRequestLine(view.substr(0, pos))) {
_state = HttpParseState::Error;
return 0;
}

// Set state for continuation
_state = HttpParseState::Headers;
offset += pos + 2;
}

// Parse the headers
if (_state == HttpParseState::Headers) {
do {
// Find end of header
size_t pos = view.find("\r\n"sv, offset);
if (pos == std::string_view::npos) return offset; // Need more data
if (pos == 0) break; // End of headers

// Parse header
if (!TryParseHeader(view.substr(0, pos))) {
_state = HttpParseState::Error;
return 0;
}

offset += pos + 2;
} while (true);

// Set state for continuation
_state = HttpParseState::Body;
}

if (_state == HttpParseState::Body) {
}

return true;
}
Expand Down Expand Up @@ -152,3 +192,16 @@ bool HttpRequestBodyParser::TryParseRequestLine(std::string_view view)

return true;
}

bool HttpRequestBodyParser::TryParseHeader(std::string_view view)
{
size_t pos = view.find(':');
if (pos == std::string_view::npos) return false;

std::string_view name = view.substr(0, pos);
std::string_view value = view.substr(pos + 1);

// TODO: Validate these two

_headers.emplace(name, value);
}

0 comments on commit 69f71b2

Please sign in to comment.