Commit b0be06a6 authored by jan.koester's avatar jan.koester
Browse files

useragent test

parent 148d726c
Loading
Loading
Loading
Loading
+48 −0
Original line number Diff line number Diff line
@@ -261,6 +261,53 @@ void testPrintHeaderSingleUserAgentLine() {
          "outgoing user-agent: line carries the exact original value, unsplit");
}

// A second request on the SAME keep-alive connection must not see the first
// request's User-Agent lingering alongside its own -- HttpRequest::parseH1()
// deliberately does getHeaderData() before setHeaderData() per-line (see its
// own comment) so a header genuinely repeated *within one request* (multiple
// Cookie: lines) appends rather than clobbers, but that lookup can't tell
// "repeated within this request" apart from "left over from the request
// before it" on a reused connection unless something clears state in
// between. Real browsers reuse one connection for many sequential requests;
// curl-style one-request-per-connection testing (like the two tests above)
// never exercises this at all -- which is exactly why it went unnoticed
// until a strict upstream (observed live: Home Assistant's aiohttp) started
// rejecting the accumulated duplicate outright.
void testKeepAliveDoesNotAccumulateHeaders(int port) {
    auto sock = std::make_unique<netplus::tcp>();
    rawtcp::connectLocal(*sock, port);

    auto doRequest = [&](const std::string &ua) {
        std::ostringstream req;
        req << "GET /ua-echo HTTP/1.1\r\n"
            << "Host: 127.0.0.1:" << port << "\r\n"
            << "User-Agent: " << ua << "\r\n"
            << "Connection: keep-alive\r\n"
            << "\r\n";
        rawtcp::sendAllOrThrow(*sock, req.str());

        HttpResponse res;
        rawReadHeadersAndParse(*sock, res);
        return res;
    };

    HttpResponse first = doRequest("FirstAgent/1.0");
    check(headerValue(first, "x-ua-count") == "1",
          "keep-alive request #1 -- server sees exactly one Value");
    check(headerValue(first, "x-ua-echo") == "FirstAgent/1.0",
          "keep-alive request #1 -- value matches what was sent");

    HttpResponse second = doRequest("SecondAgent/2.0");
    sock->close();

    check(headerValue(second, "x-ua-count") == "1",
          "keep-alive request #2 on the SAME connection -- still exactly one Value, "
          "not two (request #1's stale value must not linger)");
    check(headerValue(second, "x-ua-echo") == "SecondAgent/2.0",
          "keep-alive request #2 -- value is request #2's own, not request #1's "
          "leftover joined with it");
}

} // namespace

int main() {
@@ -274,6 +321,7 @@ int main() {

        testSemicolonHeavyUserAgentNotSplit(port);
        testPrintHeaderSingleUserAgentLine();
        testKeepAliveDoesNotAccumulateHeaders(port);

    } catch (HTTPException &e) {
        std::cerr << "HTTPException: " << e.what() << std::endl;