Wrangler CLI Kurulumu ve İlk Cloudflare Worker Projesi

Cloudflare Workers dünyasına adım atmak istiyorsanız, ilk durağınız Wrangler CLI olacak. Wrangler, Cloudflare’in resmi komut satırı aracı ve Workers projelerini yönetmek, deploy etmek, local’de test etmek için kullanacağınız temel silahınız. Bu yazıda sıfırdan başlayıp gerçek dünyada kullanılabilir bir Worker projesi oluşturana kadar her adımı detaylıca inceleyeceğiz.

Ön Hazırlık: Neler Lazım?

Başlamadan önce birkaç şeyin hazır olması gerekiyor. Cloudflare hesabınız yoksa workers.cloudflare.com üzerinden ücretsiz hesap açabilirsiniz. Free plan oldukça cömert: günde 100.000 istek, 10ms CPU süresi limiti. Üretim ortamları için paid plan düşünün ama öğrenme aşamasında free plan fazlasıyla yeterli.

Sistem gereksinimleri:

  • Node.js: 16.17.0 veya üzeri (LTS sürüm önerilir)
  • npm veya pnpm: Paket yöneticisi
  • Cloudflare hesabı: API token için
  • Git: Proje yönetimi için

Node.js versiyonunuzu kontrol edin:

node --version
npm --version

Eğer Node.js yönetimi için nvm kullanıyorsanız (ki kullanmanızı şiddetle tavsiye ederim), LTS sürümü şu şekilde kurabilirsiniz:

nvm install --lts
nvm use --lts

Wrangler CLI Kurulumu

Wrangler’ı global olarak kurmak yerine proje bazlı kullanmak daha temiz bir yaklaşım. Ama önce global kurulumla tanışalım:

npm install -g wrangler

Kurulum tamamlandıktan sonra versiyonu doğrulayın:

wrangler --version

Wrangler 3.x sürümü şu an aktif geliştirilen dal. Eğer eski bir kurulumunuz varsa güncellemeyi unutmayın:

npm update -g wrangler

Cloudflare Hesabıyla Kimlik Doğrulama

Wrangler’ı kullanabilmek için Cloudflare hesabınıza bağlamanız gerekiyor. İki yöntem var:

Yöntem 1: OAuth ile Login (Önerilen)

wrangler login

Bu komut tarayıcıyı açacak ve Cloudflare’in OAuth sayfasına yönlendirecek. İzinleri onayladıktan sonra terminal otomatik olarak authenticate olmuş olacak. Token bilgileri ~/.config/.wrangler/config/default.toml dosyasına kaydediliyor.

Yöntem 2: API Token ile Authentication

CI/CD pipeline’larında veya headless sunucularda OAuth kullanamıyorsunuz. Bu durumda API token yaklaşımı gerekiyor:

Cloudflare Dashboard > My Profile > API Tokens > Create Token yolunu izleyin. “Edit Cloudflare Workers” template’ini seçin, zone ayarlarını düzenleyin ve token’ı oluşturun.

export CLOUDFLARE_API_TOKEN="your_api_token_here"

CI/CD ortamlarında bu environment variable’ı pipeline secret’larına eklemeyi unutmayın.

Kimlik doğrulamayı test etmek için:

wrangler whoami

Account bilgilerinizi görüyorsanız her şey yolunda demektir.

İlk Worker Projesi Oluşturma

Wrangler ile proje oluşturmak son derece basit. create komutu sizi interaktif bir wizard’a yönlendiriyor:

npm create cloudflare@latest my-first-worker

Alternatif olarak doğrudan Wrangler ile de oluşturabilirsiniz:

wrangler init my-first-worker

Wizard size birkaç soru soracak:

  • Proje tipi (Worker, Worker with Assets, Pages vb.)
  • TypeScript kullanmak istiyor musunuz?
  • Test framework tercihinde bulunmak ister misiniz?

Şimdilik “Hello World” Worker seçeneğiyle ve TypeScript ile devam edelim. Proje oluşturulduktan sonra dizine girin:

cd my-first-worker
ls -la

Proje yapısına bakalım:

  • wrangler.toml: Proje konfigürasyonu, en kritik dosya
  • src/index.ts: Worker kodunuzun bulunduğu ana dosya
  • package.json: Bağımlılıklar ve scriptler
  • tsconfig.json: TypeScript konfigürasyonu

wrangler.toml Dosyasını Anlamak

