Skip to content

thanhlv-com/proxy-queue

Repository files navigation

Proxy Queue 🚀

A high-performance Go-based middleware proxy server that supports HTTP, HTTPS, and raw socket connections with advanced queue-based request processing, comprehensive monitoring, and flexible configuration options.

Features

  • 🔗 Multi-protocol support: HTTP, HTTPS, and raw socket connections
  • 📥 Queue-based processing: All requests are queued and processed sequentially with configurable queue size and header-based routing
  • 🔒 Persistent headers: Force specific headers that cannot be overwritten by clients (e.g., User-Agent: mobile)
  • Configurable delays: Set random delays between requests (min/max range in milliseconds)
  • ⚙️ Flexible configuration: Environment variables and command-line flags with precedence handling
  • 🛡️ Connection management: Proper timeout handling, resource cleanup, and context-based cancellation
  • 📊 Prometheus metrics: Built-in metrics collection for monitoring request throughput, errors, and performance
  • ❤️ Health checks: Comprehensive health and readiness endpoints with detailed status information
  • 🌐 Flexible port configuration: Support for shared or dedicated ports for health checks and metrics
  • 📝 Structured logging: JSON-formatted logs with configurable levels and detailed request/response tracking
  • 🐳 Docker support: Ready-to-use Docker images with multi-stage builds and health checks
  • 🔧 Cross-platform builds: Support for multiple architectures (Linux, macOS, Windows on AMD64/ARM64)

Building

Prerequisites

  • Go 1.23.0 or later (using toolchain go1.24.7)
  • Make (optional, for using Makefile)
  • Docker and Docker Compose (optional, for containerized deployment)

Quick Build

# Build for current platform
go build -o proxy-queue main.go

# Or use Makefile
make build

Cross-Platform Building

Use the provided Makefile to build for different platforms:

# Build for specific platforms
make build-linux          # Linux x86_64
make build-linux-arm64     # Linux ARM64
make build-ubuntu          # Ubuntu (same as Linux x86_64)
make build-macos           # macOS x86_64
make build-macos-arm64     # macOS ARM64 (Apple Silicon)
make build-windows         # Windows x86_64
make build-windows-arm64   # Windows ARM64

# Build for all platforms
make build-all

# Create distribution packages
make dist

Available Make Targets

make help                  # Show all available targets
make clean                 # Clean build artifacts
make deps                  # Install dependencies
make test                  # Run tests
make test-race             # Run tests with race detection
make lint                  # Run linter (requires golangci-lint)
make fmt                   # Format code
make vet                   # Vet code
make dev                   # Development build with debug info
make install               # Install to GOPATH/bin
make info                  # Show build information
make check-version         # Check Go version compatibility

Usage

Basic Usage

# Run with default settings (proxy to localhost:443 with HTTPS)
./proxy-queue

# Run with custom target
./proxy-queue -target-host=example.com -target-port=8080

# Run with HTTPS target
./proxy-queue -target-host=api.example.com -target-port=443 -https=true

# Configure delays and queue size
./proxy-queue -delay-min=1000 -delay-max=3000 -queue-size=500

# Configure request timeout (30 seconds for all timeout types)
./proxy-queue -timeout=30 -target-host=api.example.com

# Set longer timeout for slow APIs (120 seconds)
./proxy-queue -timeout=120 -target-host=slow-api.example.com

# Configure header-based queues for AWS requests
./proxy-queue -header-queues="X-Amz-Security-Token,Authorization" -target-host=api.example.com

# Configure persistent headers that cannot be overwritten
./proxy-queue -persistent-headers="User-Agent:mobile,X-Source:proxy" -target-host=api.example.com

# Full configuration example with timeout and persistent headers
./proxy-queue -target-host=thanhlv.com -target-port=443 -port=6789 -delay-min=1 -delay-max=5 -timeout=60 -persistent-headers="User-Agent:mobile"

# Quick run with Makefile
make run                   # Build and run with defaults
make run-example           # Run with example configuration

Configuration Options 🌍

The application supports both environment variables (prioritized) and command line flags. Environment variables take precedence when both are provided.

