Skip to content

Commit 7c2e308

Browse files
feat(rust): add HTTP proxy support (#364)
## Summary - Add HTTP/HTTPS proxy support to the Rust ADBC driver via 4 new config parameters: - `databricks.http.proxy.url` — proxy URL (overrides `HTTP_PROXY`/`HTTPS_PROXY` env vars) - `databricks.http.proxy.username` / `password` — authenticated proxy support - `databricks.http.proxy.bypass_hosts` — comma-separated hosts to skip proxy - All changes scoped to `DatabricksHttpClient::new()` — proxy applies to all requests (SEA API, CloudFetch, OAuth) - Includes design spec, unit tests, e2e tests, and a new `rust-e2e.yml` CI workflow with Squid proxy sidecars ## Changes ### Core implementation (`rust/src/client/http.rs`) - New `ProxyConfig` struct with `url`, `username`, `password`, `bypass_hosts` - Added `proxy` field to `HttpClientConfig` - Updated `DatabricksHttpClient::new()` to conditionally configure `reqwest::Proxy` ### Config parsing (`rust/src/database.rs`) - `set_option` / `get_option_string` handlers for all 4 proxy parameters ### E2E tests (`rust/tests/proxy_e2e.rs`) - `test_connection_through_proxy` — unauthenticated Squid proxy - `test_connection_through_authenticated_proxy` — basic auth Squid proxy - `test_proxy_bypass_hosts` — verifies bypass list skips proxy ### CI workflow (`.github/workflows/rust-e2e.yml`) - New generic Rust e2e workflow (first job: proxy tests, extensible for future e2e jobs) - Squid service container (unauthenticated) + docker run step (authenticated proxy with custom config) - Squid access log verification to prove traffic actually routed through proxy ## Test plan - [x] Unit tests pass (`cargo test` — 236 passed) - [x] Clippy clean (`cargo clippy --all-targets -- -D warnings`) - [x] Format clean (`cargo +stable fmt --all`) - [x] E2E/Proxy CI job passes (3 tests against real Databricks through Squid proxies) This pull request was AI-assisted by Isaac.
1 parent 656960d commit 7c2e308

File tree

9 files changed

+1155
-7
lines changed

9 files changed

+1155
-7
lines changed

.github/workflows/rust-e2e.yml

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
# Copyright (c) 2025 ADBC Drivers Contributors
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
name: Rust E2E Tests
16+
17+
on:
18+
push:
19+
branches:
20+
- main
21+
paths:
22+
- "rust/**"
23+
- .github/workflows/rust-e2e.yml
24+
pull_request:
25+
branches:
26+
- main
27+
paths:
28+
- "rust/**"
29+
- .github/workflows/rust-e2e.yml
30+
31+
concurrency:
32+
group: ${{ github.repository }}-${{ github.head_ref || github.sha }}-rust-e2e
33+
cancel-in-progress: true
34+
35+
defaults:
36+
run:
37+
shell: bash
38+
39+
jobs:
40+
proxy:
41+
name: "Proxy"
42+
runs-on: ubuntu-latest
43+
env:
44+
DATABRICKS_HOST: ${{ secrets.DATABRICKS_HOST }}
45+
DATABRICKS_HTTP_PATH: ${{ secrets.TEST_PECO_WAREHOUSE_HTTP_PATH }}
46+
DATABRICKS_TEST_CLIENT_ID: ${{ secrets.DATABRICKS_TEST_CLIENT_ID }}
47+
DATABRICKS_TEST_CLIENT_SECRET: ${{ secrets.DATABRICKS_TEST_CLIENT_SECRET }}
48+
49+
services:
50+
# Unauthenticated forward proxy (no volume mounts needed)
51+
squid:
52+
image: ubuntu/squid:latest
53+
ports:
54+
- 3128:3128
55+
56+
steps:
57+
- uses: actions/checkout@v4
58+
with:
59+
fetch-depth: 0
60+
persist-credentials: false
61+
62+
# Start authenticated proxy after checkout so config files are available
63+
- name: Start authenticated proxy
64+
run: |
65+
docker run -d --name squid-auth \
66+
-p 3129:3128 \
67+
-v ${{ github.workspace }}/rust/ci/proxy/squid-auth.conf:/etc/squid/squid.conf \
68+
-v ${{ github.workspace }}/rust/ci/proxy/htpasswd:/etc/squid/htpasswd \
69+
ubuntu/squid:latest
70+
# Wait for squid to be ready
71+
for i in $(seq 1 10); do
72+
if docker exec squid-auth squid -k check 2>/dev/null; then
73+
echo "Authenticated proxy is ready"
74+
break
75+
fi
76+
echo "Waiting for authenticated proxy to start... ($i/10)"
77+
sleep 1
78+
done
79+
80+
- uses: actions-rust-lang/setup-rust-toolchain@v1
81+
82+
- name: Run proxy E2E tests
83+
working-directory: rust
84+
run: cargo test --test proxy_e2e -- --ignored --nocapture
85+
86+
- name: Verify proxy was used (unauthenticated)
87+
if: always()
88+
run: |
89+
docker logs $(docker ps -q --filter "publish=3128") 2>&1 \
90+
| grep -i "CONNECT" \
91+
|| (echo "FAIL: No CONNECT entries found in squid logs — proxy was not used" && exit 1)
92+
93+
- name: Verify proxy was used (authenticated)
94+
if: always()
95+
run: |
96+
docker logs squid-auth 2>&1 \
97+
| grep -i "CONNECT" \
98+
|| (echo "FAIL: No CONNECT entries found in squid-auth logs — proxy was not used" && exit 1)
99+
100+
- name: Cleanup authenticated proxy
101+
if: always()
102+
run: docker rm -f squid-auth 2>/dev/null || true
103+
104+
# Future e2e jobs can be added here, e.g.:
105+
# cloudfetch:
106+
# name: "E2E/CloudFetch"
107+
# ...

.rat-excludes

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,3 +37,5 @@ test-infrastructure/proxy-server/generated/**
3737
rust/Cargo.lock
3838
rust/license.tpl
3939
rust/pixi.lock
40+
# htpasswd is a data file (username:password_hash) that cannot contain license headers
41+
rust/ci/proxy/htpasswd

rust/ci/proxy/htpasswd

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
testuser:$1$7dnCQ2ZE$C5gL4sx7Ur/HH/Vsx5wRV.

rust/ci/proxy/squid-auth.conf

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
# Copyright (c) 2025 ADBC Drivers Contributors
2+
#
3+
# Licensed under the Apache License, Version 2.0 (the "License");
4+
# you may not use this file except in compliance with the License.
5+
# You may obtain a copy of the License at
6+
#
7+
# http://www.apache.org/licenses/LICENSE-2.0
8+
#
9+
# Unless required by applicable law or agreed to in writing, software
10+
# distributed under the License is distributed on an "AS IS" BASIS,
11+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
# See the License for the specific language governing permissions and
13+
# limitations under the License.
14+
15+
# Squid configuration for authenticated proxy testing.
16+
# Requires basic auth using credentials from htpasswd file.
17+
18+
auth_param basic program /usr/lib/squid/basic_ncsa_auth /etc/squid/htpasswd
19+
auth_param basic realm Proxy Auth Required
20+
auth_param basic credentialsttl 1 hour
21+
22+
acl authenticated proxy_auth REQUIRED
23+
http_access allow authenticated
24+
http_access deny all
25+
26+
http_port 3128

0 commit comments

Comments
 (0)