Skip to content

Conversation

@vinniefalco
Copy link
Member

@vinniefalco vinniefalco commented Feb 8, 2026

Summary by CodeRabbit

  • New Features

    • Added automatic OPTIONS request handling with Allow header support.
  • Bug Fixes

    • Improved HTTP error responses with proper status codes (404 Not Found, 500 Internal Server Error) instead of connection closure.
    • Added 405 Method Not Allowed response when paths don't support the requested HTTP method.

@coderabbitai
Copy link

coderabbitai bot commented Feb 8, 2026

📝 Walkthrough

Walkthrough

The pull request modifies HTTP routing and error handling across four files. It introduces a default OPTIONS handler in the router constructor, refactors method-tracking variable names in the router base implementation, implements 405 Method Not Allowed responses for unsupported methods on matched paths, and adds result-aware error response handling in the HTTP worker for 404 and 500 scenarios.

Changes

Cohort / File(s) Summary
Default OPTIONS Handler
include/boost/http/server/router.hpp
Added default OPTIONS handler wiring in router constructor with includes for field.hpp and status.hpp to support automatic OPTIONS response generation.
Router Base Implementation
src/server/detail/router_base.hpp, src/server/detail/router_base.cpp
Updated include-guard macro (any_router → router_base); refactored method tracking variables (options_methods → matched_methods; options_custom_verbs → matched_custom_verbs); added 405 Method Not Allowed response generation when a path matches but the request method is unsupported.
HTTP Worker Error Handling
src/server/http_worker.cpp
Implemented route dispatch result handling that generates 404 Not Found responses for unmatched routes and 500 Internal Server Error responses for failed dispatch operations.

Sequence Diagram(s)

sequenceDiagram
    actor Client
    participant Worker as HTTP Worker
    participant Router as Router
    participant Response as Response Handler

    Client->>Worker: HTTP Request
    Worker->>Router: Dispatch Route
    
    alt Route Matched
        Router->>Router: Check Method Allowed
        alt Method Allowed
            Router-->>Worker: route_done
            Worker->>Response: Send Response
        else Method Not Allowed
            Router->>Router: Build Allow Header<br/>from matched methods
            Router->>Response: 405 Method Not Allowed
            Response-->>Worker: Response Sent
        end
    else Route Not Matched
        Router-->>Worker: next (no match)
        Worker->>Response: 404 Not Found
        Response-->>Worker: Response Sent
    else Dispatch Failed
        Router-->>Worker: failed
        Worker->>Response: 500 Internal Server Error
        Response-->>Worker: Response Sent
    end
    
    Worker->>Client: HTTP Response
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

Poem

🐰 A router hops with OPTIONS bright,
405s and 404s set right,
When methods don't align with paths so true,
The Allow header guides what's due.
Error handlers dance in harmony—
HTTP's protocol symphony! 🎵

🚥 Pre-merge checks | ✅ 1 | ❌ 1
❌ Failed checks (1 inconclusive)
Check name Status Explanation Resolution
Title check ❓ Inconclusive The title 'doc work' is vague and generic, providing no meaningful information about the actual code changes (OPTIONS handler wiring, router refactoring, response handling). Use a more descriptive title that reflects the main changes, such as 'Add default OPTIONS handler and improve HTTP error responses' or 'Implement automatic OPTIONS method handling in router'.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@cppalliance-bot
Copy link

cppalliance-bot commented Feb 8, 2026

An automated preview of the documentation is available at https://262.http.prtest3.cppalliance.org/index.html

If more commits are pushed to the pull request, the docs will rebuild at the same URL.

2026-02-09 01:34:00 UTC

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🤖 Fix all issues with AI agents
In `@include/boost/http/server/router.hpp`:
- Around line 603-609: The OPTIONS handler currently ignores the result of
co_await rp.send(), so send failures are discarded; update the lambda passed to
set_options_handler (the handler taking P& rp) to capture the outcome of
co_await rp.send(), check for an error, and only co_return route_done on
success—otherwise propagate or return an error/failed route result so callers
know the response wasn't sent (i.e., handle rp.send()'s failure instead of
discarding it after rp.status(status::no_content) and rp.res.set(field::allow,
allow)).