Environment Variable Command Line Flag Default Description
PROXY_LISTEN_PORT -port 6789 Port to listen on
PROXY_TARGET_HOST -target-host localhost Target host to proxy to
PROXY_TARGET_PORT -target-port 443 Target port to proxy to
PROXY_DELAY_MIN -delay-min 1000 Minimum delay between requests (ms)
PROXY_DELAY_MAX -delay-max 5000 Maximum delay between requests (ms)
PROXY_USE_HTTPS -https true Use HTTPS for target connections
PROXY_MAX_QUEUE_SIZE -queue-size 1000 Maximum queue size
PROXY_METRICS_PORT -metrics-port 9090 Port for Prometheus metrics
PROXY_HEALTH_PORT -health-port 8081 Port for health checks
PROXY_LOG_LEVEL -log-level info Log level (debug, info, warn, error)
PROXY_SHARED_HEALTH_PORT -shared-health-port false Serve health checks on HTTP proxy port 🚩
PROXY_SHARED_METRICS_PORT -shared-metrics-port false Serve metrics on HTTP proxy port 📊
PROXY_HEADER_QUEUES -header-queues X-Amz-Security-Token Comma-separated headers for dedicated queues
PROXY_PERSISTENT_HEADERS -persistent-headers (empty) Persistent headers that cannot be overwritten 🔒
PROXY_TIMEOUT -timeout 0 Request timeout in seconds (0 = infinite ⏳)
PROXY_URL -proxy-url (empty) Proxy URL for TARGET_HOST connections 🌐
PROXY_AUTH -proxy-auth (empty) Proxy authentication (username:password) 🔐

Persistent Headers 🔒

The proxy supports adding persistent headers that are always included in outgoing requests and cannot be overwritten by clients. This is useful for enforcing specific headers like User-Agent, API keys, or authentication tokens that must remain constant.

Configuration Format

Persistent headers are configured using a comma-separated list of key:value pairs:

# Command line flag
./proxy-queue -persistent-headers "User-Agent:mobile,X-API-Version:v2.1,Authorization:Bearer fixed-token"

# Environment variable
export PROXY_PERSISTENT_HEADERS="User-Agent:mobile,X-API-Version:v2.1,Authorization:Bearer fixed-token"
./proxy-queue

Common Use Cases

Use Case Example Configuration Description
Mobile User Agent User-Agent:mobile Force all requests to appear as mobile
API Versioning X-API-Version:v2.1,Accept:application/json Enforce specific API version and content type
Fixed Authentication Authorization:Bearer token123 Use a fixed auth token that clients cannot override
Custom Headers X-Source:proxy-queue,X-Environment:production Add metadata headers for tracking

Security Features

  • Non-overwriteable: Client headers with the same name are ignored
  • Always applied: Persistent headers are added to every HTTP/HTTPS request
  • Debug logging: Header application is logged at debug level for troubleshooting
  • Flexible format: Supports any valid HTTP header name and value

Example Usage

# Ensure all requests use mobile user agent
./proxy-queue -persistent-headers "User-Agent:mobile" -target-host=api.example.com

# Multiple persistent headers
./proxy-queue -persistent-headers "User-Agent:mobile,X-Source:proxy,Accept:application/json"

# Environment variable approach
export PROXY_PERSISTENT_HEADERS="User-Agent:mobile,X-Custom:always-present"
./proxy-queue -target-host=api.example.com

Proxy Configuration 🌐

The proxy-queue can route all TARGET_HOST connections through an upstream proxy server. This is useful when your network requires proxy access to reach external services, or when you need to add an additional layer of routing.

Supported Proxy Types

Proxy Type URL Format Features
HTTP http://proxy.example.com:8080 ✅ HTTP requests
❌ Socket connections
HTTPS https://proxy.example.com:8080 ✅ HTTP requests
❌ Socket connections
SOCKS5 socks5://proxy.example.com:1080 ✅ HTTP requests
✅ Socket connections

Configuration Methods

# Command line flags
./proxy-queue \
  -target-host=api.example.com \
  -proxy-url=socks5://proxy.company.com:1080 \
  -proxy-auth=username:password

