Advanced Usage#

Using the SDK Context and HTTP Client#

The EarthScope SDK provides access to its underlying HTTP client and authentication context, allowing you to make custom requests to EarthScope’s APIs while still benefiting from the SDK’s credential management.

Context and Resource Management#

The SDK’s context (ctx) holds shared resources that are more efficient when reused across multiple requests:

from earthscope_sdk import AsyncEarthScopeClient

# Create a single client and reuse its context
with AsyncEarthScopeClient() as client:
    ctx = client.ctx
    
    # The context manages shared resources:
    # - HTTP client with connection pooling (ctx.httpx_client)
    # - Authentication state and token cache (ctx.auth_flow)
    # - Configuration settings (ctx.settings)

Benefits of reusing the context:

  1. Connection Pooling

    • The HTTP client maintains a pool of connections

    • Reuses connections for multiple requests

    • Reduces connection establishment overhead

    • Improves performance for multiple requests

  2. Token Caching

    • Authentication tokens are cached in the context

    • Avoids unnecessary token refreshes

    • Reduces authentication overhead

    • Maintains session state

  3. Resource Efficiency

    • Single configuration load

    • Shared settings across requests

    • Reduced memory usage

    • Better resource utilization

Making Custom HTTP Requests#

You can use the EarthScope SDK’s HTTPx client to make custom requests. The client automatically handles:

  • Authentication headers

  • Token refresh

See the HTTPx documentation for details on their client implementation.

import asyncio

from earthscope_sdk import AsyncEarthScopeClient

async def main():
    async with AsyncEarthScopeClient() as client:
        # Create a custom request
        request = client.ctx.httpx_client.build_request(
            "GET",
            f"{client.ctx.settings.resources.api_url}/custom/endpoint",
            params={"param": "value"}
        )
        
        # Send the request using the SDK's client
        response = await client.ctx.httpx_client.send(request)
        response.raise_for_status()
        
        # Process the response
        data = response.json()

asyncio.run(main())

Building Requests Properly#

When making custom requests, always use the HTTPx client’s build_request() method to ensure proper URL construction and parameter encoding (e.g. handling spaces or special characters, and multi-valued parameters):

client: AsyncEarthScopeClient  # defined previously

# Using build_request ensures proper URL construction
request = client.ctx.httpx_client.build_request(
    "GET",
    f"{client.ctx.settings.resources.api_url}/foo",
    params={
        "start_time": "2024-01-01T00:00:00",
        "things": ["thing1", "thing2"],
    }
)

# The request will have properly encoded query parameters:
# /foo?start_time=2024-01-01T00%3A00%3A00&things=thing1&things=thing2

response = await client.ctx.httpx_client.send(request)
response_body = response.json()

Using Authentication Flow#

You can also directly use the authentication flow to get tokens for custom use:

from earthscope_sdk import AsyncEarthScopeClient

with AsyncEarthScopeClient() as client:
    # Refresh the access token if it is past or near expiration
    await client.ctx.auth_flow.async_refresh_if_necessary()

    # Get the current access token
    access_token = client.ctx.auth_flow.access_token
    
    # Check token expiration
    expires_at = client.ctx.auth_flow.expires_at
    
    # Force token refresh
    await client.ctx.auth_flow.async_refresh()

Best Practices#

  1. Use the SDK’s Client

    • Always use ctx.httpx_client instead of creating your own

    • This ensures consistent authentication and error handling

      • Let the SDK manage token refresh

      • Don’t manually set Authorization headers

  2. Use Settings

    • Access API URLs through ctx.settings.resources

    • This ensures correct endpoints are used

  3. Error Handling

    • Catch and handle SDK-specific errors

    • Use the built-in retry logic

  4. Resource Cleanup

    • Use context managers (with statements)

    • Ensure proper cleanup of resources

  5. Context Reuse

    • Create a single context for multiple requests

    • Share the context across related operations

    • Avoid creating multiple contexts unnecessarily

  6. Request Building

    • Always use build_request() for creating requests

    • Let the client handle URL encoding and parameter formatting

    • Avoid manual URL construction

    • Use the params argument for query parameters