Add test for url accumulation bug
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
#include "http_handler.hpp"
|
||||
#include "server.hpp"
|
||||
|
||||
#include <chrono>
|
||||
#include <doctest/doctest.h>
|
||||
#include <fcntl.h>
|
||||
#include <poll.h>
|
||||
@@ -198,3 +199,70 @@ TEST_CASE("HTTP pipelined POST requests race condition") {
|
||||
server->shutdown();
|
||||
runThread.join();
|
||||
}
|
||||
|
||||
TEST_CASE("HTTP URL split across multiple writes") {
|
||||
weaseldb::Config config;
|
||||
HttpHandler handler(config);
|
||||
auto server = Server::create(config, handler, {});
|
||||
int fd = server->create_local_connection();
|
||||
|
||||
auto runThread = std::thread{[&]() { server->run(); }};
|
||||
|
||||
// Test URL accumulation by splitting the URL across multiple writes
|
||||
// This would have caught the original bug where URL string_view pointed
|
||||
// to llhttp's internal buffer that gets reused between writes
|
||||
|
||||
// Split "GET /metrics HTTP/1.1\r\n" across multiple writes
|
||||
std::string part1 = "GET /met";
|
||||
std::string part2 = "rics HTTP/1.1\r\n";
|
||||
std::string headers = "Host: localhost\r\n"
|
||||
"Connection: close\r\n"
|
||||
"\r\n";
|
||||
|
||||
// Write URL in two parts - this tests URL accumulation
|
||||
int w1 = write(fd, part1.c_str(), part1.size());
|
||||
REQUIRE(w1 == static_cast<int>(part1.size()));
|
||||
|
||||
// Attempt to trigger separate llhttp parsing calls
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
|
||||
int w2 = write(fd, part2.c_str(), part2.size());
|
||||
REQUIRE(w2 == static_cast<int>(part2.size()));
|
||||
|
||||
int w3 = write(fd, headers.c_str(), headers.size());
|
||||
REQUIRE(w3 == static_cast<int>(headers.size()));
|
||||
|
||||
// Read response
|
||||
char buf[4096];
|
||||
int total_read = 0;
|
||||
bool found_metrics_response = false;
|
||||
|
||||
while (total_read < 4000) {
|
||||
int r = read(fd, buf + total_read, sizeof(buf) - total_read - 1);
|
||||
if (r <= 0)
|
||||
break;
|
||||
total_read += r;
|
||||
|
||||
buf[total_read] = '\0';
|
||||
std::string response(buf, total_read);
|
||||
|
||||
// Check for successful metrics response (not 404)
|
||||
if (response.find("HTTP/1.1 200 OK") != std::string::npos &&
|
||||
response.find("text/plain; version=0.0.4") != std::string::npos) {
|
||||
found_metrics_response = true;
|
||||
break;
|
||||
}
|
||||
|
||||
// Check for 404 which would indicate URL accumulation failed
|
||||
if (response.find("HTTP/1.1 404") != std::string::npos) {
|
||||
FAIL("Got 404 - URL accumulation failed, split URL was not properly "
|
||||
"reconstructed");
|
||||
}
|
||||
}
|
||||
|
||||
REQUIRE(found_metrics_response);
|
||||
|
||||
close(fd);
|
||||
server->shutdown();
|
||||
runThread.join();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user