# Environment variables
export PROXY_URL=http://corporate-proxy:8080
export PROXY_AUTH=myuser:mypass
./proxy-queue -target-host=api.example.com

# Docker environment
docker run -e PROXY_URL=socks5://proxy:1080 -e PROXY_AUTH=user:pass proxy-queue

Authentication Support

The proxy supports username/password authentication for all proxy types:

# Include auth in URL (HTTP/HTTPS only)
export PROXY_URL=http://username:password@proxy.example.com:8080

# Separate auth parameter (recommended for security)
export PROXY_URL=socks5://proxy.example.com:1080
export PROXY_AUTH=username:password

Security Features

  • No credential logging: Proxy authentication is never logged in plaintext
  • Fallback behavior: If proxy connection fails, falls back to direct connection
  • Connection validation: Invalid proxy URLs are detected and logged
  • Debug visibility: Proxy usage is logged at debug level for troubleshooting

Proxy vs Direct Connection

Connection Type Proxy Required Fallback Behavior
HTTP/HTTPS Optional Falls back to direct connection
Socket Optional Falls back to direct connection
Both Optional Each connection type handles its own

Header-Based Queue Routing 📤

The proxy supports routing requests to dedicated queues based on specific HTTP headers. This is particularly useful for managing different authentication systems or API providers that require rate limiting.

Supported Headers by System

System Headers Description
AWS Services, claude cli 🔑 X-Amz-Security-Token Routes AWS API requests with temporary credentials or IAM authentication
ChatGPT/OpenAI 🤖 Authorization, OpenAI-Organization Handles OpenAI API requests with API keys and organization routing
Claude/Anthropic 🌐 Authorization, anthropic-version Manages Anthropic API requests with proper versioning
Google Cloud ☁️ Authorization, X-Goog-User-Project Routes Google Cloud API requests with project-specific billing
Azure 🟦 Authorization, Ocp-Apim-Subscription-Key Handles Azure API Management requests
Custom APIs 🔧 X-API-Key, Authorization, X-Custom-Token Generic headers for custom authentication systems

Configuration Examples

# AWS-specific configuration
./proxy-queue -header-queues="X-Amz-Security-Token,Authorization" -target-host=xxx

# Environment variable approach 
export PROXY_HEADER_QUEUES="Authorization,X-Amz-Security-Token,OpenAI-Organization"
./proxy-queue

How Header Routing Works

  1. Request Analysis: Incoming requests are inspected for configured headers
  2. Queue Selection: Requests with matching headers are routed to dedicated queues
  3. Isolated Processing: Each header-based queue processes requests independently
  4. Rate Limiting: Different queues can have different processing rates and delays
  5. Fallback: Requests without matching headers go to the main queue

Environment Configuration Example

# Copy and modify the example environment file
cp .env.example .env

# Or set environment variables directly
export PROXY_TARGET_HOST=api.example.com
export PROXY_TARGET_PORT=443
export PROXY_LOG_LEVEL=debug
export PROXY_HEADER_QUEUES=X-Amz-Security-Token
export PROXY_PERSISTENT_HEADERS="User-Agent:mobile,X-Source:proxy-queue"
export PROXY_TIMEOUT=45  # 45 seconds timeout for all operations
./proxy-queue

Service Ports

  • HTTP/HTTPS Proxy: Listens on the specified port (default: 6789) 🌐
  • Socket Proxy: Listens on the specified port + 10 (default: 6799)
  • Health Checks: Listens on health-port (default: 8081) OR on HTTP proxy port if -shared-health-port=true 🚩
  • Metrics: Listens on metrics-port (default: 9090) OR on HTTP proxy port if -shared-metrics-port=true 📊

Examples

HTTP Proxy

# Start proxy
./proxy-queue -target-host=httpbin.org -target-port=80 -https=false

# Test with curl
curl http://localhost:6789/get

HTTPS Proxy

# Start HTTPS proxy
./proxy-queue -target-host=httpbin.org -target-port=443 -https=true

# Test with curl
curl http://localhost:6789/get

Socket Proxy

# Start proxy
./proxy-queue -target-host=example.com -target-port=22

# Test with telnet or netcat (socket proxy runs on port + 10)
telnet localhost 6799