In `@src/server/detail/router_base.cpp`:
- Around line 291-297: matched_custom_verbs is being appended from every
matching end-route matcher (inside the m.end_ branch) and can accumulate
duplicates, causing duplicate verbs in the Allow header because
build_allow_header doesn't deduplicate; update the logic after collecting from
matchers (or immediately before calling build_allow_header) to deduplicate
matched_custom_verbs (e.g., sort and std::unique or use an unordered_set) so
only unique custom verbs are passed to build_allow_header; keep collecting
matched_methods as-is but ensure matched_custom_verbs is de-duplicated similarly
to rebuild_global_allow_header to avoid repeated verbs in the header.
- Around line 375-384: The 405 fallback fires even when the incoming request's
method is present in matched_methods or matched_custom_verbs; change the
condition in the block that builds the Allow header to also verify the current
request method is NOT present before returning 405. Concretely, compute the
method bit for the current request (e.g. method_bit =
method_to_bit(p.req.method) or similar) and only trigger the 405 when
!is_options && (matched_methods != 0 || !matched_custom_verbs.empty()) &&
((matched_methods & method_bit) == 0) && (matched_custom_verbs does not contain
the request method string); then call build_allow_header(matched_methods,
matched_custom_verbs), p.res.set_status(status::method_not_allowed) and send as
before (return route_done).

In `@src/server/http_worker.cpp`:
- Line 84: The two discarded send results of (co_await rp.send()) must be
checked and handled: capture the await result into an error variable when
calling rp.send(), and if it indicates failure, break out of the request loop or
return early (e.g., co_return route_error(ec)) instead of continuing to check
keep_alive() and reuse the stream; apply this change to both occurrences of
rp.send() so failed sends do not allow another request/response cycle on a
broken connection.
🧹 Nitpick comments (3)
src/server/http_worker.cpp (1)

78-91: Use an else if chain for mutually exclusive dispatch outcomes.

The three conditions (close, next, failed) are semantically mutually exclusive, but they're written as independent if blocks. After the next branch sends a 404 response, execution falls through to the rv.failed() check (which should be false, but it's fragile). An else if chain would make the intent explicit and guard against subtle bugs if route_result semantics evolve.

Additionally, both the 404 and 500 paths send an empty body via rp.send(), whereas other handlers in this codebase (e.g., serve_static.cpp Line 243, Line 306) send descriptive text like "Not Found" and "Internal Server Error". Consider adding body text for consistency and to help HTTP clients that render error pages.

Proposed refactor
-            if(rv.what() == route_what::close)
-                break;
-
-            if(rv.what() == route_what::next)
+            if(rv.what() == route_what::close)
+                break;
+            else if(rv.what() == route_what::next)
             {
                 rp.status(http::status::not_found);
-                (void)(co_await rp.send());
+                (void)(co_await rp.send("Not Found"));
             }
-
-            if(rv.failed())
+            else if(rv.failed())
             {
                 rp.status(http::status::internal_server_error);
-                (void)(co_await rp.send());
+                (void)(co_await rp.send("Internal Server Error"));
             }
include/boost/http/server/router.hpp (1)

586-609: Constructor docstring doesn't mention the default OPTIONS handler.

The constructor now installs a default OPTIONS handler (lines 603–609) that responds with 204 No Content and an Allow header, but the docstring (lines 586–596) only discusses option inheritance. Since this is a public header and the behavior is user-visible (automatic OPTIONS responses), it should be documented.

As per coding guidelines, "Docstrings are required for all classes and functions in public headers in non-detail namespaces. Docstrings should include a brief description of purpose, document all parameters, return values, and any preconditions, postconditions, or exceptions."

src/server/detail/router_base.cpp (1)

375-384: The 405 path sends a response directly from the dispatch loop, bypassing the caller.

Unlike other dispatch outcomes that return route_next/route_done/route_error and let the caller (http_worker) decide the response, the 405 branch directly sets status, headers, and sends the response within dispatch_loop. This means the caller has no opportunity to customize the 405 response (e.g., add CORS headers, custom body). This is consistent with the OPTIONS fallback pattern (line 372), but worth noting as an architectural choice — the worker's route_what::next → 404 handling becomes unreachable for 405-eligible paths.

