PostMessage ile Cross-origin Haberleşme
Büyük kurumsal yazılım şirketlerinin, çok geniş müşteri kitlesinin olduğu uygulamalarının çok yavaş bir ilerleme ile teknolojiye ve düzenlemelere uyum sağladığını hepimiz düşünebiliriz. En azından bu şirketlerin birinde deneyim sağlamış biri iseniz :)
Yeni bir geliştirme veya kullanımdan kaldırılan bir yöntemin alternatifi ile uygulamanın sürdürebilirliğini sağlamak ve tüm kullanıcılar seviyesinde ortaya çıkabilecek hataları önceden tespit etmek ve kullanım alışkanlıklarını düşünerek iyi yönde deneyim sağlatmak çok zordur. Gerekli tüm testleri yapmak, kullanıcıların geri dönüşlerine göre yeni fikirleri uygulamak vb.
Konu başlığı PostMessage ın bununla ne ilgisi var diyorsanız o halde açıklamaya başlayalım :)
Html terminolojisinde iframe in adını duyup kullanananız çok olmuştur. Iframeler i başka bir web sayfası içerisinden başka bir web sayfasını çağırmak için kullanırız ve Iframe mevcut bir page içerisinde( page başka bir iframe de olabilir. ) başka bir page açmamıza olanak sağlayan bir html tag ı dır. Son olarak Iframe in her zaman bir parent page e sahip olmasını bekleriz.
Bankacılık, otomasyon kontrol sistemleri, muhasebe ve sigortacılık gibi sektörler için geliştirilen web tabanlı uygulamalarda iframeler sadece web sayfasını göstermek farklı olarak ayrıca parent page ile etkileşime geçerek onun sahip olduğu yöntemlere ve özelliklere erişmesi gerektiği durumlar olur.
Örnek olarak ana bir Dashboard web uygulamamızın olduğunu düşünelim ve bu uygulama kendi bünyesinde Authenticate ettiği kullanıcının sahip olduğu yetkileri barındırmakla birlikte kendi içerisinde diğer uygulamaların ekranlarını gösteren bir yapıya sahip olsun. Bu uygulamalarda kullanıcının yetkilerini ve kişisel bilgileri Dashboard web uygulamasından(yani parent) dan alıyor olsun.
O halde iframe, parent ile haberleşmek için global window nesnesinin parent window u refarans gösteren parent property si aracılığı ile erişmek durumundadır. (eskimiş yöntem)
PostMessage öncesinde window.parent aracılığıyla bir üst window a erişmek için Same-Origin nin sağlanıp sağlanmadığına bakmak gerekir. Aksi takdirde aşağıdaki hatayı almak kaçınılmazdır.
Bu hatayı aşmak same-origin nin desteklenmesi gerekmekte ve ayrıca parent ve iframe ler arasında document.domain değerinin aynı olması gerekmektedir. Bunu sağlamak için url de yer alan ortak domain ile document.domain her iki taraf için ezilirse istenen sağlanmış olur. (eskidi bknz.)
Ama :)
Chromium tabanlı browser geliştiricilerinin dikkate alınacağı önemli bir duyuru Ocak 2022 de yayınlandı.
Chrome disables modifying document.domain
Detay için yukarıda ki bağlantıya gidebilirsiniz. :) Özet geçmek gerekir ise document.domain ini artık ezip same-origin i sağlamak developer tarafından mümkün görünmüyor :(
Bu durumda alternatif bir yol aramak mecburi oluyor. Yukarıdaki bağlantıda alternatif olarak window.postMessage yöntemini kullanabiliceğimiz paylaşılmış.
Giriş yaptığımıza göre postMessage in kullanımı hakkında detaya geçebiliriz :)
The
window.postMessage()
method safely enables cross-origin communication betweenWindow
objects; e.g., between a page and a pop-up that it spawned, or between a page and an iframe embedded within it.
Mdn web docs da söylendiği gibi postMessage cross-origin communication u window objeleri arasında haberleşmeyi güvenli bir şekilde mümkün kılan bir yöntemdir.
// SYNTAX
postMessage(message)
postMessage(message, options)
postMessage(message, targetOrigin)
postMessage(message, targetOrigin, transfer)
message : Hedef window a ileteceğiniz mesajı(veriyi) temsil eder. Developer veriyi kendisi serialize edebilir veya bu işlemi postMessage serialize algoritmasına bırakabilir.
targetOrigin: Mesajı ulaştıracağımız hedef window un origin bilgisini temsil eder. ‘*’ geçildiği taktirde tüm origin ler kabul ediliyor anlamına gelecektir.
function SendMessageToParentWithPostMessage(){
var prnt = window.top || window.parent;
var methodInfo = {
MethodName: "GetFullName",
Parameters: ["Muhammed","Emin","Karaboğa"]
};
var strMethodInfo = methodStrHeader + JSON.stringify(methodInfo);
prnt.postMessage(strMethodInfo,'http://localhost:3000');
}
...
...
SendMessageToParentWithPostMessage();
Event Listener
PostMessage ile iletilen mesajı dinlemek için window objesine message id li eventListener ı bağlamak gerekir. Tabii bu yine hedef window içerisinde yapılmalı :)
addEventListener("message", function (e) {
var message = e.data;
// write your logics here
});
Özet olarak geçtiğim kullanımlar için repo olarak aşağıda ki paylaştığım bağlantıya bakabilirsiniz. :)
Repo da ki örnekte ‘Get Full Name’ button una tıklandığı takdir de iframe postMessage aracılığı ile Parent a gönderilen mesajın alert olarak basmasını talep eder. :) Böylece iframe talebini parent a iletmiş oldu :)
Buraya kadar okuduğunuz için teşekkür ederim : )
Önerilerinizi ve yorumlarınızı rica ediyorum.
Sağlıcakla.. :)