Health Checks and Metrics

Separate Ports (Default) 🔄

# Check application health
curl http://localhost:8081/health

# Check readiness
curl http://localhost:8081/ready

# View Prometheus metrics
curl http://localhost:9090/metrics

Shared Port Mode 🌐

# Start proxy with shared ports
./proxy-queue -shared-health-port=true -shared-metrics-port=true

# Check application health (now on proxy port)
curl http://localhost:6789/health

# Check readiness (now on proxy port)
curl http://localhost:6789/ready

# View Prometheus metrics (now on proxy port)
curl http://localhost:6789/metrics

Available Metrics

The application exposes the following Prometheus metrics:

  • proxy_requests_total (Counter): Total number of proxy requests processed
  • proxy_request_duration_seconds (Histogram): Duration of proxy requests in seconds
  • proxy_queue_size (Gauge): Current number of requests in queue
  • proxy_errors_total (Counter): Total number of proxy errors
  • proxy_concurrent_requests (Gauge): Number of concurrent requests being processed

These metrics can be scraped by Prometheus and visualized using Grafana dashboards.

Logging

The application uses structured JSON logging with the following features:

  • Configurable log levels: debug, info, warn, error
  • Request tracking: Each request gets a unique ID for end-to-end tracing
  • Detailed request/response logging: At debug level, full HTTP headers, bodies, and socket data are logged
  • Performance metrics: Request duration, queue length, and processing statistics
  • Connection details: Client IPs, connection states, and data transfer amounts

Example debug log output:

{
  "level": "debug",
  "msg": "📥 HTTP Request Details",
  "request_id": "http-1672531200123456789",
  "method": "GET",
  "url": "/api/data",
  "headers": { "User-Agent": "curl/7.81.0" },
  "remote_ip": "192.168.1.100",
  "timestamp": "2023-01-01T12:00:00.123456789Z"
}

Mixed Configuration

# Only health checks on shared port, metrics separate
./proxy-queue -shared-health-port=true

# Health checks on proxy port: http://localhost:6789/health
# Metrics still on separate port: http://localhost:9090/metrics

Development

# Development build with debug info
make dev

# Run tests
make test

# Run tests with race detection
make test-race

# Format and lint code
make fmt
make lint
make vet

How It Works

  1. Queue System: All incoming requests (HTTP, HTTPS, socket) are added to either the main queue or header-specific queues based on configured header routing
  2. Header-Based Routing: Requests with specific headers (e.g., X-Amz-Security-Token, Authorization) can be routed to dedicated queues for isolated processing
  3. Sequential Processing: Requests are processed one by one in FIFO order by dedicated goroutines for each queue
  4. Configurable Delays: After processing each request, the system waits for a random delay calculated between the configured min/max values
  5. Connection Forwarding:
    • HTTP/HTTPS requests are forwarded with proper header and body copying, including SSL/TLS support
    • Socket connections use bidirectional data copying with enhanced logging and error handling
  6. Request Tracking: Each request gets a unique ID for tracking throughout the processing pipeline
  7. Metrics Collection: Real-time metrics are collected for requests, errors, queue size, processing duration, and concurrent operations across all queues
  8. Health Monitoring: Continuous health status monitoring with automatic degradation detection based on error rates, including per-queue status

Docker Support 🐳

Quick Start with Docker

# Build and run with default configuration
docker-compose up --build

# Run in background
docker-compose up -d

# View logs
docker-compose logs -f proxy-queue

# Stop services
docker-compose down

Docker Compose Profiles

# Run with local development profile
docker-compose --profile local up

# Run with monitoring stack (Prometheus + Grafana)
docker-compose --profile monitoring up

# Run all services
docker-compose --profile local --profile monitoring up

Custom Docker Configuration

# Build custom image
docker build -t my-proxy-queue .

# Run with custom environment variables
docker run -d \
  -p 6789:6789 \
  -p 6799:6799 \
  -e PROXY_TARGET_HOST=api.example.com \
  -e PROXY_TARGET_PORT=443 \
  -e PROXY_LOG_LEVEL=debug \
  my-proxy-queue

Environment File for Docker

