Ders 03 / 22
Rota Parametreleri ve Sorgu
Durumun adreste taşınması; yol parametresi ile sorgu durumunun ayrılması, şemayla okuma ve doğrulama, varsayılanların yazılmaması, kanonik biçim, bağımlı parametrelerin sıfırlanması ve geçmiş kaydı kararı.
İçindekiler
Rota ağacı yolun taşıdığı durumu bileşenlere ulaştırdı: hangi istasyon, hangi bölüm. Ölçüm geçmişi ekranının geri kalan durumu ise henüz adreste değil. Bir tarih aralığı seçili, bir ölçüm türü süzülmüş, liste ikinci sayfada ve tarihe göre azalan sıralanmış olabilir.
Bunlar bileşenin yerel değişkenlerinde tutulduğunda kullanıcı o görünümü paylaşamaz, yer imine ekleyemez, geri düğmesiyle önceki süzgece dönemez. Adrese yazıldığında ise adres uzar, kirlenir ve her değişiklik geçmişe bir kayıt eklemeye adaydır. Bu ders iki soruyu ayırır: hangi durum adrese girer, ve giren durum nasıl yazılır.
Yol mu, Sorgu mu, Bellek mi
Geçmiş ve Konum dersinde adresin parçaları taşıdıkları duruma göre ayrılmıştı: yol kaynağın kimliğini, sorgu aynı kaynağın hangi görünümünün istendiğini, parça belge içindeki konumu taşır. Yönlendirme bu ayrımı işletilebilir bir kurala çevirir.
Yol parametresi bir kaynağı seçer. İstasyon kimliği yola girer, çünkü değiştiğinde görüntülenen şey başka bir nesnedir. Yol parametresinin bir varsayılanı olmaz: kaynak ya belirtilir ya belirtilmez.
Sorgu parametresi aynı kaynağın sunumunu ayarlar. Süzgeç, sıralama, sayfa numarası, görünüm biçimi buraya girer. Her birinin bir varsayılanı vardır ve kullanıcı hiçbirini seçmediğinde ekran yine anlamlıdır.
Bellek ise adreste yeri olmayan durumu tutar. Ölçütü Geçmiş ve Konum dersi vermişti: kullanıcı bu adresi yeni bir sekmede açtığında aynı ekranı görmeyi bekliyor mu. Açık bir ipucu balonu, sürüklenen bir kaydırıcının anlık değeri, bir animasyonun ilerlemesi bu sınavı geçemez.
Sınırda duran bir durum vardır: yalnız bu oturumda anlamlı olan ama gezinme boyunca korunması gereken bilgi — listede en son görüntülenen satır gibi. Bunun yeri geçmiş kaydının durum nesnesidir; adrese yazılmaz ama geri gidildiğinde geri gelir.
Yol Parametresi Bir Dış Girdidir
Yol parametresi kullanıcının yazabildiği bir alandır. Adres çubuğuna elle girilebilir, eski bir yer iminden gelebilir, bir bağlantıda yanlış üretilmiş olabilir. Eşleyicinin onu çıkarmış olması geçerli olduğu anlamına gelmez.
Bu, güvenlik tarafında da geçerlidir. /istasyon/kuzey-yamac adresini açabilen bir
kullanıcı /istasyon/dogu-sirt adresini de açabilir. İstemcinin parametreyi doğrulaması
biçim hatalarını yakalar; yetkiyi ise yalnızca sunucu doğrulayabilir. Bu ayrım sonraki
dersin konusudur.
Doğrulamanın üç sonucu birbirinden ayrılır. Biçimi bozuk parametre — sayı beklenen yerde harf — bulunamadı görünümüne düşer. Biçimi doğru ama karşılığı olmayan parametre sunucudan gelen yanıtla anlaşılır ve yine bulunamadı üretir. Geçerli parametre ise görünüme aktarılır.
Sorgu Durumunun Şeması
Sorgu dizgisi bir dizgi haritasıdır: her değer metindir, her ad birden çok kez görünebilir, ve içeriği dışarıdan gelir. Bu üç özellik, sorguyu doğrudan durum olarak kullanmayı olanaksız kılar. Araya bir şema girer: her parametrenin tipini, varsayılanını ve geçerli değer kümesini bildiren tanım.
// sorgu-durumu.mjs — sorgu dizgisinin semayla okunmasi ve kanonik bicimde yazilmasi const SEMA = { olcum: { tur: "secim", varsayilan: "hepsi", secenek: ["hepsi", "sicaklik", "nem", "ruzgar"] }, esik: { tur: "sayi", varsayilan: null }, sayfa: { tur: "tamsayi", varsayilan: 1, enAz: 1 }, sira: { tur: "secim", varsayilan: "azalan", secenek: ["artan", "azalan"] }, etiket: { tur: "coklu", varsayilan: [] }, }; // Tek dogrulama noktasi: hem okuma hem yazma bundan gecer. function dogrula(kural, ham) { if (kural.tur === "secim") return kural.secenek.includes(ham) ? { deger: ham } : { hata: true }; const s = kural.tur === "tamsayi" ? Number.parseInt(ham, 10) : Number(ham); if (!Number.isFinite(s) || (kural.enAz !== undefined && s < kural.enAz)) return { hata: true }; return { deger: s }; } function oku(sorgu) { const p = new URLSearchParams(sorgu); const durum = {}, uyari = []; for (const [ad, kural] of Object.entries(SEMA)) { if (kural.tur === "coklu") { const hepsi = p.getAll(ad); durum[ad] = hepsi.length ? [...new Set(hepsi)].sort() : kural.varsayilan; continue; } const ham = p.get(ad); if (ham === null) { durum[ad] = kural.varsayilan; continue; } const sonuc = dogrula(kural, ham); if (sonuc.hata) { durum[ad] = kural.varsayilan; uyari.push(`${ad}=${ham} gecersiz`); } else durum[ad] = sonuc.deger; } return { durum, uyari }; } function yaz(durum) { const p = new URLSearchParams(); for (const [ad, kural] of Object.entries(SEMA)) { // sema sirasi kanonik sirayi verir const deger = durum[ad]; if (kural.tur === "coklu") { for (const d of [...new Set(deger ?? [])].sort()) p.append(ad, d); continue; } if (deger === null || deger === undefined || deger === kural.varsayilan) continue; if (dogrula(kural, String(deger)).hata) continue; // gecersiz deger adrese yazilmaz p.set(ad, String(deger)); } const s = p.toString(); return s ? `?${s}` : ""; } console.log("-- okuma --"); for (const sorgu of [ "", "?olcum=sicaklik&sayfa=3", "?sayfa=abc&olcum=kar&esik=-3.5&etiket=gece&etiket=kar&etiket=gece", "?sayfa=0&sira=artan&olcum=bagil+nem", ]) { const { durum, uyari } = oku(sorgu); console.log((sorgu || "(bos)").padEnd(52), JSON.stringify(durum)); if (uyari.length) console.log(" ".repeat(52), "uyari:", uyari.join("; ")); } console.log("-- yazma --"); for (const durum of [ { olcum: "hepsi", esik: null, sayfa: 1, sira: "azalan", etiket: [] }, { olcum: "sicaklik", esik: -5, sayfa: 1, sira: "azalan", etiket: [] }, { olcum: "bagil nem", esik: null, sayfa: 4, sira: "artan", etiket: ["kar", "gece"] }, ]) console.log(JSON.stringify(durum).padEnd(78), yaz(durum) || "(bos)"); console.log("-- gidis donus --"); const baslangic = { olcum: "ruzgar", esik: 12.5, sayfa: 2, sira: "artan", etiket: ["gece"] }; const dizgi = yaz(baslangic); console.log("dizgi ", dizgi); console.log("ayni mi ", JSON.stringify(oku(dizgi).durum) === JSON.stringify(baslangic)); console.log("kararli ", yaz(oku(dizgi).durum) === dizgi); console.log("-- adres uzerinde --"); const adres = new URL("https://ornek.gecerli/istasyon/kuzey-yamac/olcum?sayfa=9&olcum=nem"); const guncel = { ...oku(adres.search).durum, olcum: "sicaklik", sayfa: 1 }; console.log(adres.pathname + yaz(guncel));
-- okuma --
(bos) {"olcum":"hepsi","esik":null,"sayfa":1,"sira":"azalan","etiket":[]}
?olcum=sicaklik&sayfa=3 {"olcum":"sicaklik","esik":null,"sayfa":3,"sira":"azalan","etiket":[]}
?sayfa=abc&olcum=kar&esik=-3.5&etiket=gece&etiket=kar&etiket=gece {"olcum":"hepsi","esik":-3.5,"sayfa":1,"sira":"azalan","etiket":["gece","kar"]}
uyari: olcum=kar gecersiz; sayfa=abc gecersiz
?sayfa=0&sira=artan&olcum=bagil+nem {"olcum":"hepsi","esik":null,"sayfa":1,"sira":"artan","etiket":[]}
uyari: olcum=bagil nem gecersiz; sayfa=0 gecersiz
-- yazma --
{"olcum":"hepsi","esik":null,"sayfa":1,"sira":"azalan","etiket":[]} (bos)
{"olcum":"sicaklik","esik":-5,"sayfa":1,"sira":"azalan","etiket":[]} ?olcum=sicaklik&esik=-5
{"olcum":"bagil nem","esik":null,"sayfa":4,"sira":"artan","etiket":["kar","gece"]} ?sayfa=4&sira=artan&etiket=gece&etiket=kar
-- gidis donus --
dizgi ?olcum=ruzgar&esik=12.5&sayfa=2&sira=artan&etiket=gece
ayni mi true
kararli true
-- adres uzerinde --
/istasyon/kuzey-yamac/olcum?olcum=sicaklik
Okuma tarafı hiçbir girdide çuvallamaz. Eksik parametre varsayılana düşer, bozuk sayı varsayılana düşer ve uyarı üretir, tanımsız seçenek reddedilir. Bu davranışın adı sağlamlıktır: kullanıcının elinde kalmış eski bir adres, uygulamayı hata ekranına düşürmek yerine anlamlı bir görünüm açar.
Yazma tarafında iki karar görünür. Varsayılana eşit değer adrese yazılmaz; ilk satırda tüm alanlar varsayılan olduğu için sorgu boştur. Bu, adresin kısa kalmasından öte bir şey sağlar: aynı ekran her zaman tek bir adresle anılır. Geçersiz değer de yazılmaz; üçüncü satırda tanımsız ölçüm türü düşürülmüş, geri kalan alanlar yazılmıştır.
Kanonik Biçim
Aynı durumun tek bir dizgi karşılığı olmasına kanonik biçim denir. Örnekteki yazıcı
bunu iki kuralla sağlar: parametreler şemadaki sırayla yazılır, çoklu değerler kendi
içinde sıralanır. Etiket kümesi kar, gece verilmişken çıktıda gece, kar sırasıyla
görünmesinin nedeni budur.
Gidiş dönüş bölümü iki özelliği sınar. Okuma yazmanın tersidir: yazılan durum geri okunduğunda aynı nesneyi verir. Yazma kararlıdır: geri okunan durum yeniden yazıldığında aynı dizgiyi verir. İkisi birlikte, adresin durumun güvenilir bir taşıyıcısı olduğunu söyler.
Kanonik biçim üç yerde işe yarar. Sunucu durumu önbelleği adresi anahtar olarak kullanabilir; aynı görünüm iki farklı dizgiyle anılmadığı için iki ayrı önbellek girdisi oluşmaz. İki adresin aynı ekranı gösterip göstermediği dizgi karşılaştırmasıyla anlaşılır. Ve kullanıcıların paylaştığı adresler birbirinin aynısı olur.
Bağımlı Parametreler
Son bölüm bir karar örneğidir. Adreste dokuzuncu sayfa ve nem süzgeci varken ölçüm türü sıcaklığa çevrilmiştir; çıktıda sayfa numarası yoktur, çünkü açıkça bire çekilmiştir.
Süzgeç değiştiğinde eski sayfa numarası anlamını yitirir: yeni süzgeçte dokuzuncu sayfa bulunmayabilir ve kullanıcı boş bir liste görür. Aynı bağımlılık seçili satır kimliği, sonsuz listenin yüklenmiş uzunluğu ve sıralama içinde konum için de geçerlidir. Bu sıfırlamalar kendiliğinden olmaz; hangi parametrenin hangisini geçersiz kıldığı açıkça yazılır.
Ters yön de önemlidir: ilgisiz parametre korunur. Ölçüm türü değişirken sıralama ve eşik yerinde kalmalıdır. Sorgu dizgisini elle birleştiren kod bu korumayı kaybeder; durumu bir bütün olarak okuyup üzerine yazan kod korur.
Geçmişe Ekleme mi, Değiştirme mi
Sorgu durumunun her değişimi adresi değiştirir; ancak her değişim geçmişe bir kayıt eklemek zorunda değildir. Geçmiş ve Konum dersinde kurulan ayrım burada karara dönüşür.
Eklenir: kullanıcının geri düğmesiyle dönmek isteyeceği değişimler. Sayfa geçişi, ölçüm türünün değiştirilmesi, sıralamanın tersine çevrilmesi.
Değiştirilir: ara durumlar ve kullanıcının geri dönmeyi beklemediği düzeltmeler. Metin kutusuna yazılan her karakter için ekleme yapan bir arama alanı, geri düğmesini harf harf geri alan bir düzeneğe çevirir. Bu tür alanlarda yazma sırasında değiştirme yapılır; Form Olayları dersindeki gecikmeli tetikleme ile birlikte kullanıldığında adres yazma durduktan sonra bir kez güncellenir.
Uygulamanın açılışında yapılan düzeltme de değiştirmeyle yapılır: adreste geçersiz bir değer varsa kanonik biçime çekilir, ama bu düzeltme geçmişe kayıt bırakmaz. Bıraksaydı geri düğmesi kullanıcıyı geçersiz adrese geri götürür ve döngü kurulurdu.
Özet
- Yol parametresi kaynağı seçer ve varsayılanı yoktur; sorgu parametresi aynı kaynağın sunumunu ayarlar ve her birinin bir varsayılanı vardır; geri kalan durum bellekte veya geçmiş kaydının durum nesnesinde kalır.
- Yol parametresi dış girdidir; biçim doğrulaması istemcide yapılır, yetki doğrulaması istemciye bırakılamaz. Sorgu durumu da bir şemayla okunur: eksik, bozuk ve tanımsız değerler varsayılana düşer, uygulama hata ekranına gitmez.
- Varsayılana eşit ve geçersiz değerler adrese yazılmaz; parametre sırası ve çoklu değer sırası sabitlenerek kanonik biçim elde edilir.
- Kanonik biçim, önbellek anahtarı üretmeyi, iki görünümü karşılaştırmayı ve paylaşılan adreslerin aynı olmasını sağlar.
- Bir parametre başka bir parametreyi geçersiz kılıyorsa sıfırlama açıkça yazılır; ilgisiz parametreler korunur.
- Geri dönülmesi beklenen değişimler geçmişe eklenir, ara durumlar ve açılıştaki düzeltmeler o anki kaydı değiştirir.
Sonraki Adım
Adres artık hangi kaynağın hangi görünümünün istendiğini eksiksiz taşıyor. Taşımadığı tek şey, kullanıcının o kaynağı görmeye hakkı olup olmadığı. İstasyon ayarları ekranı yalnız yetkili kullanıcılara açık; ölçüm girişi yalnız oturum açmış kullanıcılara. Adres çubuğuna elle yazılan bir yol bu ekranları da açmaya çalışır. Sonraki ders rotaya bağlı erişim koşullarını, koşulun karara dönüşmesini, oturum açtıktan sonra istenen adrese dönüşü ve istemci tarafı denetimin neden güvenlik sınırı olmadığını ele alır.
İlerlemeni kaydetmek ve not almak için Giriş yap
Notlarım
Not almak için giriş yapmalısın.