Bir Vaka İncelemesi: ASP.NET Core’un Cookie İle İmtihanı

Çok kısa bir zaman sonra Hürriyet evrenine yeni bir projeyi dahil edeceğiz. Proje .NET Core altyapısı kullanılarak geliştirilen bir MVC projesi. Projenin son aşamasında karşılaştığımız ve çözümü üzerine kafa yorduğumuz bir sorunu tartışmaya açmak niyetim.

Görsel Kaynağı: http://bit.ly/2tnIaun

Neden .NET Core?

Projenin başlangıç aşamasındaki teknik toplantılarımızda tartıştığımız en temel nokta bu oldu. Şu anda hali hazırda .NET Core ile geliştirilmiş, hurriyet.com.tr projesine hizmet veren bir kaç mikroservisimiz canlıda. Mikroservisleri geliştirirken de bu soruları sormuş ve hemen hemen aynı cevapları ortaya koymuştuk:

  • Hürriyet IT dünyasında hızlı bir open-source teknolojilere yönelim hakim. Çekirdek uygulamalarının tamamına yakını .NET teknolojileri ile geliştirilmiş bir ekip için de bu teknolojiye adaptasyon zor olmadı.
  • Sistem ekibimizin tecrübeleriyle Windows sunuculardan Linux sunuculara doğru bir kavimler göçü yaşıyoruz. Hemen sayabileceğim imaj ve lokasyon uygulamamız, zamanlanmış görevlerin koştuğu sunucularımız şu anda bu ortamda nefes alıyor.
  • Başlangıç aşaması olarak mikro seviyede yazdığımız uygulamaları dockerize ederek yönetiyoruz. Bununla ilgili avantajlar başlı başına bir yazı konusu.
  • Cloud ortamlarda koşan uygulamalarımız da hali hazırda mevcut. Günün birinde bu yazdığımız uygulamaları da rahatlıkla cloud üzerinde servis edilebilir olması üzerine tasarımlar çalışıyoruz.

.NET Core için yukarıda saydığım temel maddelerin tamamının yanına bir onay işareti koyabiliyor olmamız sebebiyle yeni projede de bu teknolojiyi seçtik.

İmtihan nerede başladı?

Testlerimiz esnasında uygulama bazı tarayıcılarda hiçbir sebep olmaksızın 400 — Bad Request hatası cevabı ile dönmeye başladı.

Bir süre kod üzerinde tespitler yapmaya çalıştık ancak farkettik ki istemciden gelen istek uygulamaya hiç düşemiyor bile. Hata alan istemci ile doğru çalışan istemci makineler üzerinde bir karşılaştırma yaptık ve en naif şekilde cookie’ler temizlendiği zaman hatanın ortadan kalktığını gördük.

İsteğin uygulamaya hiç uğramaması şüphelerin Kestrel üzerinde yoğunlaşmasına neden oldu. Hemen ardından hızlı bir Google araması ve gelen ilk sonuç:

Bingo!

.NET Core ekibi tarafından geliştirilen açık kaynak kodlu web sunucusu Kestrel’in github reposunda bir issue. İşi açan geliştirici, uygulamanın request header’ları içerisinde ASCII olmayan bir karakter yer aldığı zaman 400 hatası döndüğünü ve controller’a hiç uğramadığından şikayetçi. Tıpkı bizim gibi. Bizim de sildiğimiz zaman çalışan cookie’nin üzerinde taşıdığı değer aşağıdakine benzer:

[{"héllo" : "world"}]

Issue içerisinde bir takım tartışmalar dönmüş. IETF referans gösterilmiş ve özetle denmiş ki;

İnternet standartlarına göre request headers içerisinde non-ascii değerlerin taşınması uygun görülmemektedir. Bu tür bir zorunluluk taşıyorsanız ilgili değerleri encode-decode yöntemleri ile işleyebilirsiniz.

Eğer cookie sizin tarafınızdan oluşturuluyorsa bunu sorunsuz bir şekilde atlatabilirsiniz ancak üçüncü parti bir firma tarafından basılan bir cookie ise ve kontrolü sizde değilse farklı çözüm yolları aramanız gerekli oluyor. Biz de sistem ekibimiz ile konuyu tartıştık ve çözüm için bir yol ürettik:

Nginx — Reverse Proxy

Uygulamanın önünde hali hazırda bir nginx uygulaması çalışıyor. İstek buradan geçerken ilgili cookie’yi by-pass etsek nasıl olur? Bu süre içerisinde ilgili cookie’de bir düzenlemeye gidilirse kuralı kaldırır ve standart akışa devam ederiz.

fikri açıkçası cazip geldi. Bunun için nginx üzerinde bir kural tanımladık ve istekleri bu kuraldan geçirdikten sonra back-end sunucuya yönlendirdik. Evet, sorun çözüldü :)

nginx için konfigürasyon dosyamız tabii ki tamamen yukarıdaki snippet’ten ibaret değil. Yaramıza merhem olan kısım ilk if bloğu. Kurala göre istek ile birlikte gelen cookie’lerde “non_ascii” isimli bir cookie varsa bunu silip yeni oluşan cookie ile back-end sunucuya yönlendirme yapıyoruz.

Ekrana basılan değerler back-end sunucuya iletilen cookie değerleridir.

Durumun simülasyonu için docker-compose ile çalıştırılabilecek küçük bir uygulama aşağıdaki github repo’mda mevcut. Dilerseniz buradan uygulamayı indirebilir ve lokal ortamınızda deneyebilirsiniz.

Bizim hızlı ve efektif olarak nitelendirdiğimiz çözüm yöntemi bu oldu. Sizin de eklemek istediğiniz, eleştirmek istediğiniz noktalar var ise ve benimle paylaşırsanız çok mutlu olurum.

Bir sonraki vaka ile karşılaşana dek, sorunlarınız hep bir çerez büyüklüğünde olsun :)