Skip to content

feat(connection): add secure WebSocket (WSS) support with configurable connection host#434

Open
IMXEren wants to merge 2 commits into
autoscrape-labs:mainfrom
IMXEren:feat/connection
Open

feat(connection): add secure WebSocket (WSS) support with configurable connection host#434
IMXEren wants to merge 2 commits into
autoscrape-labs:mainfrom
IMXEren:feat/connection

Conversation

@IMXEren

@IMXEren IMXEren commented Jul 16, 2026

Copy link
Copy Markdown

Refactor connection address resolution to support connection_host, use_secure, and typed resolver parameters throughout the browser, tab, and connection stack.

Pull Request

Description

Related Issue(s)

Type of Change

  • Bug fix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Documentation update
  • Refactoring (no functional changes, no API changes)
  • Performance improvement
  • Tests (adding missing tests or correcting existing tests)
  • Build or CI/CD related changes

How Has This Been Tested?

# Include code examples if relevant

Testing Checklist

  • Unit tests added/updated
  • Integration tests added/updated
  • All existing tests pass

Screenshots

Implementation Details

API Changes

  • (BREAKING) Added connection_host and use_secure param across all browsers, Tab and ConnectionHandler.
  • (BREAKING) Added WSAddressResolverParams and now the ws address resolver callback expects it as arg only. Did it to make the params list non-exhaustive as well as more type checked. Note that the host maybe an ipv6 address hence, must be enclosed in [] before making any requests to it.
  • (BREAKING) get_browser_ws_address is updated to support the callback param.
  • (FIX) IFrameContextResolver is updated to also use host, use_secure and ws_address when creating browser_handler. Earlier even if you connected using .connect(ws_url), it only used the port to create the connection handler. Similar issue in Tab._collect_oopif_shadow_roots.
  • (FIX) _validate_ws_address now accepts ws address like ws://short allowing users to use wss://production-sfo.browserless.io?token=YOUR_API_TOKEN_HERE. No validation is done except for valid schemes and a non-empty hostname.

Additional Info

  • This PR adds feature from the PR Update Cloudflare and Connect #425 created by @realsirjoe. Credits to him for the feature idea.
  • I have manually ported the changes along with the fixes and some improvement on features, which I thought would be better.
  • Currently, I'm doing find-n-add wherever, connection_port was mentioned in docs.
  • I only know English, hence can only contribute to the docs using it.

Checklist before requesting a review

  • My code follows the style guidelines of this project
  • I have performed a self-review of my code
  • I have commented my code, particularly in hard-to-understand areas
  • I have made corresponding changes to the documentation
  • My changes generate no new warnings
  • I have added tests that prove my fix is effective or that my feature works
  • New and existing unit tests pass locally with my changes
  • I have run poetry run task lint and fixed any issues
  • I have run poetry run task test and all tests pass
  • My commits follow the conventional commits style

