A high-performance, intelligent caching proxy for Google Maps APIs built in Rust. GProxy sits between your applications and Google Maps APIs, providing Redis-based caching, retry logic, and cost optimization through intelligent response caching.
- πΊοΈ Google Maps API Proxy - Supports Geocoding, Directions, Distance Matrix, and Places APIs
- π Redis Caching - Intelligent caching with configurable TTLs per API endpoint
- π Smart Retry Logic - Exponential backoff with jitter for handling transient failures
- π° Cost Optimization - Reduces Google Maps API calls through strategic caching
- π TLS/HTTPS Support - Optional TLS configuration for secure communication
- π Observability - Comprehensive tracing, metrics, and structured logging
- β‘ Async/Await - Built on Tokio for high-performance async I/O
- π‘οΈ Graceful Shutdown - Proper signal handling and connection draining
- π§ Health Checks - Built-in health and readiness endpoints
- π CORS Support - Configurable Cross-Origin Resource Sharing
- π¦ Response Compression - Optional gzip/deflate compression
- π Google ToS Compliant - Respects Google's 30-day geocoding cache limit
- π Flexible API Key Handling - Supports both header-based and config-based API keys
- π·οΈ Cache Headers - Provides cache status information in responses
- π Rate Limit Aware - Intelligent handling of Google's rate limits
βββββββββββββββββββ βββββββββββββββββββ βββββββββββββββββββ
β Your App βββββΆβ GProxy βββββΆβ Google Maps β
β β β β β API β
β ββββββ Redis Cache ββββββ β
βββββββββββββββββββ βββββββββββββββββββ βββββββββββββββββββ
GProxy acts as an intelligent middleware that:
- Receives requests from your applications
- Checks Redis cache for existing responses
- On cache miss, forwards requests to Google Maps API
- Caches responses with appropriate TTLs
- Returns cached or fresh responses to clients
- Rust 1.70+
- Redis server
- Google Maps API key
git clone <repository-url>
cd gproxy
cargo build --release# Build the image
docker build -t gproxy .
# Run with environment variables
docker run -d \
-p 8080:8080 \
-e GOOGLE_API_KEY=your_api_key \
-e REDIS_HOST=redis_host \
gproxyGProxy is configured via environment variables:
# Server Configuration
GPROXY_ADDRESS=0.0.0.0:8080 # Server bind address
GPROXY_TLS_PATH=/path/to/certs # Optional TLS certificate path
GPROXY_OBS_ENDPOINT=http://jaeger:14268/api/traces # Observability endpoint
# Google Maps API
GOOGLE_API_KEY=your_google_maps_api_key
GOOGLE_BASE_URL=https://maps.googleapis.com/maps/api
GOOGLE_TIMEOUT_MS=1000 # Request timeout (1s)
GOOGLE_MAX_RETRIES=3 # Maximum retry attempts
GOOGLE_RATE_SEC=10 # Rate limit per second
# Redis Configuration
REDIS_HOST=127.0.0.1 # Redis server host
REDIS_PORT=6379 # Redis server port
REDIS_PREFIX=geo_cache # Cache key prefix
REDIS_POOL_SIZE=10 # Connection pool size
REDIS_TIMEOUT_MS=1000 # Redis operation timeout
# Cache TTL Configuration (seconds)
GOOGLE_TLS_GEOCODE=2592000 # 30 days (Google ToS requirement)
GOOGLE_TLS_DIRECTIONS=3600 # 1 hour
GOOGLE_TLS_DISTANCE_MATRIX=3600 # 1 hour
GOOGLE_TLS_PLACES=86400 # 24 hours
GOOGLE_TLS_DEFAULT=3600 # 1 hour
# Server Options
SERVER_ENABLE_COMPRESSION=true # Enable gzip/deflate compression
SERVER_CORS_ORIGINS=* # CORS origins (* for any)
SERVER_SHUTDOWN_TIMEOUT_SECS=30 # Graceful shutdown timeout
# Retry Configuration
GOOGLE_MAPS_MAX_RETRIES=3 # Maximum retry attempts
GOOGLE_MAPS_BASE_DELAY_MS=100 # Base retry delay
GOOGLE_MAPS_MAX_DELAY_MS=5000 # Maximum retry delay
GOOGLE_MAPS_EXPONENTIAL_BACKOFF=true # Use exponential backoff
GOOGLE_MAPS_USE_JITTER=true # Add jitter to retries
GOOGLE_MAPS_JITTER_PERCENT=25 # Jitter percentage (Β±25%)
GOOGLE_MAPS_RETRY_ON_RATE_LIMIT=true # Retry on rate limit errors
GOOGLE_MAPS_RATE_LIMIT_DELAY_MS=1000 # Rate limit retry delay# Basic startup
./gproxy
# With custom configuration
GOOGLE_API_KEY=your_key REDIS_HOST=localhost ./gproxy
# With TLS
GPROXY_TLS_PATH=/etc/ssl/certs ./gproxy
# Custom bind address
GPROXY_ADDRESS=0.0.0.0:9000 ./gproxyAll Google Maps API endpoints are available under /maps/api/:
# Geocoding API
GET /maps/api/geocode/json?address=1600+Amphitheatre+Parkway,+Mountain+View,+CA
# Directions API
GET /maps/api/directions/json?origin=Toronto&destination=Montreal
# Distance Matrix API
GET /maps/api/distancematrix/json?origins=Vancouver+BC&destinations=Seattle
# Places API - Find Place
GET /maps/api/place/findplacefromtext/json?input=Museum+of+Contemporary+Art+Australia&inputtype=textquery
# Places API - Place Details
GET /maps/api/place/details/json?place_id=ChIJN1t_tDeuEmsRUsoyG83frY4# Option 1: Use configured API key (from GOOGLE_API_KEY env var)
curl "http://localhost:8080/maps/api/geocode/json?address=Toronto"
# Option 2: Provide API key via header
curl -H "X-Maps-API-Key: your_api_key" \
"http://localhost:8080/maps/api/geocode/json?address=Toronto"# Health check (includes Redis connectivity)
GET /health
# Server information
GET /info
# Configuration dump
GET /config.jsonGProxy adds helpful headers to responses:
HTTP/1.1 200 OK
Content-Type: application/json
X-Cache-Status: HIT|MISS|ERROR
X-Cache-Key: geo_cache:geocode:abc123...gproxy/
βββ src/
β βββ main.rs # Application entry point
β βββ config/ # Configuration management
β β βββ mod.rs # CLI argument parsing
β β βββ retry.rs # Retry configuration
β βββ server/ # Server implementation
β βββ mod.rs # HTTP server & routing
β βββ google.rs # Google Maps API handler
β βββ service_state.rs # Service state management
βββ Cargo.toml # Dependencies & metadata
βββ build.rs # Build script
# Development build
cargo build
# Release build
cargo build --release
# Run tests
cargo test
# Run with cargo
cargo run -- --address 0.0.0.0:8080- axum - Web framework
- tokio - Async runtime
- fred - Redis client
- reqwest - HTTP client
- serde - Serialization
- tracing - Structured logging
- clap - CLI parsing
GProxy uses structured logging with tracing:
# Set log level
RUST_LOG=info ./gproxy
# Detailed logging
RUST_LOG=debug ./gproxy
# Module-specific logging
RUST_LOG=gproxy=debug,fred=info ./gproxy- OpenTelemetry integration for distributed tracing
- Automatic request/response metrics
- Cache hit/miss ratios
- Error rate monitoring
- Response time tracking
# Basic health check
curl http://localhost:8080/health
# Response includes Redis connectivity status
{
"server": "server-1",
"port": 8080,
"status": "healthy"
}# Place certificates in TLS path
/etc/ssl/certs/
βββ gproxy.crt # Certificate file
βββ gproxy.key # Private key file
# Start with TLS
GPROXY_TLS_PATH=/etc/ssl/certs ./gproxy- API keys can be provided via headers (recommended for multi-tenant scenarios)
- Environment variable configuration for single-tenant deployments
- No API keys are logged or exposed in responses
# Allow specific origins
SERVER_CORS_ORIGINS=https://yourdomain.com,https://app.yourdomain.com
# Allow any origin (development only)
SERVER_CORS_ORIGINS=*version: '3.8'
services:
gproxy:
build: .
ports:
- "8080:8080"
environment:
- GOOGLE_API_KEY=your_api_key
- REDIS_HOST=redis
- RUST_LOG=info
depends_on:
- redis
redis:
image: redis:7-alpine
ports:
- "6379:6379"
command: redis-server --appendonly yes
volumes:
- redis_data:/data
volumes:
redis_data:# Check Redis connectivity
redis-cli -h $REDIS_HOST ping
# Verify Google API key
curl "https://maps.googleapis.com/maps/api/geocode/json?address=Toronto&key=$GOOGLE_API_KEY"# Check Redis keys
redis-cli keys "geo_cache:*"
# Clear cache
redis-cli flushdb# Increase Redis pool size for high traffic
REDIS_POOL_SIZE=20
# Adjust retry settings
GOOGLE_MAPS_MAX_RETRIES=5
GOOGLE_MAPS_MAX_DELAY_MS=10000
# Enable compression for large responses
SERVER_ENABLE_COMPRESSION=true# Enable debug logging
RUST_LOG=debug ./gproxy
# Focus on specific modules
RUST_LOG=gproxy::server::google=trace,fred=debug ./gproxyGProxy respects Google's Terms of Service:
- Geocoding Cache Limit: 30 days maximum (configurable via
GOOGLE_TLS_GEOCODE) - Attribution: Responses maintain original Google attribution
- Rate Limiting: Intelligent retry handling respects API quotas
- Terms Compliance: No modification of response data
- Cache Keys: Generated using secure hashing of request parameters
- TTL Enforcement: Automatic expiration based on Google's requirements
- Cache Headers: Clear indication of cache status in responses
- Selective Caching: Only successful responses are cached
This project is licensed under the MIT License - see the LICENSE file for details.
- Google Maps Platform - For providing the underlying mapping APIs
- Rust Community - For the excellent ecosystem of crates
- Redis - For reliable caching infrastructure
GProxy - Making Google Maps APIs faster, cheaper, and more reliable! πΊοΈβ‘