Bu yazı angular uygulamalarında kullandığımız interceptor yapısı hakkında detaylı bilgi içermektedir. Bu bilgiler sıkıcı kısım ve hareketli kısım olarak iki alt bölümden oluşmaktadır. Sıkıcı kısımda biraz daha temel bilgiler yer alırken hareketli kısımda doğrudan Interceptor’un yapısı, kullanım alanları vb konuları ele alacağız.
1. Sıkıcı Kısım
Angular 4.3.0 ile hayatımıza giren ve özellikle frontend uygulamalarında biraz yabancı bir konsept olduğu için kafaları karıştıran Interceptor kavramını detaylı bir şekilde açıklamaya çalışacağım. Peki nedir Interceptor ?
Interceptor dediğimiz kavramı kabaca özetlemek gerekirse backend uygulamalarında yıllardır kullanılmakta olduğumuz ve bir çok backend framework’ün yerleşik olarak desteklenen middleware yapısının frontend uygulamalarına uyarlanmış hali diyebiliriz. (Aslında çok daha geniş bir konsept ancak konuyu dağıtmamak adına biz sadece belirli bir kısmına odaklanacağız.)
Interceptor üzerine konuşmadan önce aslında interceptor’un atası olarak konumlandırabileceğimiz middleware dediğimiz yapı nedir bence bunu anlamamız gerekiyor.
Backend uygulamalarında isteğin (request) uygulama tarafından karşılanması ve isteğin işlenmesi sonucu yanıt (response) dönülmesi ile tamamlanan çift yönlü (bidirectional) bir akış mevcuttur. Bu akış uygulamaya isteğin gelmesi başlar, isteğin karşılanması, ilgili handler’a yönlendirilmesi, işlenmesi, saklanması gereken bir veri varsa bu verinin kaydedilmesi ve bütün işlemler nihayetinde ise geriye bir yanıt (response) dönülmesi ile sona erdirilir. Middleware dediğimiz yapı aslında request ve response arasında yer alıyor. Uygulama içerisindeki request ve response akışını dinleyebiliyor ve müdahelelerde bulunabiliyor.
Angularda ise middleware yapı ile benzer mantıkta çalışan iki farklı yapımız var guards ve interceptors. Bu yazımızda interceptor kısmını açıklayacağız. Guard kısmına ise en kısa zamanda değinmeyi planlıyorum 🙂
Farz edelim benim uygulama içerisinde etkileşimde bulunduğum bir servis var ve ben bu servis ile yapılan bütün iletişimi kayıt altına almak (loglamak) istiyorum. Ne yapmam lazım ? Birinci ihtimal istek gönderilen bütün her yere log için oluşturduğum servisi çağırıp giden gelen her şeyi tek tek kaydedebilirim. Ancak bu servise uygulama içerisined 300 tane yerden ulaşıyorsam bu bizim için ciddi bir iş yükü doğurabilir.
Hadi diyelim o kadar boşsunuz, o kadar zamanınız var (öyle bir zaman da yok tabi 🙂 şu satırları yazarken bile uzaklarda bir developer mesai yapıyor 🙂 ) 300 yere tek tek bu mekanizmayı ekledik, ileride hadi bunun yanında bir de tarih bilgisi ekleyelim dediğimizde değiştirmemiz gereken 300 tane yer ortaya çıkacak. Dolayısıyla sürdürülebilir bir çözüm değil. Her bir değişiklik bize n miktarda iş yüküne sebep oluyor.
Dolayısı ile benim bir noktada servise giden bütün isteklere müdahelede bulunup bu işlemi tek seferde gerçekleştirmem gerekiyor.
İşte bu noktada interceptor dediğimiz yapı devreye giriyor. Uygulama içerisinde gerçekleştirilen HTTP request-response akışının tam ortasında yer alması sayesinde akışı kolaylıkla tek bir noktadan dinleyebiliyorum, kayıt altına alabiliyorum ve istersem müdahele edebiliyorum.
2. Hareketli Kısım
Interceptor dediğimiz konsept aslında tam olarak bu şekilde çalışıyor. Angular uygulaması üzerinde HttpClient üzerinden gönderdiğim bütün istekler ve yanıtlar bu ara katman içerisinden geçiyor. Interceptor API ile aramızda gerçekleşen bütün IO akışının ortasında yer alıyor. Bu sayede gönderilen istekler (request) ve gelen yanıtlar üzerinde merkezi bir şekilde gerçekleştirmek istediğim bütün müdaheleleri Interceptor aracılığı ile gerçekleştirebiliyorum.
Şu ana kadar genel olarak middleware ve interceptor kavramları hakkında belli bir temel bilgiye sahip olduğumuzu düşünüyorum. Şimdi ise biraz daha pratiğe yönelik bilgi vermek istiyorum. Peki Interceptor’u hangi durumlarda kullanmalayız ?
2.1 Interceptor Kullanım Alanları
Aslında bir çok kullanım alanı mevcut diyebiliriz. Hatta kendi özel durumlarınızda da yukarıda bahsettiğim gibi api ile aramızda olan IO akışına müdahele etme gereği duyuyorsanız, merkezi işlemler gerçekleştirmek istediğiniz bir durum varsa Interceptor kullanarak bu sorunları kolaylıkla çözebilirsiniz.
2.1.1 API Base URL
Istek gönderirken her servis metodu için ayrı ayrı base api url bilgisi eklemektense veya bu işlem için base service yapısı kullanıp HttpClient’ı kısıtlamaktansa aşağıda yer alan örnekte olduğu gibi bir Interceptor ile bu sorunu tek bir işlem ile çözebilirsiniz.
2.1.2 Authorization Header (JWT Token)
Geliştirdiğimiz uygulamada kullanıcı doğrulama işlemleri varsa bu işlemler genel itibariyle – özellikle react, angular ve vue gibi SPA uygulamalarda – JWT token üzerinden sağlanmaktadır. Kullanıcı bilgileri ile giriş işlemi yapıldıktan sonra API tarafından bize verilen tokeni local storage (veya session) üzerinde saklamamız ve gönderilen her isteğin Authorization header bilgisi içerisinde göndermemiz gerekmektedir. Bu işlemi elbette her servis metodu için manuel olarak da yapabilirsiniz – yapmayın – ancak yüzlerce metodun olduğu bir uygulamada bu sizin için çok yorucu bir hal alacaktır.
Sadece şu an için değil ilerleyen zamanlarda da kullanıcı doğrulama üzerinde yapılan bir değişiklik mesela JWT token yerine Cookie kullanımı tercih edilmesi durumunda mevcut codebase üzerinde düzenleme yapmak sizin için çok fazla iş yükü oluşturacaktır. Bunun yerine aşağıda yer alan örnekte olduğu gibi basit bir Interceptor ile bu sorunu çözebilirsiniz.
2.1.3 Global Error Handler
Uygulama içerisinde hata yönetimini daha kolay bir hale getirmek için yine Interceptor yapısından faydalanabiliriz. Kullanıcıya her hata göstermek istediğimizde, validasyon mesajlarında veya kullanıcıya gelen mesajı gösterip göstermeyeceğimize her istek için ayrı ayrı karar vermek yerine uygulama genelinde global bir error handler oluşturup bu yapı üzerinden kontrol edebiliriz. (Bütün errorlara hükmeden tek bir handler)
Aşağıda yer alan örnekte uygulama içerisinde belli başlı hataları merkezi bir şekilde handle edebiliyoruz. Kendi uygulamanızda olan özel durumları da ekleyerek daha da geliştirebilirsiniz. Her error için interceptor üzerinde düzenleme yapmak yerine anguların sağlamış olduğu injection token yapısını kullanarak daha sağlıklı yapılar da oluşturabilirsiniz.
2.1.4 Logging
Uygulama içerisinde kullanıcı tarafından gönderilen ve alınan istekleri monitoring amacıyla bir elastic servise atmamız gereken bir durum oluştu diyelim. Uygulama üzerinde kullanılan bütün servis metodlarını düzenlemenin oluşturacağı iş yükünü düşünürsek – ki bu servisin bir kaç gün sonra kaldırılması da istenebilir – bu işlem için Interceptor yapısını kullanmak daha sağlıklı olacaktır.
3. Sonuç
Yukarıda gerek middleware yapısını gerekse de angular 4+ ile hayatımıza giren interceptor yapısını olabildiğince örnekler ile açıklamaya çalıştım. Umarım kafanıza yer edinen soru işaretlerini bir nebze de olsa giderebilmeyi başarabilmişimdir. Eğer konu ile ilgili veya bu konu dışında kafanızı kurcalayan başka sorular varsa sormaktan çekinmeyin 🙂
Angular hakkında diğer yazılara 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 🙂