Türkiye'de ilk Mobil & PC Aynı Anda Metin2 Oyna. Triarchonline kalıcı ve uzun ömürlü yapısı ile 24 Temmuz'da açılıyor. | 1-99 Mobil Metin2 Triarch HEMEN TIKLA!
[NODE JS] Express Error Handling Middleware
Hata yönetimi yazılım geliştirmenin en önemli ama en çok ihmal edilen konularından biri. Bir uygulamanın kalitesini mutlu yoldan çok hata durumlarındaki davranışı belirler. Express'te hata yönetimi middleware sistemi üzerine kurulu ve doğru kullanıldığında çok güçlü bir mekanizma sunuyor.
Express'te error handling middleware'i normal middleware'lerden farklı olarak dört parametre alır: err, req, res, next. Express bu dört parametreli fonksiyonları otomatik olarak error handler olarak tanır. Bu yüzden parametre sayısını doğru tutmanız çok önemli. Üç parametre yazarsanız normal middleware olur ve hataları yakalayamaz.
Error handling middleware her zaman en son tanımlanmalıdır. Tüm route'lardan ve diğer middleware'lerden sonra gelmelidir. Çünkü Express hata oluştuğunda pipeline'daki sonraki error handler'ı arar. Eğer error handler route'lardan önce tanımlıysa çalışmaz.
Express'te hata iki şekilde error handler'a ulaşır: next(error) çağrısı ile veya throw ile. Senkron kodda throw kullanabilirsiniz, Express bunu otomatik yakalar. Ama asenkron kodda (callback, Promise) throw çalışmaz, next(error) kullanmanız gerekir. Express 5 async fonksiyonlardaki hataları otomatik yakalar ama Express 4'te bu desteği kendiniz eklemeniz lazım.
Ben bir production projesinde error handling'i geç eklemiştim. Uygulama her hatada stack trace'i kullanıcıya gösteriyordu. Bu hem güvenlik açığı (internal bilgilerin sızması) hem de kötü kullanıcı deneyimi. O zamandan beri her projeye en başından error handling ekliyorum. Production'da asla stack trace göstermeyin, sadece kullanıcı dostu bir mesaj ve hata kodu gösterin.
Operational errors ve programming errors arasındaki farkı bilmek önemli. Operational errors beklenen hatalardır: veritabanı bağlantısı kopması, geçersiz kullanıcı girişi, dosya bulunamadı gibi. Bunları graceful şekilde handle edebilirsiniz. Programming errors ise bug'lardır: undefined bir değişkene erişme, tip hatası gibi. Bunları yakalamak yerine düzeltmeniz gerekir.
Birden fazla error handler tanımlayabilirsiniz. Her biri next(err) ile hatayı sonraki handler'a iletebilir. Bu pattern ile hataları kategorize edebilirsiniz: biri loglama yapan, biri response gönderen, biri bildirim atan gibi. Bu ayrım özellikle büyük projelerde kodu temiz tutar.
Unhandled rejection ve uncaught exception yakalamayı da unutmayın. Express middleware pipeline'ının dışında kalan hatalar için process seviyesinde event listener'lar eklemeniz gerekir. Ama bu listener'larda process'i kapatmayı düşünün çünkü uygulama tutarsız bir durumda olabilir.
Custom error sınıfları oluşturmak kodunuzu çok daha düzenli hale getirir. AppError, ValidationError, NotFoundError gibi özel hata sınıfları ile farklı hata türlerini kolayca ayırt edebilirsiniz. Her sınıfın kendi status code'u, mesajı ve ek bilgileri olabilir.
JavaScript:
const express = require('express');
const app = express();
app.use(express.json());
// ===== OZEL HATA SINIFLARI =====
class AppError extends Error {{
constructor(message, statusCode, code) {{
super(message);
this.statusCode = statusCode;
this.code = code || 'UNKNOWN_ERROR';
this.isOperational = true;
Error.captureStackTrace(this, this.constructor);
}}
}}
class NotFoundError extends AppError {{
constructor(kaynak = 'Kaynak') {{
super(`${{kaynak}} bulunamadi`, 404, 'NOT_FOUND');
}}
}}
class ValidationError extends AppError {{
constructor(hatalar) {{
super('Validasyon hatasi', 400, 'VALIDATION_ERROR');
this.hatalar = hatalar;
}}
}}
class UnauthorizedError extends AppError {{
constructor(mesaj = 'Kimlik dogrulanmadi') {{
super(mesaj, 401, 'UNAUTHORIZED');
}}
}}
class ForbiddenError extends AppError {{
constructor(mesaj = 'Erisim engellendi') {{
super(mesaj, 403, 'FORBIDDEN');
}}
}}
// ===== ASYNC HANDLER WRAPPER =====
// Express 4'te async hatalari yakalamak icin
function asyncHandler(fn) {{
return (req, res, next) => {{
Promise.resolve(fn(req, res, next)).catch(next);
}};
}}
// ===== ORNEK VERILER =====
const urunler = [
{{ id: 1, ad: 'Laptop', fiyat: 25000 }},
{{ id: 2, ad: 'Telefon', fiyat: 18000 }},
];
// ===== ROUTE'LAR =====
// Senkron hata - Express otomatik yakalar
app.get('/api/senkron-hata', (req, res) => {{
throw new AppError('Bu senkron bir hatadir', 500, 'SYNC_ERROR');
}});
// Async hata - asyncHandler ile sarmalanmis
app.get('/api/urunler', asyncHandler(async (req, res) => {{
// Veritabani simule (gercekte async islem olur)
await new Promise(resolve => setTimeout(resolve, 100));
res.json(urunler);
}}));
app.get('/api/urunler/:id', asyncHandler(async (req, res) => {{
const id = parseInt(req.params.id, 10);
if (isNaN(id)) {{
throw new ValidationError([{{ alan: 'id', mesaj: 'ID sayi olmalidir' }}]);
}}
const urun = urunler.find(u => u.id === id);
if (!urun) {{
throw new NotFoundError('Urun');
}}
res.json(urun);
}}));
app.post('/api/urunler', asyncHandler(async (req, res) => {{
const {{ ad, fiyat }} = req.body;
const hatalar = [];
if (!ad || typeof ad !== 'string' || ad.trim().length < 2) {{
hatalar.push({{ alan: 'ad', mesaj: 'Urun adi en az 2 karakter olmalidir' }});
}}
if (!fiyat || typeof fiyat !== 'number' || fiyat <= 0) {{
hatalar.push({{ alan: 'fiyat', mesaj: 'Fiyat pozitif bir sayi olmalidir' }});
}}
if (hatalar.length > 0) {{
throw new ValidationError(hatalar);
}}
const yeniUrun = {{ id: urunler.length + 1, ad: ad.trim(), fiyat }};
urunler.push(yeniUrun);
res.status(201).json(yeniUrun);
}}));
// ===== 404 HANDLER =====
// Hicbir route'a uymayanlar icin
app.use((req, res, next) => {{
next(new NotFoundError(`${{req.method}} ${{req.url}} endpoint'i`));
}});
// ===== ERROR LOGGING MIDDLEWARE =====
app.use((err, req, res, next) => {{
// Hatayi logla
const logEntry = {{
timestamp: new Date().toISOString(),
requestId: req.requestId || 'N/A',
method: req.method,
url: req.originalUrl,
error: {{
message: err.message,
code: err.code,
statusCode: err.statusCode,
stack: err.stack,
}},
ip: req.ip,
}};
if (err.statusCode >= 500 || !err.isOperational) {{
console.error('[KRITIK HATA]', JSON.stringify(logEntry, null, 2));
}} else {{
console.warn('[ISTEMCI HATASI]', `${{err.statusCode}} ${{err.message}}`);
}}
next(err); // Sonraki error handler'a ilet
}});
// ===== ANA ERROR HANDLER =====
app.use((err, req, res, next) => {{
const statusCode = err.statusCode || 500;
const isDev = process.env.NODE_ENV !== 'production';
const response = {{
basarili: false,
hata: {{
mesaj: statusCode >= 500 && !isDev
? 'Sunucu hatasi olustu'
: err.message,
kod: err.code || 'INTERNAL_ERROR',
}},
}};
// Validasyon hatalarinda detaylari ekle
if (err instanceof ValidationError) {{
response.hata.detaylar = err.hatalar;
}}
// Gelistirme ortaminda stack trace goster
if (isDev) {{
response.hata.stack = err.stack;
}}
res.status(statusCode).json(response);
}});
// ===== PROCESS SEVIYESI HATA YAKALAMA =====
process.on('unhandledRejection', (reason, promise) => {{
console.error('Yakalanmamis Promise Rejection:', reason);
}});
process.on('uncaughtException', (err) => {{
console.error('Yakalanmamis Exception:', err);
process.exit(1);
}});
app.listen(3000, () => {{
console.log('Error handling sunucusu port 3000\'de');
}});
Hata yönetimi bir düşünce biçimidir. Kod yazarken her zaman "ya bu başarısız olursa?" sorusunu sorun. Network istekleri başarısız olabilir, veritabanı bağlantısı kopabilir, dosya bulunamayabilir, kullanıcı geçersiz veri gönderebilir. Bu senaryoların hepsini önceden düşünüp ele almak sağlam bir uygulama oluşturmanın temelidir.
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
Altın Konu
Next.js'de API Oluşturma Ve Kullanma
- Cevaplar
- 12
- Görüntüleme
- 1K
