Skip to content

RFC 6585 Compliance

ContextForge implements RFC 6585 HTTP status codes to ensure standards-compliant error handling and client interoperability.

Overview

RFC 6585 defines additional HTTP status codes for specific error conditions:

  • 428 Precondition Required - Server requires conditional request headers
  • 429 Too Many Requests - Rate limiting enforcement
  • 431 Request Header Fields Too Large - Header size validation
  • 511 Network Authentication Required - Captive portal authentication (not applicable to ContextForge)

429 Too Many Requests

Implementation

ContextForge uses 429 responses with RFC-compliant headers for rate limiting across multiple surfaces:

Middleware: RateLimitMiddleware Configuration: config.py

Response Headers

Per RFC 6585 § 4 and RFC 9110, 429 responses include:

HTTP/1.1 429 Too Many Requests
Retry-After: 60
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1234567890

Rate Limit Tiers

Tier Endpoints Default Limit Burst
CRITICAL /auth/email/*, /auth/sso/* 10 req/min 0
HIGH /tokens, /oauth, /rbac 30 req/min 0
MEDIUM /mcp, /tools, /prompts, /resources 100 req/min 20
LOW /health, /metrics, /docs 500 req/min 100

Configuration

# Enable rate limiting
RATE_LIMITING_ENABLED=true
RATE_LIMITING_REDIS_ENABLED=true

# Tier limits (requests per minute)
RATE_LIMIT_CRITICAL_RPM=10
RATE_LIMIT_HIGH_RPM=30
RATE_LIMIT_MEDIUM_RPM=100
RATE_LIMIT_LOW_RPM=500

# Lockout after excessive violations
RATE_LIMIT_LOCKOUT_ENABLED=true
RATE_LIMIT_LOCKOUT_THRESHOLD=5
RATE_LIMIT_LOCKOUT_DURATION_MINUTES=15

Example Response

{
  "error": "Rate limit exceeded",
  "message": "Maximum 100 requests per minute for MEDIUM tier endpoints.",
  "limit": 100,
  "reset_in_seconds": 60
}

Lockout Response

After exceeding the violation threshold on a tier, further requests from that client to the same tier are blocked for the lockout duration. The lockout is scoped to the tier that was abused (for example CRITICAL auth endpoints). Health, readiness, metrics, API docs and static asset paths are never locked out, but they remain subject to their ordinary per-minute limit.

{
  "error": "Rate limit lockout",
  "message": "Too many rate limit violations. Requests to CRITICAL tier endpoints are blocked for 15 minutes.",
  "lockout_duration_minutes": 15,
  "reset_in_seconds": 900
}

431 Request Header Fields Too Large

Implementation

ContextForge validates header sizes per RFC 6585 § 5 to prevent resource exhaustion attacks.

Middleware: HeaderSizeMiddleware Configuration: config.py

Validation Rules

  1. Total header size: All headers combined must not exceed max_header_total_size_bytes (default: 16KB)
  2. Individual field size: Each header field must not exceed max_header_field_size_bytes (default: 8KB)
  3. Header count: Total number of headers must not exceed max_header_count (default: 100)

Response Headers

Per RFC 6585 § 5, 431 responses include:

HTTP/1.1 431 Request Header Fields Too Large
Connection: close

The Connection: close header is included as recommended by RFC 6585 to prevent further requests on the same connection.

Configuration

# Enable header size validation
HEADER_SIZE_VALIDATION_ENABLED=true

# Size limits
MAX_HEADER_TOTAL_SIZE_BYTES=16384  # 16KB
MAX_HEADER_FIELD_SIZE_BYTES=8192   # 8KB
MAX_HEADER_COUNT=100

# Sanitization limit; raise field and total limits too for large OAuth tokens
MAX_HEADER_VALUE_LENGTH=4096       # 4KB

Example Responses

Too many headers:

{
  "error": "Request Header Fields Too Large",
  "message": "Too many header fields (105 > 100)",
  "violation_type": "header_count",
  "limits": {
    "max_total_size_bytes": 16384,
    "max_field_size_bytes": 8192,
    "max_header_count": 100
  }
}

Individual field too large:

{
  "error": "Request Header Fields Too Large",
  "message": "Header field 'X-Large-Header' exceeds maximum size (9000 > 8192 bytes)",
  "violation_type": "field_size",
  "field_name": "X-Large-Header",
  "limits": {
    "max_total_size_bytes": 16384,
    "max_field_size_bytes": 8192,
    "max_header_count": 100
  }
}

Total size too large:

{
  "error": "Request Header Fields Too Large",
  "message": "Total header size exceeds maximum (20000 > 16384 bytes)",
  "violation_type": "total_size",
  "limits": {
    "max_total_size_bytes": 16384,
    "max_field_size_bytes": 8192,
    "max_header_count": 100
  }
}

428 Precondition Required

Status

Not currently implemented - Reserved for future conditional request support.

Planned Use Cases

  • Optimistic locking for resource updates
  • Conditional tool execution based on resource state
  • ETag-based caching validation

Future Implementation

When implemented, 428 responses will require clients to include conditional headers:

HTTP/1.1 428 Precondition Required
{
  "error": "Precondition Required",
  "message": "This request requires conditional headers",
  "required_headers": ["If-Match", "If-Unmodified-Since"]
}

511 Network Authentication Required

Status

Not applicable - This status code is for captive portals and network-level authentication, which is outside the scope of ContextForge's application-layer authentication.

Cross-Surface Consistency

RFC 6585 status codes are consistently applied across all ContextForge surfaces:

REST API

All REST endpoints respect rate limiting and header size validation:

curl -X POST https://gateway.example.com/tools/execute \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json"
# Returns 429 if rate limited
# Returns 431 if headers too large

MCP Protocol

MCP endpoints (/mcp, /mcp/sse, /mcp/ws) enforce the same limits:

curl -X POST https://gateway.example.com/mcp \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json"
# Returns 429 if rate limited
# Returns 431 if headers too large

A2A (Agent-to-Agent)

A2A endpoints respect rate limiting for agent invocations:

curl -X POST https://gateway.example.com/a2a/agents/my-agent/invoke \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json"
# Returns 429 if rate limited

Client Handling

Retry Logic

Clients should implement exponential backoff when receiving 429 responses:

import time
import httpx

def make_request_with_retry(url, headers, max_retries=3):
    for attempt in range(max_retries):
        response = httpx.post(url, headers=headers)

        if response.status_code == 429:
            retry_after = int(response.headers.get("Retry-After", 60))
            print(f"Rate limited. Retrying after {retry_after}s...")
            time.sleep(retry_after)
            continue

        return response

    raise Exception("Max retries exceeded")

Header Size Management

Clients should monitor header sizes to avoid 431 responses:

def validate_headers(headers):
    total_size = sum(len(k) + len(v) + 2 for k, v in headers.items())

    if total_size > 16384:
        raise ValueError(f"Headers too large: {total_size} bytes")

    if len(headers) > 100:
        raise ValueError(f"Too many headers: {len(headers)}")

    for name, value in headers.items():
        field_size = len(name) + len(value) + 2
        if field_size > 8192:
            raise ValueError(f"Header '{name}' too large: {field_size} bytes")

Testing

Rate Limiting Tests

See test_rate_limit_middleware.py for comprehensive test coverage.

Header Size Tests

See test_header_size_middleware.py for validation tests.

Security Considerations

Rate Limiting

  • Multi-dimensional limiting: Enforced per IP, user, and team
  • Lockout protection: Temporary account lockout after excessive violations
  • Redis-backed: Distributed rate limiting across multiple gateway instances
  • Audit logging: All rate limit violations logged via SecurityLogger

Header Size Validation

  • DoS prevention: Prevents resource exhaustion from oversized headers
  • Early rejection: Headers validated before authentication/authorization
  • Connection closure: RFC-compliant connection management for 431 responses

Monitoring

Metrics

Rate limiting and header validation metrics are exposed via /metrics:

# Rate limit violations
http_requests_total{status="429",endpoint="/mcp"}

# Header size rejections
http_requests_total{status="431",endpoint="/tools"}

Logs

Structured logs include RFC 6585 status codes:

{
  "level": "warning",
  "message": "Rate limit exceeded",
  "status_code": 429,
  "client_ip": "203.0.113.1",
  "endpoint": "/mcp",
  "tier": "MEDIUM"
}

References