Class: Trackdown::Providers::AutoProvider

Inherits:
BaseProvider show all
Defined in:
lib/trackdown/providers/auto_provider.rb

Overview

Intelligent provider that automatically selects the best available provider Selection order:

  1. Use the single edge provider whose client-IP header matches the target IP.
  2. Try MaxMind, then return Unknown, when no edge provider can be verified.
  3. Fail closed when both edge providers appear valid; header names alone cannot distinguish an authentic stacked-CDN request from forwarded viewer input.

This is the recommended default for most applications

IMPORTANT: When there's an upstream proxy before the CDN (e.g., a legacy API gateway), the CDN's geo headers will reflect the proxy's location, not the real client. AutoProvider detects this by comparing the CDN's own view of the client IP (CF-Connecting-IP for Cloudflare, CloudFront-Viewer-Address for CloudFront) with the passed IP and falls back to MaxMind (or Unknown when MaxMind is unavailable) on a mismatch.

Cloudflare documents that CF-Connecting-IP is added only on edge-to-origin traffic: https://developers.cloudflare.com/fundamentals/reference/http-headers/#cf-connecting-ip AWS documents that the managed CloudFront policy forwards every viewer header, so CF-* names can still be viewer-controlled when they arrive through CloudFront: https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/using-managed-origin-request-policies.html#managed-origin-request-policy-all-viewer-and-cloudfront

Constant Summary collapse

CF_CONNECTING_IP_HEADER =
'HTTP_CF_CONNECTING_IP'
CLOUDFRONT_VIEWER_ADDRESS_HEADER =
'HTTP_CLOUDFRONT_VIEWER_ADDRESS'

Class Method Summary collapse

Methods inherited from BaseProvider

get_country_name, get_emoji_flag, parse_coordinate, request_provenance

Class Method Details

.available?(request: nil) ⇒ Boolean

Auto provider is available if at least one provider is available

Returns:

  • (Boolean)


54
55
56
57
58
# File 'lib/trackdown/providers/auto_provider.rb', line 54

def available?(request: nil)
  cloudflare_auto_available?(request) ||
    cloudfront_auto_available?(request) ||
    MaxmindProvider.available?(request: request)
end

.locate(ip, request: nil) ⇒ LocationResult

Intelligently locate IP using the best available provider

Parameters:

  • ip (String)

    The IP address to locate

  • request (ActionDispatch::Request, nil) (defaults to: nil)

    Optional Rails request object

Returns:



64
65
66
67
68
69
70
71
72
73
74
# File 'lib/trackdown/providers/auto_provider.rb', line 64

def locate(ip, request: nil)
  edge_provider = select_edge_provider(ip, request)
  return edge_provider.locate(ip, request: request) if edge_provider

  # Fall back to MaxMind if available
  return MaxmindProvider.locate(ip, request: request) if MaxmindProvider.available?(request: request)

  # No providers available - fail gracefully with a warning
  warn_no_providers
  LocationResult.unavailable(:no_provider_available)
end

.provider_nameObject

:auto has no identity of its own. Every result names whichever provider actually won, and a result with no provider at all names none.



45
46
47
# File 'lib/trackdown/providers/auto_provider.rb', line 45

def provider_name
  nil
end

.provider_sourceObject



49
50
51
# File 'lib/trackdown/providers/auto_provider.rb', line 49

def provider_source
  nil
end