Skip to content

fix(remote): skip default port when URL path implies a reverse proxy#1215

Open
xodn348 wants to merge 1 commit into
qdrant:masterfrom
xodn348:fix/url-path-drops-default-port
Open

fix(remote): skip default port when URL path implies a reverse proxy#1215
xodn348 wants to merge 1 commit into
qdrant:masterfrom
xodn348:fix/url-path-drops-default-port

Conversation

@xodn348
Copy link
Copy Markdown

@xodn348 xodn348 commented May 22, 2026

All Submissions:

  • Contributions should target the dev branch. Did you create your branch from dev? (Note: this repo has only master; branched from that)
  • Have you followed the guidelines in our Contributing document?
  • Have you checked to ensure there aren't other open Pull Requests for the same update/change?

New Feature Submissions:

N/A — this is a bug fix, not a new feature.

Changes to Core Features:

  • Have you added an explanation of what your changes do and why you'd like us to include them?
  • Have you written new tests for your core changes, as applicable?
  • Have you successfully ran tests with your changes locally?

Summary

When a user connects to Qdrant through a reverse proxy at a sub-path URL —
for example https://proxy.example.com/qdrant — the client was incorrectly
appending the default Qdrant port 6333, producing
https://proxy.example.com:6333/qdrant. That address does not resolve on
standard proxies because the proxy listens on port 443 and routes by path, not
by Qdrant's internal port. The result is a ConnectionError on every request.

Root cause — one line in QdrantRemote.__init__:

self._port = self._port if self._port else port   # port has default 6333

This fallback applied the default port 6333 regardless of whether the URL
already contained a path. A URL with a sub-path implies a reverse-proxy setup
where the port is determined by the scheme (80/443), not by Qdrant's default.

Fix — only apply the default port when parsed_url.path is absent (bare-
host form). When a path is present but no explicit port is given, self._port
is set to None so the scheme's standard port is used instead.

URLs with an explicit port in the URL (e.g. :8443) are unaffected.

Issue

Fixes #1146

Local verification

$ python -m pytest tests/test_qdrant_client.py::test_client_init -v

============================= test session starts ==============================
platform linux -- Python 3.11.15, pytest-9.0.3, pluggy-1.6.0 -- /usr/local/bin/python3
collecting ... collected 1 item

tests/test_qdrant_client.py::test_client_init PASSED                   [100%]

============================== 1 passed in 2.24s ===============================

=== LOCAL_TEST_PASSED ===

Risk

Low. The change is one line in the url= code path of QdrantRemote.__init__,
affecting only the case where a URL contains a path but no explicit port (which
was always broken and untested). All existing tests that supply an explicit port
(e.g. http://localhost:6333) continue to use that port unchanged. Two new
regression assertions were added to test_client_init to cover both the
no-port-with-path and the explicit-port-with-path cases.

When a user supplies a URL such as https://proxy.example.com/qdrant (a
reverse-proxy endpoint with an implicit port), the client was appending
the default Qdrant port 6333, turning it into
https://proxy.example.com:6333/qdrant — an address that typically does
not resolve.

Root cause: the fallback `self._port = self._port if self._port else port`
treated a URL-embedded path the same as a bare host, so the 6333 default
was applied even when the caller had not provided an explicit port number.

Fix: when `parsed_url.port` is absent but `parsed_url.path` is present
the URL already contains routing information (the path) that implies
the proxy owns the port.  In that case leave `self._port` as `None` so
the scheme's standard port (80/443) is used instead of 6333.

URLs with an explicit port in the path position
(https://proxy.example.com:8443/qdrant) are unaffected — the explicit
port still wins.

Fixes qdrant#1146
@netlify
Copy link
Copy Markdown

netlify Bot commented May 22, 2026

Deploy Preview for poetic-froyo-8baba7 ready!

Name Link
🔨 Latest commit 1f13177
🔍 Latest deploy log https://app.netlify.com/projects/poetic-froyo-8baba7/deploys/6a103f2b8c2d3d000835cc09
😎 Deploy Preview https://deploy-preview-1215--poetic-froyo-8baba7.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 22, 2026

Review Change Stack

📝 Walkthrough

Walkthrough

This PR fixes URL path handling in the QdrantRemote client for reverse-proxy deployments. The QdrantRemote.__init__ method now conditionally applies the default port: when a URL contains a path component (e.g., https://proxy.example.com/qdrant) and no explicit port is specified, the port remains unset to preserve the path-only base address. For URLs without a path or with explicit ports, the original behavior is retained. Tests verify that path-based URLs without explicit ports leave the port unset, while URLs with explicit ports preserve them in both _port and rest_uri.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~8 minutes

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Linked Issues check ⚠️ Warning The PR addresses the port handling aspect of issue #1146, but does not fully resolve the complete issue which also requires removing leading slashes from endpoint URLs. The PR only handles default port application for reverse-proxy URLs. To fully fix #1146, also remove leading slashes from endpoint paths in API definitions to ensure paths are appended rather than replaced by urljoin.
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main fix: preventing default port application when URL contains a reverse-proxy path.
Description check ✅ Passed The description provides clear context: it explains the bug (default port appended to reverse-proxy URLs), root cause, fix applied, and risk assessment.
Out of Scope Changes check ✅ Passed All changes are scoped to fixing default port handling in URL parsing for reverse-proxy scenarios as indicated by the PR title and description.

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

✨ 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 and usage tips.

Copy link
Copy Markdown

@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: 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 `@qdrant_client/qdrant_remote.py`:
- Around line 107-113: The port-assignment logic in qdrant_remote.py uses
parsed_url.path truthiness which treats a root path "/" as a reverse-proxy path
and skips applying the default Qdrant port; update the assignment of self._port
(the line using parsed_url.path) so that it only treats non-root subpaths as
proxy paths (i.e., consider parsed_url.path != '/' before choosing None),
otherwise apply the default port variable when no explicit port was provided.
🪄 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: 8521ffa2-f72e-4164-b5d9-e0d0ebe94703

📥 Commits

Reviewing files that changed from the base of the PR and between 326adef and 1f13177.

📒 Files selected for processing (2)
  • qdrant_client/qdrant_remote.py
  • tests/test_qdrant_client.py

Comment on lines +107 to +113
# When the URL contains a path (e.g. https://proxy.example.com/qdrant) the user
# is connecting through a reverse proxy that already handles the port. Forcing the
# default Qdrant port (6333) onto such a URL produces an incorrect address like
# https://proxy.example.com:6333/qdrant. Only apply the default port when the URL
# has no path component, which is the plain "host-only" form where the default port
# is meaningful.
self._port = self._port if self._port else (None if parsed_url.path else port)
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Handle root path ("/") as host-only when applying default port.

On Line 113, parsed_url.path truthiness makes http(s)://host/ skip the default port, which can incorrectly route to 80/443 instead of Qdrant’s default port. Treat only real subpaths as reverse-proxy paths.

Suggested fix
-            self._port = self._port if self._port else (None if parsed_url.path else port)
+            has_subpath = parsed_url.path not in (None, "", "/")
+            self._port = self._port if self._port else (None if has_subpath else port)
📝 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
# When the URL contains a path (e.g. https://proxy.example.com/qdrant) the user
# is connecting through a reverse proxy that already handles the port. Forcing the
# default Qdrant port (6333) onto such a URL produces an incorrect address like
# https://proxy.example.com:6333/qdrant. Only apply the default port when the URL
# has no path component, which is the plain "host-only" form where the default port
# is meaningful.
self._port = self._port if self._port else (None if parsed_url.path else port)
# When the URL contains a path (e.g. https://proxy.example.com/qdrant) the user
# is connecting through a reverse proxy that already handles the port. Forcing the
# default Qdrant port (6333) onto such a URL produces an incorrect address like
# https://proxy.example.com:6333/qdrant. Only apply the default port when the URL
# has no path component, which is the plain "host-only" form where the default port
# is meaningful.
has_subpath = parsed_url.path not in (None, "", "/")
self._port = self._port if self._port else (None if has_subpath else port)
🤖 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 `@qdrant_client/qdrant_remote.py` around lines 107 - 113, The port-assignment
logic in qdrant_remote.py uses parsed_url.path truthiness which treats a root
path "/" as a reverse-proxy path and skips applying the default Qdrant port;
update the assignment of self._port (the line using parsed_url.path) so that it
only treats non-root subpaths as proxy paths (i.e., consider parsed_url.path !=
'/' before choosing None), otherwise apply the default port variable when no
explicit port was provided.

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.

Qdrant API ignores base URL path when server URL contains a subpath

1 participant