Class: Trackdown::Providers::CloudflareProvider
- Inherits:
-
BaseProvider
- Object
- BaseProvider
- Trackdown::Providers::CloudflareProvider
- Defined in:
- lib/trackdown/providers/cloudflare_provider.rb
Overview
Provider that uses Cloudflare HTTP headers for IP geolocation This is the fastest and most lightweight option when your app is behind Cloudflare
Cloudflare must have "IP Geolocation" or "Add visitor location headers" enabled in the dashboard under Network settings or via Managed Transforms Exact header contract: https://developers.cloudflare.com/fundamentals/reference/http-headers/ Exact origin-protection guidance: https://developers.cloudflare.com/ssl/origin-configuration/authenticated-origin-pull/
Constant Summary collapse
- COUNTRY_HEADER =
'HTTP_CF_IPCOUNTRY'- CITY_HEADER =
'HTTP_CF_IPCITY'- REGION_HEADER =
'HTTP_CF_REGION'- REGION_CODE_HEADER =
'HTTP_CF_REGION_CODE'- LATITUDE_HEADER =
'HTTP_CF_IPLATITUDE'- LONGITUDE_HEADER =
'HTTP_CF_IPLONGITUDE'- TIMEZONE_HEADER =
'HTTP_CF_TIMEZONE'- CONTINENT_HEADER =
'HTTP_CF_IPCONTINENT'- METRO_CODE_HEADER =
'HTTP_CF_METRO_CODE'- POSTAL_CODE_HEADER =
'HTTP_CF_POSTAL_CODE'- UNKNOWN_CODE =
Cloudflare's XX and T1 pseudo-codes do not name countries. Unicode also defines ZZ as unknown/invalid territory, so none is treated as a country. Cloudflare: https://developers.cloudflare.com/fundamentals/reference/http-headers/#cf-ipcountry Unicode ZZ semantics: https://www.unicode.org/reports/tr35/tr35-78/tr35.html#unicode_region_subtag_validity
'XX'- UNKNOWN_OR_INVALID_TERRITORY_CODE =
'ZZ'- TOR_CODE =
'T1'
Class Method Summary collapse
-
.available?(request: nil) ⇒ Boolean
Check if Cloudflare headers are available in the request.
-
.locate(_ip, request: nil) ⇒ LocationResult
Locate IP using Cloudflare headers.
- .provider_name ⇒ Object
- .provider_source ⇒ Object
Methods inherited from BaseProvider
get_country_name, get_emoji_flag, parse_coordinate, request_provenance
Class Method Details
.available?(request: nil) ⇒ Boolean
Check if Cloudflare headers are available in the request
57 58 59 60 61 |
# File 'lib/trackdown/providers/cloudflare_provider.rb', line 57 def available?(request: nil) return false unless request !extract_country_code(request).nil? end |
.locate(_ip, request: nil) ⇒ LocationResult
Locate IP using Cloudflare headers
67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 |
# File 'lib/trackdown/providers/cloudflare_provider.rb', line 67 def locate(_ip, request: nil) raise Trackdown::Error, "CloudflareProvider requires a request object with Cloudflare headers" unless request provenance = request_provenance(request) country_code = extract_country_code(request) # If no valid country code, return unknown if country_code.nil? || country_code == UNKNOWN_CODE return LocationResult.unavailable(:provider_returned_unknown_country, **provenance) end country_name = get_country_name(country_code) city = extract_city(request) flag_emoji = get_emoji_flag(country_code) LocationResult.new( country_code, country_name, city, flag_emoji, region: extract_header(request, REGION_HEADER), region_code: extract_header(request, REGION_CODE_HEADER), continent: extract_header(request, CONTINENT_HEADER), timezone: extract_header(request, TIMEZONE_HEADER), latitude: parse_coordinate(request.env[LATITUDE_HEADER], range: LATITUDE_RANGE), longitude: parse_coordinate(request.env[LONGITUDE_HEADER], range: LONGITUDE_RANGE), postal_code: extract_header(request, POSTAL_CODE_HEADER), metro_code: extract_header(request, METRO_CODE_HEADER), # "T1" says the visitor came through Tor, which is precisely a country # Cloudflare could not determine. The code is kept, the claim is not. # Only Cloudflare's own two pseudo-codes are treated this way: a code # we simply haven't heard of (Kosovo's user-assigned "XK", say) is a # real answer, not an unresolved one. # https://developers.cloudflare.com/fundamentals/reference/http-headers/#cf-ipcountry unavailable_reason: (:provider_returned_unknown_country if country_code == TOR_CODE), **provenance ) end |
.provider_name ⇒ Object
48 49 50 |
# File 'lib/trackdown/providers/cloudflare_provider.rb', line 48 def provider_name :cloudflare end |
.provider_source ⇒ Object
52 53 54 |
# File 'lib/trackdown/providers/cloudflare_provider.rb', line 52 def provider_source :cloudflare_request_headers end |