Comment on lines +603 to +609
set_options_handler(
[](P& rp, std::string_view allow) -> route_task {
rp.status(status::no_content);
rp.res.set(field::allow, allow);
(void)(co_await rp.send());
co_return route_done;
});
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Default OPTIONS handler discards send error.

Same pattern as in http_worker.cpp — if rp.send() fails, the error is silently discarded and route_done is returned. This means the caller won't know the response wasn't actually sent. Low severity since OPTIONS responses are lightweight, but worth noting for consistency.

🤖 Prompt for AI Agents
In `@include/boost/http/server/router.hpp` around lines 603 - 609, The OPTIONS
handler currently ignores the result of co_await rp.send(), so send failures are
discarded; update the lambda passed to set_options_handler (the handler taking
P& rp) to capture the outcome of co_await rp.send(), check for an error, and
only co_return route_done on success—otherwise propagate or return an
error/failed route result so callers know the response wasn't sent (i.e., handle
rp.send()'s failure instead of discarding it after rp.status(status::no_content)
and rp.res.set(field::allow, allow)).

Comment on lines +291 to 297
// Collect methods from matching end-route matchers
if(m.end_)
{
options_methods |= m.allowed_methods_;
matched_methods |= m.allowed_methods_;
for(auto const& v : m.custom_verbs_)
options_custom_verbs.push_back(v);
matched_custom_verbs.push_back(v);
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Method collection runs unconditionally for every matching end-route matcher.

matched_methods and matched_custom_verbs accumulate from every end-route matcher whose path matches, even when the handler subsequently matches the method and runs. This is fine for the Allow header (you want all methods), but matched_custom_verbs is a std::vector<std::string> that may accumulate duplicates across matchers. The build_allow_header function doesn't deduplicate (unlike rebuild_global_allow_header which sorts/uniques). For routes with many custom verbs or overlapping matchers, the Allow header could contain duplicates.

Proposed fix — deduplicate before building
     if(is_options && matched_methods != 0 && options_handler_)
     {
+        std::sort(matched_custom_verbs.begin(), matched_custom_verbs.end());
+        matched_custom_verbs.erase(
+            std::unique(matched_custom_verbs.begin(), matched_custom_verbs.end()),
+            matched_custom_verbs.end());
         std::string allow = build_allow_header(matched_methods, matched_custom_verbs);
         co_return co_await options_handler_->invoke(p, allow);
     }

     // 405 fallback: path matched but method didn't
     if(!is_options &&
         (matched_methods != 0 || !matched_custom_verbs.empty()))
     {
+        std::sort(matched_custom_verbs.begin(), matched_custom_verbs.end());
+        matched_custom_verbs.erase(
+            std::unique(matched_custom_verbs.begin(), matched_custom_verbs.end()),
+            matched_custom_verbs.end());
         std::string allow = build_allow_header(matched_methods, matched_custom_verbs);
🤖 Prompt for AI Agents
In `@src/server/detail/router_base.cpp` around lines 291 - 297,
matched_custom_verbs is being appended from every matching end-route matcher
(inside the m.end_ branch) and can accumulate duplicates, causing duplicate
verbs in the Allow header because build_allow_header doesn't deduplicate; update
the logic after collecting from matchers (or immediately before calling
build_allow_header) to deduplicate matched_custom_verbs (e.g., sort and
std::unique or use an unordered_set) so only unique custom verbs are passed to
build_allow_header; keep collecting matched_methods as-is but ensure
matched_custom_verbs is de-duplicated similarly to rebuild_global_allow_header
to avoid repeated verbs in the header.

Comment on lines +375 to +384
// 405 fallback: path matched but method didn't
if(!is_options &&
(matched_methods != 0 || !matched_custom_verbs.empty()))
{
std::string allow = build_allow_header(matched_methods, matched_custom_verbs);
p.res.set(field::allow, allow);
p.res.set_status(status::method_not_allowed);
(void)(co_await p.send());
co_return route_done;
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

cat -n src/server/detail/router_base.cpp | sed -n '350,400p'

Repository: cppalliance/http

Length of output: 1718


🏁 Script executed:

# Search for matched_methods initialization and usage
rg -n 'matched_methods' src/server/detail/router_base.cpp -B2 -A2

Repository: cppalliance/http

Length of output: 1049


🏁 Script executed:

# Look for route_next and 405 related logic
rg -n 'route_next\|method_not_allowed' src/server/detail/router_base.cpp -B3 -A3

Repository: cppalliance/http

Length of output: 42


🏁 Script executed:

# Search for any tests related to this scenario
find . -name "*test*.cpp" -o -name "*_test.cpp" | xargs grep -l "route_next\|method_not_allowed" 2>/dev/null | head -5

Repository: cppalliance/http

Length of output: 42


🏁 Script executed:

cat -n src/server/detail/router_base.cpp | sed -n '200,310p'

Repository: cppalliance/http

Length of output: 4102


🏁 Script executed:

# Search for where the current request method is checked against allowed methods
rg -n 'pv\.verb_|allowed_methods' src/server/detail/router_base.cpp -B2 -A2

Repository: cppalliance/http

Length of output: 1227


🏁 Script executed:

# Look for the handler invocation and route_next handling
rg -n 'handler.*invoke|route_next' src/server/detail/router_base.cpp -B3 -A3

Repository: cppalliance/http

Length of output: 913


🏁 Script executed:

cat -n src/server/detail/router_base.cpp | sed -n '300,375p'

Repository: cppalliance/http

Length of output: 2412


🏁 Script executed:

# Look for where handlers are invoked in the loop
rg -n '\.invoke\(p' src/server/detail/router_base.cpp -B5 -A5

Repository: cppalliance/http

Length of output: 42


🏁 Script executed:

find . -type f -name "*.cpp" | xargs grep -l "405\|method_not_allowed" 2>/dev/null | head -10

Repository: cppalliance/http

Length of output: 327


🏁 Script executed:

# Search for test files related to router
find . -type f \( -name "*test*.cpp" -o -name "test_*.cpp" \) | head -10

Repository: cppalliance/http

Length of output: 88


🏁 Script executed:

# Look for tests that cover route_next behavior
rg -l 'route_next' --type=cpp | grep -i test | head -5

Repository: cppalliance/http

Length of output: 227


🏁 Script executed:

# Search for 405 tests in router test files
rg -n '405\|method_not_allowed' test/unit/server/router.cpp -B3 -A3

Repository: cppalliance/http

Length of output: 42


🏁 Script executed:

# Look for tests with route_next and method handling
rg -n 'route_next' test/unit/server/router.cpp -B5 -A5 | head -50

Repository: cppalliance/http

Length of output: 1615


🏁 Script executed:

# Search for test cases that test 405 or method_not_allowed behavior
rg -n 'TEST\|BOOST_AUTO_TEST\|method_not_allowed\|405' test/unit/server/router.cpp | head -30

Repository: cppalliance/http

Length of output: 42


🏁 Script executed:

# Look for tests combining route_next with method-specific routes
rg -n 'on.*GET\|on.*POST.*h_next\|\.get\(' test/unit/server/router.cpp -B2 -A2 | head -40

Repository: cppalliance/http

Length of output: 42


🏁 Script executed:

# Get an overview of router test structure
cat -n test/unit/server/router.cpp | head -150

Repository: cppalliance/http

Length of output: 5283


🏁 Script executed:

# Search for any tests involving method selection and route_next
rg -n 'get\(|post\(|put\(' test/unit/server/router.cpp | head -20

Repository: cppalliance/http

Length of output: 42


🏁 Script executed:

cat -n test/unit/server/router.cpp | sed -n '150,400p'

Repository: cppalliance/http

Length of output: 10382


🏁 Script executed:

# Look for test methods that test method-based routing
rg -n 'BOOST_FIXTURE_TEST_CASE|void|auto.*test' test/unit/server/router.cpp | grep -A2 'test' | head -30

Repository: cppalliance/http

Length of output: 604


🏁 Script executed:

cat -n test/unit/server/router.cpp | sed -n '394,470p'

Repository: cppalliance/http

Length of output: 2933


🏁 Script executed:

# Look for any 405-related test cases
rg -n 'status.*method\|method.*status\|405\|method_not_allowed' test/unit/server/router.cpp

Repository: cppalliance/http

Length of output: 42


🏁 Script executed:

rg -n '405\|method_not_allowed' test/unit/server/detail/router_base.cpp

Repository: cppalliance/http

Length of output: 42


🏁 Script executed:

# Check if there are tests that specifically test the scenario described in the bug
# (handler matches both path and method, returns route_next, then falls through)
cat -n test/unit/server/detail/router_base.cpp | head -100

Repository: cppalliance/http

Length of output: 3321


🏁 Script executed:

# Let me trace through the exact scenario: what is pv.verb_ and how is it set?
rg -n 'pv.verb_.*=' src/server/detail/router_base.cpp

Repository: cppalliance/http

Length of output: 190


🏁 Script executed:

# Examine the match_method function to understand how method matching works
rg -n 'match_method' src/server/detail/router_base.cpp -B5 -A10

Repository: cppalliance/http

Length of output: 509


🏁 Script executed:

# Let me understand the complete picture of route entry and what e.match_method does
rg -n 'match_method' src/server/ -B2 -A5 --type=cpp | head -50

Repository: cppalliance/http

Length of output: 967


🏁 Script executed:

# Find the router_entry structure to understand match_method
rg -n 'struct.*router_entry\|bool match_method' src/server/ --type=cpp -A5 | head -40

Repository: cppalliance/http

Length of output: 42


🏁 Script executed:

cat -n src/server/detail/router_base.hpp | sed -n '68,100p'

Repository: cppalliance/http

Length of output: 1066


🏁 Script executed:

# Get the complete router_entry structure
rg -n 'struct router_entry' src/server/detail/router_base.hpp -A20

Repository: cppalliance/http

Length of output: 42


🏁 Script executed:

# Now let me verify the complete picture: after handler returns route_next, is there any way
# the current request's method could be saved or flagged?
rg -n 'route_what::next' src/server/detail/router_base.cpp -B10 -A10

Repository: cppalliance/http

Length of output: 807


🏁 Script executed:

# Check if there's any tracking of whether current method was matched
rg -n 'current.*method\|method.*matched' src/server/detail/router_base.cpp -i

Repository: cppalliance/http

Length of output: 42


🏁 Script executed:

# Now let me verify the logic of the proposed fix by understanding pv.verb_ and matched_methods structure
cat -n src/server/detail/router_base.cpp | sed -n '206,220p'

Repository: cppalliance/http

Length of output: 625


🏁 Script executed:

# Understand the bit manipulation: how are methods stored in matched_methods?
rg -n '1ULL << static_cast' src/server/ --type=cpp -B2 -A2

Repository: cppalliance/http

Length of output: 1237


🏁 Script executed:

# Verify the complete scenario by creating a simple trace
cat > /tmp/verify_405.txt << 'EOF'
Scenario: GET handler at "/" returns route_next

1. Request: GET /
2. Path matching succeeds
3. matched_methods gets 0 (initially)
4. Loop iteration 1: find handler for GET /
   - Path matcher matches (end_ = true)
   - Line 294: matched_methods |= m.allowed_methods_ (now has GET bit set)
   - Line 299-304: e.match_method() returns true (GET == GET)
   - Line 319: Handler invoked, returns route_next
   - Line 330-333: Loop continues (++i)
5. No more handlers match
6. Loop exits
7. Line 376-384: 405 check fires
   - matched_methods != 0 (true - has GET bit)
   - is_options is false (true)
   - Condition is true, sends 405 Method Not Allowed
   - BUT: the request method WAS in matched_methods!

The bug: The 405 check never verifies that the CURRENT REQUEST'S METHOD
is absent from matched_methods. It only checks that SOME method was matched.
EOF
cat /tmp/verify_405.txt

Repository: cppalliance/http

Length of output: 910


🏁 Script executed:

# Verify the proposed fix checks the correct logic
cat > /tmp/verify_fix.txt << 'EOF'
Proposed fix logic:
1. method_is_matched = check if pv.verb_ is in matched_methods
2. For custom verbs: check if pv.verb_str_ is in matched_custom_verbs
3. Handle "all methods" case: matched_methods == ~0ULL
4. Only fire 405 if:
   - NOT is_options AND
   - NOT method_is_matched AND  <-- NEW: ensure current method isn't matched
   - (matched_methods != 0 OR !matched_custom_verbs.empty())

This is correct!
EOF
cat /tmp/verify_fix.txt

Repository: cppalliance/http

Length of output: 468


Bug: 405 fires incorrectly even when the request method IS in the matched set.

The 405 fallback at lines 376-384 checks only that matched_methods != 0 || !matched_custom_verbs.empty() but never verifies that the current request's method is absent from these sets. Consider a scenario where a GET handler for "/" returns route_next: the path matches, matched_methods accumulates the GET bit (line 294), the handler passes the method check (line 299), returns route_next (line 330), and the loop continues. After all entries are processed, the 405 check fires even though GET was in matched_methods — the response incorrectly sends 405 Method Not Allowed instead of falling through to route_next.

The condition must additionally verify that the current request's method is not in the matched set before returning 405.

Proposed fix
     // 405 fallback: path matched but method didn't
-    if(!is_options &&
-        (matched_methods != 0 || !matched_custom_verbs.empty()))
+    bool method_is_matched = false;
+    if(pv.verb_ != http::method::unknown)
+        method_is_matched = (matched_methods & (1ULL << static_cast<unsigned>(pv.verb_))) != 0;
+    else
+    {
+        for(auto const& v : matched_custom_verbs)
+        {
+            if(v == pv.verb_str_)
+            {
+                method_is_matched = true;
+                break;
+            }
+        }
+    }
+    // Also treat "all methods" as matching
+    if(matched_methods == ~0ULL)
+        method_is_matched = true;
+
+    if(!is_options && !method_is_matched &&
+        (matched_methods != 0 || !matched_custom_verbs.empty()))
     {
🤖 Prompt for AI Agents
In `@src/server/detail/router_base.cpp` around lines 375 - 384, The 405 fallback
fires even when the incoming request's method is present in matched_methods or
matched_custom_verbs; change the condition in the block that builds the Allow
header to also verify the current request method is NOT present before returning
405. Concretely, compute the method bit for the current request (e.g. method_bit
= method_to_bit(p.req.method) or similar) and only trigger the 405 when
!is_options && (matched_methods != 0 || !matched_custom_verbs.empty()) &&
((matched_methods & method_bit) == 0) && (matched_custom_verbs does not contain
the request method string); then call build_allow_header(matched_methods,
matched_custom_verbs), p.res.set_status(status::method_not_allowed) and send as
before (return route_done).

if(rv.what() == route_what::next)
{
rp.status(http::status::not_found);
(void)(co_await rp.send());
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Discarded send errors may leave the connection in a bad state.

Both (void)(co_await rp.send()) calls discard the error code. If the send fails (e.g., broken pipe), the loop proceeds to check keep_alive() and may attempt another request/response cycle on a broken stream. Consider breaking out of the loop on send failure, similar to how route handlers use co_return route_error(ec).

Also applies to: 90-90

🤖 Prompt for AI Agents
In `@src/server/http_worker.cpp` at line 84, The two discarded send results of
(co_await rp.send()) must be checked and handled: capture the await result into
an error variable when calling rp.send(), and if it indicates failure, break out
of the request loop or return early (e.g., co_return route_error(ec)) instead of
continuing to check keep_alive() and reuse the stream; apply this change to both
occurrences of rp.send() so failed sends do not allow another request/response
cycle on a broken connection.

@cppalliance-bot
Copy link

GCOVR code coverage report https://262.http.prtest3.cppalliance.org/gcovr/index.html
LCOV code coverage report https://262.http.prtest3.cppalliance.org/genhtml/index.html
Coverage Diff Report https://262.http.prtest3.cppalliance.org/diff-report/index.html

Build time: 2026-02-09 01:43:53 UTC

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants