Add SPOG support for ?o= routing in httpPath#1316
Open
msrathore-db wants to merge 6 commits intodatabricks:mainfrom
Open
Add SPOG support for ?o= routing in httpPath#1316msrathore-db wants to merge 6 commits intodatabricks:mainfrom
msrathore-db wants to merge 6 commits intodatabricks:mainfrom
Conversation
SPOG replaces workspace-specific hostnames with account-level vanity URLs. This requires workspace routing info (?o=<workspaceId> or x-databricks-org-id header) on all HTTP requests to the SPOG host. Fixes: 1. Property parser: use indexOf to split on first '=' only, so values containing '=' (like httpPath with ?o=) are preserved correctly (DatabricksConnectionContext.java) 2. Warehouse ID regex: (.+) -> ([^?&]+) to stop at query params (DatabricksJdbcConstants.java) 3. Auto-inject x-databricks-org-id header from ?o= in httpPath into custom headers map, propagating to Thrift, SEA, telemetry, and feature flags (DatabricksConnectionContext.java) 4. Propagate custom headers to telemetry and feature flag clients (TelemetryPushClient.java, DatabricksDriverFeatureFlagsContext.java) Co-authored-by: Isaac Signed-off-by: Madhavendra Rathore <madhavendra.rathore@databricks.com>
DBFSVolumeClient uses the SDK's ApiClient directly for /api/2.0/fs/* endpoints. These requests need the x-databricks-org-id header for SPOG routing, same as telemetry and feature flags. Add connectionContext.getCustomHeaders() to all 5 HTTP request paths in DBFSVolumeClient (4 sync via apiClient, 1 async via requestBuilder). Co-authored-by: Isaac Signed-off-by: Madhavendra Rathore <madhavendra.rathore@databricks.com>
ddcf35e to
df5451e
Compare
- Fix regex: ([^?&]+) -> ([^?&]+).* so warehouse/endpoint patterns match full JDBC URLs in isValidJdbcUrl() when ?o= is present. The trailing .* consumes remaining URL content for .matches() while [^?&]+ still stops at query params for .find() in buildCompute(). - Add SPOG URL test cases to ValidationUtilTest (3 new URLs with ?o=) - Add unit tests for buildPropertiesMap (property parser preserves ?o=) - Add unit tests for parseCustomHeaders (org-id extraction from ?o=, clean warehouse ID extraction, explicit header precedence) - Remove leftover SpogIntegrationTests.java from earlier exploration Co-authored-by: Isaac Signed-off-by: Madhavendra Rathore <madhavendra.rathore@databricks.com>
Existing tests create DBFSVolumeClient with a test constructor that sets connectionContext to null. Guard getCustomHeaders() calls with null check to avoid NPE in test paths while preserving SPOG header propagation in production paths. Co-authored-by: Isaac Signed-off-by: Madhavendra Rathore <madhavendra.rathore@databricks.com>
gopalldb
reviewed
Apr 7, 2026
| if (queryStart >= 0) { | ||
| String queryString = httpPath.substring(queryStart + 1); | ||
| for (String param : queryString.split("&")) { | ||
| String[] kv = param.split("=", 2); |
Collaborator
There was a problem hiding this comment.
use some Url parser utility for this
Collaborator
Author
There was a problem hiding this comment.
Updated to use URI builder. Thanks
Replace manual string splitting of ?o= from httpPath with Apache URIBuilder.getQueryParams() as suggested in code review. Signed-off-by: Madhavendra Rathore <madhavendra.rathore@databricks.com> Co-authored-by: Isaac Signed-off-by: Madhavendra Rathore <madhavendra.rathore@databricks.com>
a27cd13 to
0f16824
Compare
gopalldb
reviewed
Apr 7, 2026
| try { | ||
| for (NameValuePair param : | ||
| new URIBuilder("http://placeholder" + httpPath).getQueryParams()) { | ||
| if ("o".equals(param.getName()) |
gopalldb
reviewed
Apr 7, 2026
| } | ||
| } | ||
| } catch (URISyntaxException e) { | ||
| // Malformed httpPath — skip SPOG header extraction |
gopalldb
reviewed
Apr 7, 2026
| public static final Pattern HTTP_WAREHOUSE_PATH_PATTERN = Pattern.compile(".*/warehouses/(.+)"); | ||
| public static final Pattern HTTP_ENDPOINT_PATH_PATTERN = Pattern.compile(".*/endpoints/(.+)"); | ||
| public static final Pattern HTTP_WAREHOUSE_PATH_PATTERN = | ||
| Pattern.compile(".*/warehouses/([^?&]+).*"); |
Collaborator
There was a problem hiding this comment.
we also allow some other http paths, I guess /endpoints/ or something
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
SPOG (Single Panel of Glass) replaces workspace-specific hostnames with account-level vanity URLs. When httpPath contains
?o=<workspaceId>, the driver needs to:?o=value through URL parsing?o=) for SEA JSON bodyx-databricks-org-idheader on endpoints that don't carry?o=in the URL path (telemetry, feature flags, DBFS volume)Changes
Fix 1 — Property parser (
DatabricksConnectionContext.java):split("=")broke httpPath values containing=(e.g.httpPath=/sql/1.0/warehouses/xxx?o=yyysplit into 3 parts, dropping the workspace ID)indexOf("=")+substringto split on first=onlyFix 2 — Warehouse ID regex (
DatabricksJdbcConstants.java):(.+)capturedabc123?o=999as warehouse ID, corrupting SEA JSON body([^?]+).*to stop capture at query params.*needed because Java.matches()requires full-string matchFix 3 — SPOG header extraction (
DatabricksConnectionContext.java):URIBuilderto parse?o=<workspaceId>from httpPathx-databricks-org-idintocustomHeadersmapFix 4 — Header propagation (telemetry, feature flags, DBFS volume):
TelemetryPushClient.java: AddedconnectionContext.getCustomHeaders()to telemetry POSTDatabricksDriverFeatureFlagsContext.java: AddedconnectionContext.getCustomHeaders()to feature flag GETDBFSVolumeClient.java: AddedconnectionContext.getCustomHeaders()to all 5 HTTP request paths (4 sync + 1 async), with null guard for test constructorWhat does NOT get the header
OAuth endpoints (
/oidc/v1/token, OIDC discovery) — they are workspace-agnostic and rejectx-databricks-org-idwith HTTP 400. These use their own HTTP client and never seecustomHeaders.Context
Per the SPOG Peco Clients doc:
?o=in the POST URL handles routing naturallyx-databricks-org-idheader since they use separate endpoint pathsJira: XTA-15079
Test plan
Unit tests added:
testBuildPropertiesMap_preservesQueryParamInHttpPath— httpPath with?o=preservedtestBuildPropertiesMap_handlesValueWithMultipleEquals— values with multiple=preservedtestBuildPropertiesMap_handlesValueWithNoEquals— key-only params handledtestSpogContext_extractsOrgIdFromHttpPath—x-databricks-org-idextracted from?o=testSpogContext_extractsCleanWarehouseId— warehouse ID isabc123notabc123?o=...testSpogContext_noOrgIdWithoutQueryParam— no header injected for legacy URLstestSpogContext_explicitHeaderTakesPrecedence— explicithttp.header.x-databricks-org-idwins over?o=ValidationUtilTestE2E tested (not committed):
NO_CHANGELOG=true
This pull request was AI-assisted by Isaac.