Skip to content

Conversation

PR-HARIHARAN
Copy link

@PR-HARIHARAN PR-HARIHARAN commented Oct 4, 2025

Fix: Resolve shared httpx client base_url mutation across services

Overview

This PR resolves GitHub Issue #1244 - a critical bug where shared httpx.Client instances cause URL corruption between Supabase services (Storage, PostgREST, Functions). The issue occurred when multiple services mutated the same client's base_url property, causing API requests to hit wrong endpoints.

** Problem**: Storage calls would fail after accessing PostgREST, hitting /rest/v1/ instead of /storage/v1/
** Solution**: Implemented client isolation pattern with configuration preservation
** Result**: All services maintain correct URLs while preserving shared httpx configuration


🔍 Problem Analysis

Root Cause Identified

The bug occurred because multiple Supabase services shared the same httpx.Client instance and directly mutated its base_url property:

# ❌ BEFORE (Buggy Pattern)
if options.httpx_client:
    options.httpx_client.base_url = service_url  # Mutates shared client!
    return options.httpx_client

Impact:

  • Storage → PostgREST access would change storage client URL from /storage/v1/ to /rest/v1/
  • Subsequent storage operations would fail with 404 or unexpected responses
  • Functions and other services experienced similar cross-contamination
  • Users with custom httpx clients (timeouts, proxies, SSL) were most affected

Reproduction Confirmed

Created comprehensive test cases showing:

  • URL mutation between service accesses
  • Authentication header duplication issues
  • Configuration loss in shared clients

Technical Solution

Core Strategy: Client Isolation with Configuration Preservation

Instead of mutating shared clients, I implemented a pattern that creates isolated httpx.Client instances while preserving all shared configuration:

#  AFTER (Fixed Pattern)
if http_client is not None:
    # Create isolated client with preserved config
    merged_headers = {}
    merged_headers.update(service_headers)
    
    # Safely merge headers, avoiding auth duplication
    for key, value in http_client.headers.items():
        lower_key = key.lower()
        if lower_key not in ["authorization", "apikey", "x-client-info"]:
            if key not in merged_headers:
                merged_headers[key] = value
    
    return httpx.Client(
        base_url=service_url,
        headers=merged_headers,
        timeout=http_client.timeout,
        auth=http_client.auth,
        # ... preserve all configuration
    )

Key Benefits

  • Isolation: Each service gets its own httpx client
  • Preservation: All shared config (timeouts, SSL, proxy) maintained
  • Safety: No authentication header duplication
  • Compatibility: Zero breaking changes for existing code

Files Modified

Service Client Implementations (8 files)

  1. src/storage/src/storage3/_sync/client.py - Storage sync client isolation
  2. src/storage/src/storage3/_async/client.py - Storage async client isolation
  3. src/postgrest/src/postgrest/_sync/client.py - PostgREST sync client isolation
  4. src/postgrest/src/postgrest/_async/client.py - PostgREST async client isolation
  5. src/functions/src/supabase_functions/_sync/functions_client.py - Functions sync client isolation
  6. src/functions/src/supabase_functions/_async/functions_client.py - Functions async client isolation
  7. src/supabase/src/supabase/_sync/client.py - Main Supabase sync client coordination
  8. src/supabase/src/supabase/_async/client.py - Main Supabase async client coordination

Documentation Updates

  1. CHANGELOG.md - Comprehensive changelog entry with technical details

Dependencies

  1. uv.lock - Updated dependency lock file

Message to Maintainers:

@silentworks
@olirice

This is one of my first contributions to open source, and I’m excited to be part of the community. I’m open to any guidance, feedback, or improvements that can help me learn and make this contribution more valuable.


PR-HARIHARAN and others added 2 commits October 4, 2025 15:52
…vices

- Implement client isolation pattern for Storage, PostgREST, and Functions services
- Prevent URL corruption when multiple services share the same httpx.Client instance
- Preserve shared client configuration (timeout, headers, SSL, proxy) in isolated clients
- Add selective header merging to prevent authentication header duplication
- Maintain backward compatibility with existing user code

Fixes supabase#1244
Copy link
Contributor

@silentworks silentworks left a comment

Choose a reason for hiding this comment

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

Changelog should never be manually modified as it's handled by the release process. The other parts of this PR seems to be changing how base_url is handled on the http_client, this is not the approach we want to take on this. A PR was already opened for this which we are reviewing and are working on updating it.

Removed unreleased section detailing critical fixes and technical details.
@PR-HARIHARAN
Copy link
Author

Thank @silentworks for the clarification and guidance! 🙏
I’ve removed the changelog modifications as suggested. I’m still new to open source contributions, so I really appreciate your patience and feedback — it’s helping me understand the right practices.

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.

2 participants