Ana içeriğe geç
  1. Blogs/

Cloudflare Workers'ta Üç Ayda Çarptığım Beş Tuzak

·436 kelime·3 dk
appsec cloudflare workers engineering

Son üç ayda Cloudflare Workers üzerinde birkaç uygulama oluşturdum — cron ile çalışan bir healthcheck aracı, D1 destekli iki farklı web uygulaması. Hepsi ücretsiz katmanda. Platform genel olarak iyi tasarlanmış, ama beşi de “dokümantasyonda bir cümleyle geçiyor, productionda saatlerinizi alıyor” kategorisinde beş davranışla karşılaştım. Sırayla.

1. waitUntil() cron hatalarını görünmez yapıyor #

scheduled() handler’ı içinde asıl işi ctx.waitUntil() ile başlatırsanız, o promise reddedilse bile Cloudflare cron event’i “başarılı” olarak işaretliyor. Dashboard’daki geçmiş yeşil kalıyor, worker sessizce hiçbir şey yapmıyor.

Düzeltmesi basit: scheduled() handler’ını async yapıp asıl işi doğrudan awaitleyin. O zaman bir hata fırlaması cron event geçmişine gerçekten “failed” olarak düşüyor.

export default {
  async scheduled(event, env, ctx) {
    await doTheActualWork(env);   // waitUntil değil
  }
}

waitUntil request-response döngüsünün dışında iş bitirmek için var, “hatayı görmezden gel” anlamına gelmiyor — ama cron context’inde tam olarak öyle davranıyor.

2. Static Assets’in immutable header’ları #

ASSETS.fetch()‘ten dönen response’un header’larını sonradan mutate etmeye çalışırsanız (c.res.headers.set(...) gibi) TypeError: Can't modify immutable headers ile 500 alırsınız. Passthrough asset response’ları immutable geliyor.

Çözüm response’u yeniden sarmak:

c.res = new Response(c.res.body, c.res);

Bunu bir kere yaptıktan sonra header’lar mutable oluyor. Middleware zincirinde statik dosyalara güvenlik header’ı eklemeye çalışan herkesin er ya da geç çarpacağı bir davranış.

3. Workers Logs varsayılan olarak kapalı #

wrangler.toml‘da "observability": { "enabled": true } yazmadığınız sürece üretimdeki console.error çağrılarınız hiçbir yere gitmiyor — sadece canlı bir wrangler tail bağlıyken görünüyorlar. Yani bir hata üretimde bir kere olup geçtiyse, o log kaydı hiç var olmamış gibi.

İlk deploy’da bunu açmak, “neden loglarım boş” diye bir saat harcamaktan daha ucuz.

4. Ücretsiz katmanda 50 subrequest sınırı #

Bir invocation başına 50 subrequest hakkınız var. Hedef başına iki fetch atan bir izleme/fan-out worker’ı yazdıysanız, bu sizi invocation başına yaklaşık 20 hedefle sınırlıyor. Daha fazlasını izlemeniz gerekiyorsa cron tick’i başına deterministik bir batch döndürmeniz gerekiyor — hepsini tek seferde denemek sessizce bazı hedefleri atlıyor, hata da fırlatmayabiliyor.

5. PBKDF2 pahalı değil — çünkü native #

Auth tarafında beklediğimden iyi bir sürpriz: crypto.subtle.deriveBits 600 bin iterasyon PBKDF2’yi workerd’de lokalde ~75ms’de bitiriyor, çünkü işlem V8’de değil native crypto katmanında çalışıyor. Workers’ın 10ms CPU limitine takılmıyor. Tek eksik: nodejs_compat olmadan crypto.timingSafeEqual yok, karşılaştırmayı elle XOR ile yapmanız gerekiyor.

Kısacası #

  • Cron’da waitUntil yerine await kullanın, yoksa hatalar sessizce kayboluyor.
  • Static asset response header’larını mutate etmeden önce yeniden sarın.
  • Workers Logs’u ilk deploy’da açın, sonradan hatırlamayın.
  • Fan-out worker’larda 50 subrequest sınırını batch’leyerek aşın.
  • PBKDF2’den native crypto sayesinde CPU limiti konusunda korkmayın — asıl eksik timingSafeEqual.

Yan iş olarak web uygulaması sızma testleri yapıyorum, Cloudflare Workers üzerinde çalışan uygulamalar dahil. Platformun kendi tuzaklarının güvenlik tarafına düşen kısmı — auth bypass, SSRF, erişim kontrolü — sizi ilgilendiriyorsa: [email protected].