エッジでの地理的ルーティング: コンテンツのパーソナライゼーションと GDPR への準拠
国、地域、言語に基づいてルーティング ロジックを構築する方法を学びます Workers で直接、ジオフェンシングの例、ローカライズされた価格 メインサーバーを変更せずに GDPR に準拠します。
地理的ルーティングがエッジに属する理由
地理的位置に基づいてコンテンツをパーソナライズすることは、その 1 つです。 グローバル Web アプリケーションで最も一般的なニーズ: に価格を表示する 現地通貨、国固有の規制に準拠 (ヨーロッパの GDPR、 カリフォルニア州の CCPA)、特定の法域でのコンテンツのブロック、およびリダイレクト 地域ドメインに向けて。
従来、これはサーバー側の地理位置情報データベースで処理されていました。 (MaxMind GeoLite2)、または手動で構成された CDN ルールを使用します。どちらのアプローチも これらには制限があります。データベース サーバーにより待ち時間が追加され、CDN ルールは静的です。 動的に更新することは困難です。
Cloudflare Workers では、地理位置情報が すでに利用可能です
オブジェクトの中で request.cf データベースを維持する必要はありません。
CloudflareはネットワークのBGPトポロジに基づいて場所を決定します。
IP ルックアップではなく、国レベルの精度が 99.9% 以上です。
何を学ぶか
- で利用可能なプロパティ
request.cf地理位置情報用 - ジオフェンシング: 国ごとのブロックとリダイレクト
- ローカライズされた価格設定: 地域に基づいた通貨と VAT
- GDPR 準拠: EU ユーザー向けの自動 Cookie 同意
- カスタムヘッダーを使用したマルチリージョンルーティング
- 導入せずに地理ベースのロジックをテストする
オブジェクト request.cf アーティスト: クラウドフレア
Cloudflare Workerへの各リクエストには件名が含まれます cf と
Cloudflareによってリアルタイムで決定される地理およびネットワークのメタデータ:
// Tutte le proprieta disponibili in request.cf
export default {
async fetch(request: Request): Promise<Response> {
const cf = request.cf as CfProperties;
// Geolocalizzazione
const country = cf.country; // "IT" - ISO 3166-1 alpha-2
const region = cf.region; // "Puglia" - nome della regione
const regionCode = cf.regionCode; // "75" - codice regione
const city = cf.city; // "Bari"
const postalCode = cf.postalCode; // "70121"
const latitude = cf.latitude; // "41.1171"
const longitude = cf.longitude; // "16.8719"
const timezone = cf.timezone; // "Europe/Rome"
const continent = cf.continent; // "EU"
// Rete
const asn = cf.asn; // 1234 - Autonomous System Number
const asOrganization = cf.asOrganization; // "Telecom Italia"
const isEuCountry = cf.isEUCountry; // "1" o "0"
// Performance
const colo = cf.colo; // "FCO" - datacenter Cloudflare piu vicino
const httpProtocol = cf.httpProtocol; // "HTTP/2"
const tlsVersion = cf.tlsVersion; // "TLSv1.3"
return Response.json({
country,
region,
city,
timezone,
continent,
isEuCountry,
colo,
});
},
};
// Tipo per le proprieta cf (parziale)
interface CfProperties {
country?: string;
region?: string;
regionCode?: string;
city?: string;
postalCode?: string;
latitude?: string;
longitude?: string;
timezone?: string;
continent?: string;
asn?: number;
asOrganization?: string;
isEUCountry?: string;
colo?: string;
httpProtocol?: string;
tlsVersion?: string;
}
ジオフェンシング: 国ごとのブロック
ジオフェンシングは、コンテンツをブロックまたは特定のコンテンツにリダイレクトするパターンです。 国々。最も一般的な使用例は次のとおりです: 国際制裁のためのブロック、 地域ライセンスのあるコンテンツ (ストリーミング、メディア)、およびまだ市場が確立されていない 特定の製品にオープン:
// src/geo-fence-worker.ts
// Paesi con accesso bloccato (esempio: sanzioni, licenze)
const BLOCKED_COUNTRIES = new Set(['KP', 'IR', 'SY', 'CU']);
// Paesi che richiedono un redirect a una versione localizzata
const REDIRECTS: Record<string, string> = {
DE: 'https://de.example.com',
FR: 'https://fr.example.com',
JP: 'https://jp.example.com',
};
export default {
async fetch(request: Request, env: Env): Promise<Response> {
const cf = request.cf as CfProperties;
const country = cf.country ?? 'US';
const url = new URL(request.url);
// Blocco per paesi non consentiti
if (BLOCKED_COUNTRIES.has(country)) {
return new Response(
JSON.stringify({
error: 'Service not available in your region',
country,
}),
{
status: 451, // 451 Unavailable For Legal Reasons
headers: {
'Content-Type': 'application/json',
'Vary': 'CF-IPCountry',
},
}
);
}
// Redirect verso versione localizzata per certi paesi
const redirectTarget = REDIRECTS[country];
if (redirectTarget && !url.pathname.startsWith('/api/')) {
const targetUrl = new URL(url.pathname + url.search, redirectTarget);
return Response.redirect(targetUrl.toString(), 302);
}
// Aggiunge header con il paese per il downstream (server di origine)
const headers = new Headers(request.headers);
headers.set('CF-Worker-Country', country);
headers.set('CF-Worker-Continent', cf.continent ?? '');
headers.set('CF-Worker-Timezone', cf.timezone ?? '');
// Prosegui verso il server di origine
return fetch(new Request(request.url, {
method: request.method,
headers,
body: ['GET', 'HEAD'].includes(request.method) ? undefined : request.body,
}));
},
};
interface CfProperties {
country?: string;
continent?: string;
timezone?: string;
}
interface Env {}
ローカライズされた価格と通貨
価格を顧客の現地通貨で表示することがベスト プラクティスです コンバージョン率を高める電子商取引。 Worker を使用すると、次のことができます リクエストが届く前に正しい通貨を決定する オリジンサーバー:
// src/pricing-worker.ts - prezzi localizzati all'edge
interface CurrencyConfig {
code: string;
symbol: string;
position: 'before' | 'after';
vatRate: number; // IVA in percentuale (0.22 = 22%)
}
const COUNTRY_CURRENCY: Record<string, CurrencyConfig> = {
// Eurozona
IT: { code: 'EUR', symbol: '€', position: 'before', vatRate: 0.22 },
DE: { code: 'EUR', symbol: '€', position: 'before', vatRate: 0.19 },
FR: { code: 'EUR', symbol: '€', position: 'before', vatRate: 0.20 },
ES: { code: 'EUR', symbol: '€', position: 'before', vatRate: 0.21 },
// Altre valute
GB: { code: 'GBP', symbol: '£', position: 'before', vatRate: 0.20 },
US: { code: 'USD', symbol: '






