URL va query parametrlar bilan ishlash
Internet-do‘konda "Go" so‘zini qidirib, narx bo‘yicha saralab, ikkinchi sahifaga o‘tsangiz, brauzer manzili shunday ko‘rinishga keladi:
? belgisidan keyingi qism — query parametrlar (query string). Ular orqali klient serverga qo‘shimcha shartlar yuboradi: nimani qidirish, qanday saralash, nechanchi sahifani ko‘rsatish.
Bu darsda URL qanday qismlardan iboratini, Go’da query parametrlarni o‘qish, tekshirish va turga o‘tkazishni o‘rganamiz.
URL tuzilishi
https://user:[email protected]:8443/books/42?format=json&lang=uz#izohlar
└─┬─┘ └───┬───┘ └──┬──┘└─┬┘└───┬───┘└─────────┬─────────┘└──┬──┘
scheme userinfo host port path query fragment
| Qism | Ma’nosi |
|---|---|
scheme |
Protokol: http yoki https |
host |
Domen yoki IP manzil |
port |
Port. Ko‘rsatilmasa, http uchun 80, https uchun 443 |
path |
Resurs yo‘li |
query |
kalit=qiymat juftliklari, & bilan ajratiladi |
fragment |
Sahifa ichidagi joy. Serverga yuborilmaydi |
Go’da URL net/url paketidagi url.URL struct bilan ifodalanadi. Handler ichida u r.URL orqali olinadi.
Yo‘l parametri va query parametr farqi
Ikkalasi ham URL orqali ma’lumot uzatadi, lekin vazifasi har xil:
/books/42 → yo‘l parametri: aynan qaysi resurs
/books?author=Qodiriy → query parametr: ro‘yxatni filtrlash
Odatiy qoida:
- resursni aniqlash uchun yo‘l parametri ishlatiladi:
/users/5,/orders/1001; - ro‘yxatni filtrlash, saralash, sahifalash uchun query parametr ishlatiladi:
?status=active&page=2.
Yo‘l parametrlari oldingi URL routing darsida ko‘rilgan edi. Bu darsda asosiy e’tibor query parametrlarga qaratiladi.
Query parametrlarni o‘qish
r.URL.Query() query qismini tahlil qilib, url.Values turida qaytaradi. url.Values aslida map[string][]string.
Misol
Kod qanday ishladi:
q.Get("q")kalitning birinchi qiymatini qaytaradi. Kalit bo‘lmasa, bo‘sh satr qaytadi.- URL’dagi
+belgisi bo‘shliqqa aylantirildi. Maxsus belgilar (%20,%D0%...) ham avtomatik dekodlanadi.
Warning
curl buyrug‘ida URL’ni qo‘shtirnoqqa oling. Aks holda shell & belgisini "buyruqni fonda ishga tushir" deb tushunadi va URL kesilib qoladi.
Parametr berilganmi yoki bo‘shmi?
Get parametr umuman yo‘q bo‘lganda ham, ?q= ko‘rinishida bo‘sh berilganda ham "" qaytaradi. Bu ikki holatni ajratish kerak bo‘lsa, Has metodidan foydalaning:
Bir kalit — bir nechta qiymat
Bir kalit URL’da bir necha marta kelishi mumkin:
Barcha qiymatlarni olish uchun Get emas, map’ning o‘zidan foydalaniladi:
Ba’zi API’lar bir nechta qiymatni vergul bilan yuboradi: ?tag=go,backend,api. Bunday holatda strings.Split(q.Get("tag"), ",") ishlatiladi. Qaysi usulni tanlasangiz ham, API hujjatida aniq yozib qo‘ying.
Qiymatni turga o‘tkazish
Query parametrlar doim satr sifatida keladi. page=2 ham "2" bo‘lib keladi. Son, mantiqiy qiymat yoki sana kerak bo‘lsa, uni strconv yoki time paketi bilan o‘zgartirish va xatoni tekshirish kerak.
page, err := strconv.Atoi(q.Get("page"))
if err != nil {
http.Error(w, "page butun son bo‘lishi kerak", http.StatusBadRequest)
return
}
inStock, err := strconv.ParseBool(q.Get("in_stock")) // "true", "1", "false", "0"
if err != nil {
http.Error(w, "in_stock true yoki false bo‘lishi kerak", http.StatusBadRequest)
return
}
from, err := time.Parse(time.DateOnly, q.Get("from")) // "2026-09-30"
if err != nil {
http.Error(w, "from YYYY-MM-DD formatida bo‘lishi kerak", http.StatusBadRequest)
return
}
Klient noto‘g‘ri qiymat yuborganini 400 Bad Request bilan bildirish to‘g‘ri. Xato xabarida qaysi parametr noto‘g‘ri ekanini va qanday qiymat kutilganini yozing.
Standart qiymat va chegaralar
Ko‘p parametrlar ixtiyoriy bo‘ladi. Masalan, page berilmasa, birinchi sahifa ko‘rsatiladi. Har bir handlerda bir xil kodni takrorlamaslik uchun kichik yordamchi funksiya yozamiz:
// intParam query parametrni butun songa o‘tkazadi.
// Parametr berilmagan bo‘lsa, def qiymatini qaytaradi.
func intParam(q url.Values, key string, def, min, max int) (int, error) {
s := q.Get(key)
if s == "" {
return def, nil
}
n, err := strconv.Atoi(s)
if err != nil {
return 0, fmt.Errorf("%s butun son bo‘lishi kerak", key)
}
if n < min || n > max {
return 0, fmt.Errorf("%s %d va %d oralig‘ida bo‘lishi kerak", key, min, max)
}
return n, nil
}
Chegara qo‘yish muhim. Aks holda klient ?limit=1000000 yuborib, bitta so‘rovda millionta yozuvni olishga urinishi mumkin. Bu database va serverga ortiqcha yuk tushiradi.
Ruxsat etilgan qiymatlar ro‘yxati
sort kabi parametrlar faqat oldindan belgilangan qiymatlardan birini qabul qilishi kerak. Buni map yordamida tekshirish qulay:
var allowedSort = map[string]bool{
"title": true,
"price": true,
"created_at": true,
}
sort := q.Get("sort")
if sort == "" {
sort = "created_at"
}
if !allowedSort[sort] {
http.Error(w, "sort qiymati noto‘g‘ri", http.StatusBadRequest)
return
}
Danger
sort qiymatini tekshirmasdan SQL so‘roviga qo‘shish SQL injection’ga yo‘l ochadi. Ustun nomlari SQL parametr ($1) orqali uzatilmaydi, shuning uchun ular faqat shunday ruxsat ro‘yxati bilan tekshiriladi. Batafsil SQL Injection oldini olish darsida.
To‘liq misol: filtrlash va sahifalash
Quyidagi API kitoblar ro‘yxatini muallif bo‘yicha filtrlaydi, saralaydi va sahifalarga bo‘lib qaytaradi:
Sinab ko‘ramiz:
curl "http://localhost:8080/books?author=qodiriy"
curl "http://localhost:8080/books?sort=price&limit=3"
curl "http://localhost:8080/books?page=abc"
{"data":[{"id":1,"title":"O‘tkan kunlar","author":"Abdulla Qodiriy","price":45000},{"id":2,"title":"Mehrobdan chayon","author":"Abdulla Qodiriy","price":42000}],"limit":2,"page":1,"total":2}
{"data":[{"id":3,"title":"Kecha va kunduz","author":"Cho‘lpon","price":39000},{"id":4,"title":"Sarob","author":"Abdulla Qahhor","price":41000},{"id":2,"title":"Mehrobdan chayon","author":"Abdulla Qodiriy","price":42000}],"limit":3,"page":1,"total":5}
page butun son bo‘lishi kerak
Kod qanday ishladi:
intParamparametr berilmaganda standart qiymatni qaytardi, noto‘g‘ri qiymatda esa xato berdi.- Filtrlash harf katta-kichikligiga qaramaydi, chunki ikkala tomon
strings.ToLowerbilan kichik harfga o‘tkazildi. - Sahifalashda
minfunksiyasi slice chegarasidan chiqib ketishning oldini oladi.page=100bo‘lsa ham, dasturpanicbermaydi, bo‘sh ro‘yxat qaytadi. - Javobda
totalham bor. Klient shu qiymat bilan jami sahifalar sonini hisoblaydi.
URL yaratish: url.Values
Ba’zan server o‘zi URL yasashi kerak bo‘ladi. Masalan, javobda keyingi sahifaga havola berish uchun. Satrlarni qo‘lda ulash xavfli, chunki maxsus belgilar kodlanmay qoladi. Buning o‘rniga url.Values ishlatiladi:
| main.go | |
|---|---|
Encode() kalitlarni alifbo tartibida joylashtiradi va maxsus belgilarni kodlaydi. & belgisi %26 ga aylandi. Aks holda u parametrlar orasidagi ajratuvchi deb tushunilgan bo‘lardi.
Tayyor URL’ni tahlil qilish
Satr ko‘rinishidagi URL’ni qismlarga ajratish uchun url.Parse ishlatiladi:
u, err := url.Parse("https://shop.uz:8443/books?page=2#top")
if err != nil {
log.Fatal(err)
}
fmt.Println(u.Scheme) // https
fmt.Println(u.Hostname()) // shop.uz
fmt.Println(u.Port()) // 8443
fmt.Println(u.Path) // /books
fmt.Println(u.Query().Get("page")) // 2
fmt.Println(u.Fragment) // top
Xulosa
- Yo‘l parametri resursni aniqlaydi, query parametr esa ro‘yxatni filtrlaydi, saralaydi va sahifalaydi.
r.URL.Query()url.Valuesqaytaradi.Getbirinchi qiymatni,q["kalit"]esa barcha qiymatlarni beradi.- Qiymatlar doim satr bo‘lib keladi. Ularni
strconvbilan o‘zgartiring va xatoda400qaytaring. - Ixtiyoriy parametrlarga standart qiymat bering, sonli parametrlarga chegara qo‘ying.
sortkabi parametrlarni ruxsat ro‘yxati bilan tekshiring.- URL yasashda
url.ValuesvaEncode()dan foydalaning.
Endi server tomonining asosiy qismlari tayyor. Keyingi darsda ularni birlashtirib, to‘liq CRUD API loyihasini yozamiz.