Summary by CodeRabbit

  • New Features

    • Added configurable CDP connection host support and secure WebSocket (wss://) support for Chrome and Edge.
    • Connection settings now propagate to tabs and iframe/OOPIF sessions, including correct scheme/port handling (with IPv6-safe formatting).
  • Bug Fixes

    • Improved WebSocket address validation and page-level WebSocket resolution.
    • Better propagation of connection options during reconnection and cross-origin iframe workflows.
  • Tests

    • Expanded unit and integration coverage for secure connections, custom hosts, IPv6 handling, and WebSocket validation.
  • Documentation

    • Updated connection-layer and browser/tab architecture docs to reflect the new initialization parameters.

…e connection host

Refactor connection address resolution to support `connection_host`,
`use_secure`, and typed resolver parameters throughout the browser, tab,
and connection stack.
@coderabbitai

coderabbitai Bot commented Jul 16, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Changes

The CDP connection flow now supports configurable hosts and secure WebSocket schemes. Browser, tab, and OOPIF handlers propagate these settings, while address resolution supports explicit schemes, default ports, IPv6 hosts, and typed resolver parameters.

CDP connection configuration

Layer / File(s) Summary
Connection handler and address resolution
pydoll/connection/..., pydoll/utils/general.py, docs/en/deep-dive/fundamentals/connection-layer.md
Connection handling and browser WebSocket resolution now use structured host, port, scheme, IPv6, and secure-transport parameters.
Browser and Chromium constructor propagation
pydoll/browser/chromium/..., docs/en/deep-dive/architecture/browser-domain.md
Browser, Chrome, and Edge accept and forward connection host and secure-transport settings; tab creation preserves them.
Tab and OOPIF connection propagation
pydoll/browser/tab.py, pydoll/interactions/iframe.py, docs/en/deep-dive/architecture/...
Nested tab and OOPIF handlers receive host, WebSocket, target, and secure connection settings.
Address validation and connection coverage
tests/unit/..., tests/integration/...
Tests cover supported schemes, host parsing, secure defaults, resolver behavior, IPv6 addresses, explicit wiring, and integration connections.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Browser
  participant ConnectionHandler
  participant Resolver
  participant CDPServer
  Browser->>ConnectionHandler: configure host, port, and secure scheme
  ConnectionHandler->>Resolver: request browser WebSocket address
  Resolver->>CDPServer: GET /json/version
  CDPServer-->>Resolver: return WebSocket debugger URL
  Resolver-->>ConnectionHandler: return resolved address
  ConnectionHandler-->>Browser: establish CDP connection
Loading

Possibly related PRs

Poem

I’m a rabbit with a WebSocket tune,
Hopping from host to host beneath the moon.
Secure paths sparkle bright,
IPv6 brackets fit just right.
Tabs and frames follow the trail—
CDP connections never fail!

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 39.47% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Description check ⚠️ Warning The template is mostly unfilled: Description, Related Issue(s), How Has This Been Tested?, and Implementation Details are left empty. Fill in the missing sections with a clear change summary, related issues, testing steps/results, and implementation details; keep API Changes and checklist.
✅ Passed checks (3 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Title check ✅ Passed The title is concise and accurately highlights the main change: secure WebSocket support with configurable connection host.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

@codecov

codecov Bot commented Jul 16, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 95.52239% with 3 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
pydoll/utils/general.py 80.00% 2 Missing ⚠️
pydoll/browser/chromium/edge.py 0.00% 1 Missing ⚠️

📢 Thoughts on this report? Let us know!

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@pydoll/browser/chromium/base.py`:
- Around line 1095-1097: Update start() to construct the initial Tab using the
propagated connection_host, connection_port, and use_secure kwargs, matching the
configuration passed to later tabs. Preserve the existing configured endpoint
behavior for subsequent tab creation.

In `@pydoll/connection/types.py`:
- Around line 20-22: Update the resolver contract fields in the connection types
definition so host is required and non-optional, using a string type while
preserving the existing required semantics. Keep port and use_secure unchanged,
matching ConnectionHandler’s localhost normalization invariant.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: e7e2584c-8ae6-4a2d-9491-4ad92d27c44b

📥 Commits

Reviewing files that changed from the base of the PR and between 1dc455d and d9fce3d.

📒 Files selected for processing (14)
  • pydoll/browser/chromium/base.py
  • pydoll/browser/chromium/chrome.py
  • pydoll/browser/chromium/edge.py
  • pydoll/browser/tab.py
  • pydoll/connection/connection_handler.py
  • pydoll/connection/types.py
  • pydoll/interactions/iframe.py
  • pydoll/utils/general.py
  • tests/integration/test_connection_handler.py
  • tests/unit/conftest.py
  • tests/unit/test_browser_commands.py
  • tests/unit/test_browser_wiring.py
  • tests/unit/test_connection_handler_unit.py
  • tests/unit/test_utils.py

Comment on lines +1095 to +1097
kwargs['connection_host'] = self._connection_host
kwargs['connection_port'] = self._connection_port
kwargs['use_secure'] = self._use_secure

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Use these propagated kwargs for the initial tab as well.

start() still constructs its initial Tab with only connection_port at Line 218. With a custom host or use_secure=True, that tab falls back to localhost/ws, while later tabs use the configured endpoint.

Proposed fix
-        tab = Tab(self, target_id=valid_tab_id, connection_port=self._connection_port)
+        tab = Tab(self, **self._get_tab_kwargs(valid_tab_id))
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pydoll/browser/chromium/base.py` around lines 1095 - 1097, Update start() to
construct the initial Tab using the propagated connection_host, connection_port,
and use_secure kwargs, matching the configuration passed to later tabs. Preserve
the existing configured endpoint behavior for subsequent tab creation.

Comment on lines +20 to +22
host: Required[Optional[str]]
port: Required[Optional[int]]
use_secure: Required[bool]

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win

Make host non-optional in the resolver contract.

get_browser_ws_address interpolates this value directly, so a type-valid host=None produces http(s)://None:.... ConnectionHandler already normalizes missing hosts to localhost; reflect that invariant here.

Proposed fix
-    host: Required[Optional[str]]
+    host: Required[str]
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
host: Required[Optional[str]]
port: Required[Optional[int]]
use_secure: Required[bool]
host: Required[str]
port: Required[Optional[int]]
use_secure: Required[bool]
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@pydoll/connection/types.py` around lines 20 - 22, Update the resolver
contract fields in the connection types definition so host is required and
non-optional, using a string type while preserving the existing required
semantics. Keep port and use_secure unchanged, matching ConnectionHandler’s
localhost normalization invariant.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs/en/deep-dive/fundamentals/connection-layer.md`:
- Around line 140-146: Align the documented connection contracts with the
implementation: in docs/en/deep-dive/fundamentals/connection-layer.md lines
140-146, mark connection_port and page_id as optional, use None for
browser-level page connections, and document ws_address precedence; in lines
159-161, change _connection_port to Optional[int]; in
docs/en/deep-dive/architecture/browser-domain.md lines 239-245, change
connection_host to Optional[str]; and in
docs/en/deep-dive/architecture/tab-domain.md lines 101-103, use str for the host
and bool for secure transport.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 7a9a6525-f314-4db5-babf-5a2be06f89e8

📥 Commits

Reviewing files that changed from the base of the PR and between d9fce3d and ba86be6.

📒 Files selected for processing (5)
  • docs/en/deep-dive/architecture/browser-domain.md
  • docs/en/deep-dive/architecture/find-elements-mixin.md
  • docs/en/deep-dive/architecture/tab-domain.md
  • docs/en/deep-dive/fundamentals/connection-layer.md
  • docs/en/deep-dive/fundamentals/iframes-and-contexts.md

Comment on lines +140 to +146
| `connection_host` | `str` | Host where the browser's CDP endpoint is listening |
| `connection_port` | `int` | Port number where the browser's CDP endpoint is listening |
| `page_id` | `str` | Identifier for the specific page/target (use 'browser' for browser-level connections) |
| `ws_address_resolver` | `Callable` | Function to resolve the WebSocket URL from the port number |
| `ws_address_resolver` | `Callable` | Function to resolve the WebSocket URL from the `WSAddressResolverParams` |
| `ws_connector` | `Callable` | Function to establish the WebSocket connection |
| `ws_address` | `str` | WebSocket address of browser's CDP endpoint for use with remote connections |
| `use_secure` | `bool` | Whether to establish a secure connection to the browser's CDP endpoint |

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Align all documented connection types and semantics with the implementation.

The new documentation currently mixes incorrect required types with the actual optional/string/boolean contract.

  • docs/en/deep-dive/fundamentals/connection-layer.md#L140-L146: document optional connection_port/page_id, use None for browser-level connections, and mention ws_address precedence.
  • docs/en/deep-dive/fundamentals/connection-layer.md#L159-L161: use Optional[int] for _connection_port.
  • docs/en/deep-dive/architecture/browser-domain.md#L239-L245: change connection_host to Optional[str].
  • docs/en/deep-dive/architecture/tab-domain.md#L101-L103: use str for the host and bool for secure transport.
📍 Affects 3 files
  • docs/en/deep-dive/fundamentals/connection-layer.md#L140-L146 (this comment)
  • docs/en/deep-dive/fundamentals/connection-layer.md#L159-L161
  • docs/en/deep-dive/architecture/browser-domain.md#L239-L245
  • docs/en/deep-dive/architecture/tab-domain.md#L101-L103
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/en/deep-dive/fundamentals/connection-layer.md` around lines 140 - 146,
Align the documented connection contracts with the implementation: in
docs/en/deep-dive/fundamentals/connection-layer.md lines 140-146, mark
connection_port and page_id as optional, use None for browser-level page
connections, and document ws_address precedence; in lines 159-161, change
_connection_port to Optional[int]; in
docs/en/deep-dive/architecture/browser-domain.md lines 239-245, change
connection_host to Optional[str]; and in
docs/en/deep-dive/architecture/tab-domain.md lines 101-103, use str for the host
and bool for secure transport.

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.

1 participant