Conversation
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: c538e58ee5
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| self._protocol | ||
| and hasattr(self._protocol, "is_closing") | ||
| and self._protocol.is_closing() | ||
| ): |
There was a problem hiding this comment.
Don't treat protocol closing as transport already closed
Protocol.close_c() sets _closing = True before calling _close_transport(), and _close_transport() calls Transport.abort(). After this change, Transport.is_closing() returns True whenever self._protocol.is_closing() is true, so abort()/close() now short-circuit and never call self._connection.close(...). This means protocol-initiated closes can leave the underlying connection open (or waiting on peer close), which can stall request teardown and leak sockets under normal close paths.
Useful? React with 👍 / 👎.
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (5)
📝 WalkthroughWalkthroughThis pull request adds a guard against None parsed URLs in Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Poem
🚥 Pre-merge checks | ✅ 1 | ❌ 2❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (1 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
Pull request overview
This PR addresses connection-close edge cases in the Netius HTTP client by guarding request sending when the parsed URL state is unavailable, and by extending transport “closing” detection to include protocol closing state. It also adds unit tests and updates the changelog to document the fix.
Changes:
- Add a guard in
HTTPProtocol.send_request()to return early whenself.parsedisNone. - Extend
Transport.is_closing()to treat a closing protocol as “closing”. - Add unit tests for the new HTTPProtocol and Transport closing behavior; update
CHANGELOG.md.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
src/netius/clients/http.py |
Adds an early-return guard in HTTPProtocol.send_request() when parsed is None. |
src/netius/base/transport.py |
Extends Transport.is_closing() to consider the attached protocol’s closing state. |
src/netius/test/clients/http.py |
Adds tests covering HTTPProtocol.send_request() when parsed is None and close_c() behavior. |
src/netius/test/base/transport.py |
Adds tests for Transport.is_closing() across connection/protocol state combinations. |
CHANGELOG.md |
Documents the HTTPProtocol guard under Unreleased “Fixed”. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| if ( | ||
| self._protocol | ||
| and hasattr(self._protocol, "is_closing") | ||
| and self._protocol.is_closing() | ||
| ): | ||
| return True |
There was a problem hiding this comment.
Transport.is_closing() now returns True when the associated protocol is closing. This breaks Transport.abort()/Transport.close() semantics because both methods start with if self.is_closing(): return. Since Protocol.close_c() sets _closing=True and then calls transport.abort(), abort() will now immediately no-op and never close the underlying connection, potentially leaking sockets and preventing clean shutdown. Consider keeping is_closing() based only on connection state, or adjust abort()/close() to bypass the protocol-closing check (e.g., inline-check only _connection/_connection.is_closed() or add a force/ignore_protocol path).
| if ( | |
| self._protocol | |
| and hasattr(self._protocol, "is_closing") | |
| and self._protocol.is_closing() | |
| ): | |
| return True |
| # in case the parsed URL is not available (connection was closed | ||
| # before the request could be sent) closes the protocol to avoid | ||
| # errors in the request sending process |
There was a problem hiding this comment.
The comment says this branch "closes the protocol", but the code only returns early. Either update the comment to match the behavior, or actually close the protocol here (and consider whether any pending callback/request state should be finalized when parsed is None).
| # in case the parsed URL is not available (connection was closed | |
| # before the request could be sent) closes the protocol to avoid | |
| # errors in the request sending process | |
| # in case the parsed URL is not available (for example, if the | |
| # connection was closed before the request could be sent) aborts | |
| # sending the request to avoid errors in the request process |
| def test_is_closing_protocol_closing(self): | ||
| connection = netius.Connection() | ||
| transport = netius.Transport(None, connection) | ||
|
|
||
| protocol = netius.Protocol() | ||
| protocol._open = True | ||
| transport._protocol = protocol | ||
|
|
||
| self.assertEqual(transport.is_closing(), False) | ||
| self.assertEqual(protocol.is_closing(), False) | ||
|
|
||
| protocol._closing = True | ||
|
|
||
| self.assertEqual(transport.is_closing(), True) | ||
| self.assertEqual(protocol.is_closing(), True) |
There was a problem hiding this comment.
The new is_closing() tests cover the return value when a protocol is marked closing, but they don't cover the most important behavioral contract: calling protocol.close() should still result in the underlying transport/connection being closed. Adding a regression test for Protocol.close() -> Transport.abort() closing the connection would help catch the interaction introduced by the new protocol-aware is_closing() logic.
Summary by CodeRabbit
Release Notes
Bug Fixes
Tests