Bu dosya Worker’ınızın beyni. Açıp inceleyelim:

cat wrangler.toml

Tipik bir wrangler.toml şu şekilde görünür:

# wrangler.toml içeriği (bu bash bloğu config gösterimi için)
name = "my-first-worker"
main = "src/index.ts"
compatibility_date = "2024-01-01"

[vars]
MY_VARIABLE = "production_value"

[[kv_namespaces]]
binding = "MY_KV"
id = "your-kv-namespace-id"

Önemli alanlar:

  • name: Worker’ınızın Cloudflare’deki adı, deployment URL’ini belirliyor
  • main: Entry point dosyası
  • compatibility_date: Cloudflare runtime’ının hangi versiyonunu kullanacağınızı belirliyor, bunu güncel tutun
  • vars: Environment variable’lar

İlk Worker Kodunu Yazalım

src/index.ts dosyasını açın. Varsayılan içerik şu şekilde:

# TypeScript Worker kodu (index.ts)
export default {
  async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> {
    return new Response('Hello World!');
  },
};

Bu çok basit ama Workers’ın temel konseptini gösteriyor. Her Worker bir fetch event handler’ı export ediyor. Request geldiğinde bu fonksiyon çağrılıyor ve Response dönüyor.

Şimdi daha gerçekçi bir örnek yazalım. Diyelim ki bir API routing yapıyoruz:

# Gelişmiş Worker örneği
export default {
  async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> {
    const url = new URL(request.url);
    const path = url.pathname;

    // CORS headers
    const corsHeaders = {
      'Access-Control-Allow-Origin': '*',
      'Access-Control-Allow-Methods': 'GET, POST, OPTIONS',
      'Content-Type': 'application/json',
    };

    // OPTIONS preflight
    if (request.method === 'OPTIONS') {
      return new Response(null, { headers: corsHeaders });
    }

    // Route handling
    if (path === '/api/health') {
      return new Response(
        JSON.stringify({ status: 'ok', timestamp: Date.now() }),
        { headers: corsHeaders }
      );
    }

    if (path === '/api/info') {
      const info = {
        region: request.cf?.colo || 'unknown',
        country: request.cf?.country || 'unknown',
        city: request.cf?.city || 'unknown',
        userAgent: request.headers.get('User-Agent'),
      };
      return new Response(JSON.stringify(info), { headers: corsHeaders });
    }

    return new Response(
      JSON.stringify({ error: 'Not Found' }),
      { status: 404, headers: corsHeaders }
    );
  },
};

Bu örnekte dikkat çekici birkaç şey var. request.cf objesi Cloudflare’e özgü metadata içeriyor: kullanıcının hangi ülkeden bağlandığı, hangi Cloudflare datacenter’ı kullandığı (colo) gibi bilgiler. Bu bilgileri ücretsiz olarak alıyorsunuz, ayrıca GeoIP servisi satın almanıza gerek yok.

Local Development: Wrangler Dev

Local’de test etmek için:

wrangler dev

Bu komut local bir server başlatıyor, genellikle http://localhost:8787 adresinde. Hot reload özelliğiyle dosyada değişiklik yaptığınızda otomatik olarak güncelleniyor.

Farklı port belirtmek için:

wrangler dev --port 9000

Remote modda çalıştırmak (gerçek Cloudflare edge’inde test):

wrangler dev --remote

Remote mod özellikle KV, D1 database gibi Cloudflare servislerini kullanan Worker’ları test ederken işe yarıyor çünkü local emülatörün bazı limitleri var.

Başka terminal açıp API’yi test edelim:

# Health check
curl http://localhost:8787/api/health

# Lokasyon bilgisi (local'de CF metadata boş gelir)
curl http://localhost:8787/api/info

# 404 testi
curl http://localhost:8787/api/nonexistent

KV Storage Entegrasyonu

Gerçek dünya uygulamalarında veri saklamanız gerekiyor. Cloudflare KV (Key-Value) storage bu iş için biçilmiş kaftan. Önce KV namespace oluşturun:

# Production namespace
wrangler kv namespace create "USER_DATA"

# Preview namespace (local dev için)
wrangler kv namespace create "USER_DATA" --preview

Bu komutlar size namespace ID’leri verecek. Bunları wrangler.toml‘a ekleyin:

# wrangler.toml'a eklenecek konfigürasyon
[[kv_namespaces]]
binding = "USER_DATA"
id = "abc123production"
preview_id = "abc123preview"