# Copy and modify environment file
cp .env.example .env

# Use with docker-compose
docker-compose --env-file .env up

Monitoring with Docker

Access the monitoring stack:

Architecture

Core Components

  • QueueManager: Main orchestrator managing multiple queues (main + header-based queues)
  • ProxyQueue: Individual queue manager with thread-safe operations, metrics collection, and request processing
  • Config: Configuration structure supporting both environment variables and command-line flags
  • HTTPRequestData/SocketRequestData: Type-safe request data structures with client information
  • ProxyRequest/ProxyResponse: Queue communication protocol with response channels
  • Metrics: Prometheus metrics collection with counters, histograms, and gauges (shared across queues)

Runtime Architecture

  • Main Goroutine: Configuration loading, server initialization, and coordination
  • Queue Manager: Orchestrates multiple queues and routes requests based on headers
  • Queue Processors: Dedicated goroutines for each queue (main + header-based) with sequential processing
  • HTTP Proxy Server: Goroutine handling HTTP/HTTPS requests on the main port with header-based routing
  • Socket Proxy Server: Goroutine handling raw socket connections on port+10 (uses main queue)
  • Health Server: Optional dedicated goroutine for health checks (port 8081)
  • Metrics Server: Optional dedicated goroutine for Prometheus metrics (port 9090)
  • Connection Handlers: Per-connection goroutines for socket bidirectional copying

Key Features

  • Context-based Cancellation: Proper shutdown handling across all components
  • Thread-safe Operations: Mutex-protected shared state and atomic counters
  • Request Identification: Unique request IDs with timestamp-based generation
  • Comprehensive Logging: Structured JSON logging with configurable levels and detailed request/response tracking
  • Error Handling: Graceful error recovery with metrics tracking and client notification
  • Resource Management: Proper connection cleanup and timeout handling

Dependencies

The project uses minimal external dependencies to ensure reliability and security:

All dependencies are automatically managed through Go modules (go.mod/go.sum).

Security & Performance Considerations

Security Features

  • TLS Support: Configurable HTTPS/TLS for target connections with InsecureSkipVerify option
  • Client IP Detection: Proper client IP extraction supporting X-Forwarded-For and X-Real-IP headers
  • Resource Limits: Configurable queue size limits to prevent memory exhaustion
  • Timeout Protection: Configurable timeouts for HTTP requests, socket connections, HTTP proxy responses, and socket connection handling - all customizable via -timeout flag. Note: There's a bug in the HTTP request timeout logic (main.go:787-788) where timeout=0 incorrectly sets 30s instead of infinite
  • Connection Cleanup: Proper resource cleanup and connection closing

Performance Optimizations

  • Buffered Channels: Queue implementation uses buffered channels for efficient request handling
  • Connection Pooling: HTTP client with configurable transport settings
  • Concurrent Processing: Separate goroutines for different protocol handlers
  • Memory Management: 32KB buffers for socket data copying to balance memory usage and performance
  • Atomic Operations: Lock-free counters for high-frequency metrics updates

Operational Considerations

  • Queue Sizing: Choose appropriate PROXY_MAX_QUEUE_SIZE based on expected load and available memory
  • Delay Configuration: Set PROXY_DELAY_MIN/PROXY_DELAY_MAX according to target server capacity
  • Timeout Configuration: Set appropriate PROXY_TIMEOUT values based on target server response times. Different timeout behavior:
    • HTTP client requests: Uses config.Timeout value (bug: timeout=0 sets 30s instead of infinite)
    • HTTP proxy responses: Uses config.Timeout value (timeout=0 sets 60min, >0 multiplies by seconds)
    • Socket connections: Uses config.Timeout value (timeout=0 sets 30min, >0 multiplies by seconds)
    • Socket connection handling: Uses config.Timeout value (timeout=0 uses config.Timeout as-is, >0 multiplies by seconds)
    • Note: The timeout logic has inconsistencies across different components
  • Log Level: Use debug level cautiously in production as it logs full request/response bodies
  • Health Checks: Configure monitoring systems to use /health and /ready endpoints
  • Resource Monitoring: Monitor queue size and error rate metrics for capacity planning