[NODE JS] Express ile Query String Okuma
Query string, URL'nin soru işaretinden sonraki kısmıdır. Mesela /products?category=laptop&sort=price&page=2 URL'sinde category, sort ve page query parametreleridir. Bunlar sunucuya ek bilgi göndermek için kullanılır. Route parametrelerinden farkı opsiyonel olmalarıdır yani URL'de bulunmak zorunda değillerdir.
Express'te query string'e erişmek çok kolay: req.query objesi tüm query parametrelerini içerir. Herhangi bir middleware veya ek paket kurmanıza gerek yok, Express bunu otomatik olarak parse eder. req.query.category dediğinizde "laptop" değerini alırsınız.
Query string'ler genellikle filtreleme, sıralama, sayfalama ve arama işlemlerinde kullanılır. Bir ürün listesini kategoriye göre filtrelemek, fiyata göre sıralamak, sayfa başına kaç sonuç göstermek istediğinizi belirtmek gibi işlemler query parametreleriyle yapılır. REST API tasarımında bu çok yaygın bir pattern.
Query parametreleri her zaman string olarak gelir. Sayısal bir değer bekliyorsanız parseInt veya Number ile çevirmeniz gerekir. Boolean değerler de string gelir yani "true" veya "false" şeklinde. Bu dönüşümleri yaparken edge case'leri düşünmeniz gerekir. Mesela parseInt("abc") NaN döner, bunu kontrol etmeniz lazım.
Array parametreleri de gönderebilirsiniz. /products?color=red&color=blue şeklinde aynı parametreyi birden fazla kez gönderdiğinizde Express bunu otomatik olarak array'e çevirir. Ama tek bir değer gönderildiğinde string kalır. Bu davranış farkını bilerek kodunuzu buna göre yazmalısınız. Ben genellikle her zaman Array.isArray kontrolü yapıyorum ya da parametreyi [].concat(req.query.color) ile array'e çeviriyorum.
Nested objeler de desteklenir. /search?filter[category]=laptop&filter[brand]=apple şeklinde iç içe parametreler gönderebilirsiniz. Express bunu { filter: { category: 'laptop', brand: 'apple' } } objesine çevirir. Bu özellik qs kütüphanesi sayesinde gelir ve varsayılan olarak aktiftir.
Güvenlik açısından query parametrelerini mutlaka sanitize etmeniz gerekir. Özellikle bu parametreleri veritabanı sorgusuna veya HTML çıktısına doğrudan koyarsanız injection saldırılarına açık olursunuz. XSS saldırılarını önlemek için HTML entity encoding yapın, SQL injection için prepared statements kullanın.
Query string uzunluğunun bir sınırı var. Çoğu tarayıcı ve sunucu yaklaşık 2048 karakter uzunluğunda URL'yi destekler. Daha uzun query string'ler kesilebilir veya hata verebilir. Eğer çok fazla parametre göndermeniz gerekiyorsa POST metoduyla body'de göndermek daha doğru olur.
Bir de query parametrelerinde encoding konusu var. Boşluk, Türkçe karakterler, özel semboller gibi değerler URL encoding'e tabi tutulur. Express bunları otomatik decode eder ama bazen double encoding sorunlarıyla karşılaşabilirsiniz. encodeURIComponent ve decodeURIComponent fonksiyonlarını bilmenizde fayda var.
Pratikte query string parametrelerini varsayılan değerlerle birlikte kullanmanızı öneririm. Kullanıcı sayfa parametresi göndermezse 1, limit göndermezse 10 gibi mantıklı varsayılanlar belirleyin. Bu hem kullanıcı deneyimini iyileştirir hem de undefined hatalarının önüne geçer.
JavaScript:
const express = require('express');
const app = express();
// Ornek urun veritabani
const urunler = [
{{ id: 1, ad: 'Gaming Laptop', kategori: 'bilgisayar', fiyat: 35000, marka: 'Asus', puan: 4.5 }},
{{ id: 2, ad: 'Ultrabook', kategori: 'bilgisayar', fiyat: 28000, marka: 'Dell', puan: 4.2 }},
{{ id: 3, ad: 'iPhone 15', kategori: 'telefon', fiyat: 55000, marka: 'Apple', puan: 4.8 }},
{{ id: 4, ad: 'Galaxy S24', kategori: 'telefon', fiyat: 42000, marka: 'Samsung', puan: 4.6 }},
{{ id: 5, ad: 'iPad Air', kategori: 'tablet', fiyat: 22000, marka: 'Apple', puan: 4.4 }},
{{ id: 6, ad: 'Tab S9', kategori: 'tablet', fiyat: 18000, marka: 'Samsung', puan: 4.1 }},
{{ id: 7, ad: 'MacBook Pro', kategori: 'bilgisayar', fiyat: 85000, marka: 'Apple', puan: 4.9 }},
{{ id: 8, ad: 'Pixel 8', kategori: 'telefon', fiyat: 32000, marka: 'Google', puan: 4.3 }},
{{ id: 9, ad: 'AirPods Pro', kategori: 'aksesuar', fiyat: 8500, marka: 'Apple', puan: 4.7 }},
{{ id: 10, ad: 'Galaxy Buds', kategori: 'aksesuar', fiyat: 4500, marka: 'Samsung', puan: 4.0 }},
{{ id: 11, ad: 'ThinkPad X1', kategori: 'bilgisayar', fiyat: 45000, marka: 'Lenovo', puan: 4.6 }},
{{ id: 12, ad: 'Surface Pro', kategori: 'tablet', fiyat: 38000, marka: 'Microsoft', puan: 4.3 }},
];
// GET /api/urunler?kategori=telefon&siralama=fiyat&sira=asc&sayfa=1&limit=5&minFiyat=10000&maxFiyat=50000&arama=galaxy
app.get('/api/urunler', (req, res) => {{
let sonuclar = [...urunler];
// --- Filtreleme ---
const {{ kategori, marka, minFiyat, maxFiyat, minPuan, arama }} = req.query;
if (kategori) {{
sonuclar = sonuclar.filter(u => u.kategori === kategori);
}}
if (marka) {{
// Birden fazla marka: ?marka=Apple&marka=Samsung
const markalar = Array.isArray(marka) ? marka : [marka];
sonuclar = sonuclar.filter(u => markalar.includes(u.marka));
}}
if (minFiyat) {{
const min = Number(minFiyat);
if (!isNaN(min)) sonuclar = sonuclar.filter(u => u.fiyat >= min);
}}
if (maxFiyat) {{
const max = Number(maxFiyat);
if (!isNaN(max)) sonuclar = sonuclar.filter(u => u.fiyat <= max);
}}
if (minPuan) {{
const puan = Number(minPuan);
if (!isNaN(puan)) sonuclar = sonuclar.filter(u => u.puan >= puan);
}}
// Arama (ad icinde arar, buyuk-kucuk harf duyarsiz)
if (arama) {{
const aramaLower = arama.toLowerCase();
sonuclar = sonuclar.filter(u =>
u.ad.toLowerCase().includes(aramaLower) ||
u.marka.toLowerCase().includes(aramaLower)
);
}}
// --- Siralama ---
const siralama = req.query.siralama || 'id'; // varsayilan: id
const sira = req.query.sira || 'asc'; // varsayilan: artan
const gecerliAlanlar = ['id', 'ad', 'fiyat', 'puan', 'marka'];
if (gecerliAlanlar.includes(siralama)) {{
sonuclar.sort((a, b) => {{
let deger;
if (typeof a[siralama] === 'string') {{
deger = a[siralama].localeCompare(b[siralama], 'tr');
}} else {{
deger = a[siralama] - b[siralama];
}}
return sira === 'desc' ? -deger : deger;
}});
}}
// --- Sayfalama ---
const sayfa = Math.max(1, parseInt(req.query.sayfa) || 1);
const limit = Math.min(50, Math.max(1, parseInt(req.query.limit) || 10));
const toplam = sonuclar.length;
const toplamSayfa = Math.ceil(toplam / limit);
const baslangic = (sayfa - 1) * limit;
sonuclar = sonuclar.slice(baslangic, baslangic + limit);
// Response
res.json({{
meta: {{
toplam,
sayfa,
limit,
toplamSayfa,
oncekiSayfa: sayfa > 1 ? sayfa - 1 : null,
sonrakiSayfa: sayfa < toplamSayfa ? sayfa + 1 : null,
}},
filtreler: {{
kategori: kategori || null,
marka: marka || null,
fiyatAraligi: {{ min: minFiyat || null, max: maxFiyat || null }},
arama: arama || null,
}},
sonuclar,
}});
}});
// Kategorileri listele
app.get('/api/kategoriler', (req, res) => {{
const kategoriler = [...new Set(urunler.map(u => u.kategori))];
res.json({{ kategoriler }});
}});
// Markalari listele
app.get('/api/markalar', (req, res) => {{
const markalar = [...new Set(urunler.map(u => u.marka))];
res.json({{ markalar }});
}});
app.listen(3000, () => {{
console.log('Query string sunucusu port 3000\'de');
console.log('Ornek: http://localhost:3000/api/urunler?kategori=telefon&siralama=fiyat&sira=desc');
}});
Query string parametrelerini dokümante etmeyi unutmayın. API'nizi kullanan diğer geliştiriciler hangi parametrelerin desteklendiğini, hangi değerlerin geçerli olduğunu ve varsayılan değerlerin ne olduğunu bilmek ister. Swagger veya OpenAPI gibi araçlarla bu dokümantasyonu otomatik oluşturabilirsiniz.
Emeğiniz ve katkınız için teşekkür ederiz!
Konunuz gerekli incelemelerden geçerek onaylandı. Topluluğumuza katkılarınızın devamını bekliyoruz.
İyi forumlar!
Konunuz gerekli incelemelerden geçerek onaylandı. Topluluğumuza katkılarınızın devamını bekliyoruz.
İyi forumlar!

Şu an konuyu görüntüleyenler (Toplam : 0, Üye: 0, Misafir: 0)
Benzer konular
- Cevaplar
- 2
- Görüntüleme
- 46
- Cevaplar
- 20
- Görüntüleme
- 356
- Cevaplar
- 8
- Görüntüleme
- 28K
- Kilitli
- Cevaplar
- 4
- Görüntüleme
- 2K
- Cevaplar
- 1
- Görüntüleme
- 548