Express.js''in gücü middleware pattern''inden gelir. Her HTTP isteği, pipeline üzerindeki fonksiyonların sırayla çalıştığı bir yolculuk geçirir. Bu yazı middleware''in nasıl çalıştığını, en kritik üç kategoriyi (auth, logging, error handling) ve kendi middleware''inizi nasıl yazacağınızı üretim seviyesi örneklerle gösterir.

Middleware Nedir?

İlgili rehberler: Yazılım geliştirme süreçleri · PostgreSQL optimizasyonu · Git ileri seviye komutlar · Redis nedir, nasıl kullanılır · Docker ile deploy

Middleware, (req, res, next) => {} imzasına sahip bir fonksiyondur. next() çağrıldığında pipeline bir sonraki middleware''e geçer; çağrılmazsa istek orada asılı kalır. next(err) ise pipeline''ı atlayıp error handler''a gider.

// En basit middleware
app.use((req, res, next) => {
    req.startTime = Date.now();
    next();
});

app.get('/', (req, res) => {
    res.json({ took: Date.now() - req.startTime });
});

Request Logger

function requestLogger(req, res, next) {
    const start = Date.now();
    res.on('finish', () => {
        const dur = Date.now() - start;
        const level = res.statusCode >= 500 ? 'ERROR' : res.statusCode >= 400 ? 'WARN' : 'INFO';
        console.log(`[${level}] ${req.method} ${req.originalUrl} ${res.statusCode} ${dur}ms`);
    });
    next();
}

app.use(requestLogger);
İpucu
Production''da console.log yerine Pino veya Winston gibi structured logger kullanın — JSON formatında log çıktısı ELK/Loki''ye kolay aktarılır.

Authentication Middleware

const jwt = require('jsonwebtoken');

async function requireAuth(req, res, next) {
    const header = req.headers.authorization || '';
    const token = header.startsWith('Bearer ') ? header.slice(7) : null;
    if (!token) return res.status(401).json({ error: 'Token required' });

    try {
        const payload = jwt.verify(token, process.env.JWT_SECRET, {
            algorithms: ['HS256']
        });
        const user = await db.users.findByPk(payload.sub);
        if (!user || !user.active) {
            return res.status(401).json({ error: 'Invalid user' });
        }
        req.user = user;
        next();
    } catch (err) {
        return res.status(401).json({ error: 'Invalid token' });
    }
}

// Kullanım
app.get('/api/me', requireAuth, (req, res) => {
    res.json(req.user);
});

Role-Based Authorization

function requireRole(...allowedRoles) {
    return (req, res, next) => {
        if (!req.user) return res.status(401).json({ error: 'Not authenticated' });
        if (!allowedRoles.includes(req.user.role)) {
            return res.status(403).json({ error: 'Insufficient permission' });
        }
        next();
    };
}

// Zincirleme kullanım
app.delete('/api/users/:id', requireAuth, requireRole('admin'), async (req, res) => {
    await db.users.destroy({ where: { id: req.params.id } });
    res.status(204).end();
});

Error Handler

Express''te error handler (err, req, res, next) 4-argüman imzalı olan özel middleware''dir ve her zaman pipeline''ın sonunda tanımlanmalıdır.

class AppError extends Error {
    constructor(status, message, code) {
        super(message);
        this.status = status;
        this.code = code;
    }
}

// Kullanım
if (!user) throw new AppError(404, 'User not found', 'USER_NOT_FOUND');

// Async route handler'larında error yakalama
function asyncHandler(fn) {
    return (req, res, next) => Promise.resolve(fn(req, res, next)).catch(next);
}

app.get('/api/users/:id', asyncHandler(async (req, res) => {
    const user = await db.users.findByPk(req.params.id);
    if (!user) throw new AppError(404, 'User not found', 'USER_NOT_FOUND');
    res.json(user);
}));

// Global error handler
app.use((err, req, res, next) => {
    const status = err.status || 500;
    const reqId = req.id || Date.now().toString(36);
    if (status >= 500) {
        console.error(`[${reqId}] ${err.stack}`);
    }
    res.status(status).json({
        error: err.message || 'Internal server error',
        code: err.code,
        requestId: reqId
    });
});

Validation Middleware

const { z } = require('zod');

function validate(schema) {
    return (req, res, next) => {
        const result = schema.safeParse(req.body);
        if (!result.success) {
            return res.status(400).json({
                error: 'Validation failed',
                issues: result.error.flatten()
            });
        }
        req.body = result.data;  // parsed + trimmed
        next();
    };
}

const createUserSchema = z.object({
    email: z.string().email(),
    password: z.string().min(8),
    name: z.string().min(2).max(100)
});

app.post('/api/users', validate(createUserSchema), async (req, res) => {
    // req.body artık validated ve typed
    const user = await db.users.create(req.body);
    res.status(201).json(user);
});

Rate Limit

const rateLimit = require('express-rate-limit');

// Global
app.use(rateLimit({ windowMs: 60000, max: 120 }));

// Hassas endpoint
app.use('/login', rateLimit({
    windowMs: 900000, max: 5,
    message: { error: 'Çok fazla giriş denemesi' }
}));

Pipeline Sıralaması

Middleware''lerin sırası çok önemli:

  • Security (helmet, cors) — en başta
  • Parser (express.json) — body''yi parse etmeden auth yapamazsın
  • Logger — başarısız istekleri de görmek için erken
  • Rate limit — kimlik doğrulamadan önce
  • Authentication — route''lardan önce
  • Routes
  • 404 handler — tüm route''lardan sonra
  • Error handler — en sonda

Modern Yazılım Geliştirme ve DevOps Pratikleri

Profesyonel yazılım geliştirme süreci üç pillar üzerine kuruludur: kaynak kontrolü (Git + GitHub/GitLab pull request akışı, code review zorunlu), CI/CD pipeline (otomatik test + lint + build + deploy), ve gözlemlenebilirlik (Sentry/Datadog/Grafana ile log, metric, trace toplama). Test piramidi (unit > integration > e2e) ile kod kalitesini garantilemek, mikroservis mimarisinde Docker container ve Kubernetes orkestrasyonu kullanmak, REST veya GraphQL API tasarımında OpenAPI/GraphQL Schema sözleşmesi tutmak modern standardlardır. Yazılım geliştirme yaşam döngüsü boyunca (gereksinim → tasarım → implementasyon → test → deploy → bakım) Agile/Scrum sprintleri 1-2 hafta, DevOps takımları sürekli teslim (continuous delivery) prensibiyle çalışır.

Node.js backend geliştirme

Express/Fastify ile API tasarımı, auth mimarisi ve production deploy için bize yazın

WhatsApp