Şimdi Worker kodunu KV kullanacak şekilde güncelleyelim:

# KV kullanan Worker örneği
interface Env {
  USER_DATA: KVNamespace;
}

export default {
  async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> {
    const url = new URL(request.url);
    const path = url.pathname;

    if (request.method === 'POST' && path === '/api/user') {
      const body = await request.json() as { name: string; email: string };
      const userId = crypto.randomUUID();

      await env.USER_DATA.put(userId, JSON.stringify(body), {
        expirationTtl: 86400, // 24 saat sonra otomatik sil
      });

      return new Response(
        JSON.stringify({ id: userId, message: 'User created' }),
        {
          status: 201,
          headers: { 'Content-Type': 'application/json' }
        }
      );
    }

    if (request.method === 'GET' && path.startsWith('/api/user/')) {
      const userId = path.replace('/api/user/', '');
      const userData = await env.USER_DATA.get(userId);

      if (!userData) {
        return new Response(
          JSON.stringify({ error: 'User not found' }),
          { status: 404, headers: { 'Content-Type': 'application/json' } }
        );
      }

      return new Response(userData, {
        headers: { 'Content-Type': 'application/json' }
      });
    }

    return new Response('Not Found', { status: 404 });
  },
};

KV’yi komut satırından test etmek de mümkün:

# KV'ye değer yaz
wrangler kv key put --namespace-id="abc123preview" "test-key" "test-value"

# KV'den değer oku
wrangler kv key get --namespace-id="abc123preview" "test-key"

# Tüm keyleri listele
wrangler kv key list --namespace-id="abc123preview"

Environment Variables ve Secrets

Hassas bilgileri (API key, database password vb.) wrangler.toml’a yazmayın. Bunun için Cloudflare Secrets kullanın:

# Secret ekle (değeri terminal prompt'tan gireceksiniz)
wrangler secret put DATABASE_PASSWORD

# Mevcut secretları listele
wrangler secret list

# Secret sil
wrangler secret delete DATABASE_PASSWORD

Normal environment variable’lar için wrangler.toml:

# Environment variables konfigürasyonu
[vars]
API_BASE_URL = "https://api.example.com"
APP_ENV = "production"
MAX_REQUESTS = "1000"

Worker kodunda bunlara env.DATABASE_PASSWORD, env.API_BASE_URL şeklinde erişiyorsunuz.

Deployment

Local testleri başarılı olduktan sonra deploy zamanı:

wrangler deploy

Deployment tamamlandığında Worker URL’nizi göreceksiniz: https://my-first-worker.your-subdomain.workers.dev

Staging ortamı için farklı environment’lar kullanabilirsiniz. wrangler.toml‘a staging konfigürasyonu ekleyin:

# Staging environment konfigürasyonu
[env.staging]
name = "my-first-worker-staging"
vars = { APP_ENV = "staging" }

[[env.staging.kv_namespaces]]
binding = "USER_DATA"
id = "staging-kv-namespace-id"

Staging’e deploy etmek için:

wrangler deploy --env staging

Deploy geçmişini görmek ve rollback yapmak için:

# Deploy listesi
wrangler deployments list

# Belirli versiyona rollback
wrangler rollback --deployment-id="deployment-id-here"

Gerçek Dünya Senaryosu: Rate Limiting Middleware

İşte Workers’ın gerçekten parlayan bir kullanım senaryosu. KV storage kullanarak basit bir rate limiter yazalım:

# Rate limiting Worker implementasyonu
interface Env {
  RATE_LIMIT: KVNamespace;
}

async function checkRateLimit(
  ip: string,
  env: Env,
  limit: number = 10,
  windowSeconds: number = 60
): Promise<{ allowed: boolean; remaining: number; resetAt: number }> {
  const key = `rl:${ip}`;
  const now = Math.floor(Date.now() / 1000);
  const windowStart = now - windowSeconds;

  const current = await env.RATE_LIMIT.get(key, { type: 'json' }) as
    { count: number; windowStart: number } | null;

  if (!current || current.windowStart < windowStart) {
    await env.RATE_LIMIT.put(key, JSON.stringify({ count: 1, windowStart: now }), {
      expirationTtl: windowSeconds,
    });
    return { allowed: true, remaining: limit - 1, resetAt: now + windowSeconds };
  }

  if (current.count >= limit) {
    return {
      allowed: false,
      remaining: 0,
      resetAt: current.windowStart + windowSeconds
    };
  }

  await env.RATE_LIMIT.put(key, JSON.stringify({
    count: current.count + 1,
    windowStart: current.windowStart
  }), { expirationTtl: windowSeconds });

  return {
    allowed: true,
    remaining: limit - current.count - 1,
    resetAt: current.windowStart + windowSeconds
  };
}

