Herkese Merhabalar arkadaşlar! Bugün uzun zamandır anlatmak istediğim bir konuya, Angular Interceptor yapısına değineceğiz. Frontend dünyasına yeni adım atmış biriyseniz “isteklerin tam ortasına oturan bir ara katman” fikri ilk başta biraz korkutucu gelebilir, ancak söz veriyorum yazının sonunda “aa bu kadarmış” diyeceksiniz. Çünkü Angular Interceptor aslında backend tarafında yıllardır kullandığımız çok tanıdık bir kavramın frontend’e uyarlanmış halinden başka bir şey değil.
Bu yazıyı iki bölüme ayırdım: önce biraz teori (yani neden böyle bir şeye ihtiyacımız var?), sonra da doğrudan kullanım alanları ve örnekler. Sıkı durun, başlıyoruz.
Peki Nedir Bu Interceptor?
Angular 4.3 ile hayatımıza giren ve frontend uygulamalarında biraz yabancı bir konsept olduğu için kafaları karıştıran Interceptor’u kabaca şöyle özetleyebiliriz: backend framework’lerinin yerleşik olarak desteklediği middleware yapısının frontend uygulamalarına uyarlanmış hali. (Aslında çok daha geniş bir konsept, ancak konuyu dağıtmamak adına biz belirli bir kısmına odaklanacağız.)
Interceptor üzerine konuşmadan önce, onun atası olarak konumlandırabileceğimiz middleware’i anlamamız gerekiyor diye düşünüyorum. Backend uygulamalarında isteğin (request) karşılanması ve işlenmesi sonucu bir yanıt (response) dönülmesiyle tamamlanan çift yönlü (bidirectional) bir akış vardır. Bu akış; isteğin uygulamaya gelmesiyle başlar, ilgili handler’a yönlendirilir, işlenir, saklanması gereken bir veri varsa kaydedilir ve nihayetinde geriye bir response dönülerek sona erer. İşte middleware dediğimiz yapı tam olarak request ve response’un arasında yer alır; bu akışı dinleyebilir ve istediğinde müdahalede bulunabilir.
Angular tarafında ise middleware ile benzer mantıkta çalışan iki farklı yapımız var: guards ve interceptors. Bu yazıda interceptor kısmını ele alacağız; guard tarafına da en kısa zamanda değinmeyi planlıyorum 🙂
Neden Angular Interceptor’a İhtiyaç Duyarız?
En sevdiğim anlatım şekliyle, bir senaryo üzerinden gidelim. Diyelim ki uygulamamda etkileşimde bulunduğum bir servis var ve bu servisle yapılan bütün iletişimi kayıt altına almak (loglamak) istiyorum. Ne yapmam lazım?
Birinci ihtimal: istek gönderdiğim her yere, log için oluşturduğum servisi çağırıp giden geleni tek tek kaydederim. Ama bu servise uygulama içerisinde 300 farklı yerden ulaşıyorsam, bu ciddi bir iş yükü demek. Hadi diyelim o kadar boş vaktiniz var (öyle bir zaman yok tabii 🙂 şu satırları yazarken bile uzaklarda bir developer mesai yapıyor) ve 300 yere bu mekanizmayı tek tek ekledik. Peki ileride “bir de tarih bilgisi ekleyelim” dediğimizde? Değiştirmemiz gereken yine 300 nokta çıkacak karşımıza. Yani sürdürülebilir bir çözüm değil; her küçük değişiklik bize n kadar iş yükü doğuruyor.
Dolayısıyla servise giden bütün isteklere tek bir noktadan müdahale edebilmem ve bu işlemi merkezi olarak gerçekleştirebilmem gerekiyor. İşte tam burada Interceptor devreye giriyor: HTTP request-response akışının tam ortasında yer aldığı için akışı tek bir yerden dinleyebiliyor, kayıt altına alabiliyor ve gerektiğinde müdahale edebiliyorum.
Angular Interceptor’un Temel Çalışma Mantığı
Şimdiye kadar middleware ve interceptor kavramları hakkında belli bir temele sahip olduğumuzu düşünüyorum. Konsept aslında tam olarak şöyle çalışıyor: HttpClient üzerinden gönderdiğim bütün istekler ve geri dönen bütün yanıtlar bu ara katmandan geçiyor. Interceptor, API ile aramızda gerçekleşen tüm IO akışının ortasında oturuyor. Bu sayede merkezi olarak yapmak istediğim her müdahaleyi tek bir yerden gerçekleştirebiliyorum.
Modern Angular (15+) tarafında iki yaklaşım var: klasik sınıf tabanlı (HttpInterceptor implement eden) interceptor’lar ve standalone uygulamalarda öne çıkan fonksiyonel (HttpInterceptorFn) interceptor’lar. İkisi de aynı işi yapıyor; standalone bir projede provideHttpClient(withInterceptors([...])) ile fonksiyonel olanları kaydetmek artık çok daha pratik. Detaylar için resmi kaynak olarak Angular HTTP Interceptors dokümantasyonuna göz atmanızı tavsiye ederim.
Angular Interceptor Kullanım Alanları
Peki ne zaman kullanmalıyız? Aslında birçok kullanım alanı var diyebiliriz. Kendi özel durumlarınızda da, az önce bahsettiğim gibi API ile aramızdaki IO akışına müdahale etme veya merkezi bir işlem gerçekleştirme ihtiyacı duyuyorsanız, Interceptor bu sorunları zarifçe çözer. En sık karşımıza çıkan dört senaryoya bakalım.
1. API Base URL
İstek gönderirken her servis metodu için ayrı ayrı base URL bilgisi eklemek ya da bunun için ayrı bir base service yapısı kurup HttpClient‘ı kısıtlamak yerine, tek bir Interceptor ile bu sorunu kökten çözebilirsiniz. İlgili istekler interceptor’dan geçerken URL’in başına ortam değişkeninizdeki base URL’i ekler.
2. Authorization Header (JWT Token)
Geliştirdiğimiz uygulamada kullanıcı doğrulama işlemleri varsa — özellikle React, Angular ve Vue gibi SPA uygulamalarında — bu genelde JWT token üzerinden sağlanır. Giriş işleminden sonra API’nin bize verdiği token’ı local storage (veya session) içinde saklamamız ve her isteğin Authorization header’ında göndermemiz gerekir. Bunu elbette her servis metodu için manuel de yapabilirsiniz — yapmayın — ancak yüzlerce metodun olduğu bir uygulamada bu çok yorucu bir hale gelir.
Üstelik bu sadece bugünün değil yarının da problemi: ileride doğrulama yönteminizi JWT yerine Cookie’ye çevirmek istediğinizde, mevcut codebase üzerinde devasa bir düzenleme yapmanız gerekir. Bunun yerine basit bir Interceptor ile token’ı tek noktadan ekleyin, gönül rahatlığıyla devam edin. JWT tabanlı oturum yönetimine daha derin girdiğim Angular state management yazıma da göz atabilirsiniz.
3. Global Error Handler
Uygulama içindeki hata yönetimini kolaylaştırmak için yine Interceptor’dan faydalanabiliriz. Kullanıcıya hangi hatayı göstereceğimize, validasyon mesajlarını nasıl ele alacağımıza her istek için ayrı ayrı karar vermek yerine, uygulama genelinde global bir error handler kurup kontrolü tek elden sağlayabiliriz. (Bütün error’lara hükmeden tek bir handler diyelim 🙂)
Aşağıdaki örnekte belli başlı hataları merkezi olarak handle ediyoruz; siz kendi uygulamanızın özel durumlarını ekleyerek geliştirebilirsiniz. Her error için interceptor’ı tekrar tekrar düzenlemek yerine, Angular’ın sağladığı InjectionToken yapısını kullanarak çok daha sağlıklı bir mimari de kurabilirsiniz. Hata kodlarının ne anlama geldiğini hatırlamak isterseniz MDN’in HTTP durum kodları referansı başucu kaynağınız olsun.
4. Logging
Diyelim ki kullanıcı tarafından gönderilen ve alınan istekleri monitoring amacıyla bir Elastic servisine atmamız gereken bir durum doğdu. Uygulamadaki bütün servis metodlarını tek tek düzenlemenin yaratacağı iş yükünü düşünün — ki bu servisin birkaç gün sonra kaldırılması bile istenebilir. Böyle bir senaryoda Interceptor kullanmak çok daha sağlıklı olacaktır; logging mantığını tek noktadan açıp kapatırsınız.
Sonuç
Yukarıda hem middleware yapısını hem de Angular 4+ ile hayatımıza giren Angular Interceptor kavramını olabildiğince örnekle açıklamaya çalıştım. Umarım kafanızdaki soru işaretlerini bir nebze de olsa giderebilmişimdir. Konuyla ilgili ya da bunun dışında aklınıza takılan başka sorular varsa sormaktan çekinmeyin 🙂
Angular hakkındaki diğer yazılara da göz atmak isterseniz:

Aşağıdaki örnek dediniz ama örnek göremedim. Teşekkürler yazı için.
Rica ederim. Resimler uçmuş en kısa zamanda güncelleyeceğim 🙂