export default {
  async fetch(request: Request, env: Env): Promise<Response> {
    const ip = request.headers.get('CF-Connecting-IP') || '0.0.0.0';
    const { allowed, remaining, resetAt } = await checkRateLimit(ip, env);

    const rateLimitHeaders = {
      'X-RateLimit-Limit': '10',
      'X-RateLimit-Remaining': remaining.toString(),
      'X-RateLimit-Reset': resetAt.toString(),
      'Content-Type': 'application/json',
    };

    if (!allowed) {
      return new Response(
        JSON.stringify({ error: 'Too Many Requests' }),
        { status: 429, headers: rateLimitHeaders }
      );
    }

    // Asıl iş mantığınız burada
    return new Response(
      JSON.stringify({ message: 'Request processed', remainingRequests: remaining }),
      { headers: rateLimitHeaders }
    );
  },
};

Bu rate limiter edge’de çalışıyor yani her Cloudflare datacenter’ında ayrı ayrı limit sayıyor. Global rate limiting için Durable Objects’e bakmanız gerekiyor ama basit senaryolar için bu yaklaşım gayet iyi.

Log ve Monitoring

Deploy sonrası logları takip etmek için:

# Real-time log streaming
wrangler tail

# Belirli bir Worker için
wrangler tail my-first-worker

# JSON formatında loglar
wrangler tail --format json

# Sadece hataları göster
wrangler tail --status error

wrangler tail komutu production ortamındaki gerçek trafiği canlı olarak gösteriyor. Debug için son derece kullanışlı.

Worker kodunuzda console.log kullandığınızda bunlar otomatik olarak bu stream’e geliyor:

# Worker içinde loglama
console.log('Request received:', request.url);
console.error('Something went wrong:', error.message);

Sık Karşılaşılan Sorunlar ve Çözümleri

Wrangler login sonrası token hatası alıyorum:

Token dosyasını silip tekrar login olmayı deneyin:

rm -rf ~/.config/.wrangler
wrangler login

“Workers.dev subdomain not configured” hatası:

Dashboard’da Workers & Pages > Your subdomain kısmından subdomain’inizi ayarlayın. Bir kez yapıldıktan sonra tüm Worker’larınız bu subdomain altında çalışır.

CPU time limit aşımı:

Free plan’da 10ms CPU limiti var. Paid plan’da bu 50ms’ye çıkıyor. Ağır hesaplama işlemleri için Workers uygun değil, bu işleri origin server’a bırakın. Workers daha çok routing, authentication, edge caching, request/response manipulation için ideal.

KV namespace bulunamıyor:

Preview namespace ID’sini production ID’siyle karıştırmak çok yaygın bir hata. wrangler dev için preview_id, deploy için id kullanıldığını unutmayın.

Sonuç

Wrangler CLI ve Cloudflare Workers ikilisi, edge computing dünyasına giriş için mükemmel bir başlangıç noktası. Kurulum süreci oldukça pürüzsüz, local development deneyimi wrangler dev sayesinde gerçekten keyifli ve deployment tek komutla halloluyor.

Bu yazıda temel kurulumdan başlayıp KV storage entegrasyonu, environment management, gerçek dünya rate limiting örneği ve monitoring konularına kadar uzandık. Workers’ın asıl gücü ise henüz değinmediğimiz konularda saklı: Durable Objects ile stateful uygulamalar, D1 ile edge-side SQL database, R2 ile object storage ve WebAssembly modülü yükleme gibi özellikler.

Edge computing’in getirdiği en büyük avantaj gecikme sürelerinin dramatik biçimde düşmesi. Kullanıcıya yakın, dünyanın 300’den fazla noktasında çalışan bir uygulama düşünün ve bunun için tek bir sunucu yönetmek zorunda kalmayın. Workers tam da bunu sağlıyor. Sysadmin perspektifinden bakıldığında, yönetilecek sunucu yok, patch yok, kapasitelere karar vermek yok. Odağınız tamamen uygulama koduna kayıyor ki bu bence en büyük kazanım.

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir