Scarlet 1
Scarlet
Best Studio 1
Best Studio
mannaxxx 1
mannaxxx
Agora Metin2 1
Agora Metin2
[DEV]AB 1
[DEV]AB
Sevdamsın 1
Sevdamsın
TuZaKK 1
TuZaKK
kaptanmikro1 1
kaptanmikro1
Hikaye Ekle

[NODE JS] JSON API Donduren Basit Sunucu Yazma

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!

nodejs.png


[NODE JS] JSON API Donduren Basit Sunucu Yazma​


Selam arkadaslar, bugun ogrendigimiz HTTP bilgilerini birlestirip tam calisir bir JSON API sunucusu yazacagiz. Framework kullanmadan, sadece Node.js'in yerlesik modulleriyle production'a yakin bir API olusturacagiz. Ben bu egzersizi yeni baslayanlar icin cok degerli buluyorum cunku Express.js'in kaputun altinda ne yaptigini anlamanizi sagliyor.

API Sunucu Yapisini Kuralim​


Guzel bir API sunucusu yazmak icin birkac temel bilesene ihtiyacimiz var: bir router, bir body parser, hata yonetimi, loglama ve CORS destegi. Express.js bunlarin hepsini hazir sunuyor ama biz bunlari kendimiz yazarak ogrenelim. Boylece Express'i kullandigimizda ne yaptigini cok daha iyi anlayacagiz.

JavaScript:
const http = require('http');
const { URL } = require('url');

// ===== YARDIMCI FONKSIYONLAR =====

// JSON cevap gonder
function jsonYanit(res, statusKod, veri) {
    const json = JSON.stringify(veri, null, 2);
    res.writeHead(statusKod, {
        'Content-Type': 'application/json; charset=utf-8',
        'Content-Length': Buffer.byteLength(json),
        'X-Powered-By': 'NodeJS-Egitim',
        'Access-Control-Allow-Origin': '*',
        'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
        'Access-Control-Allow-Headers': 'Content-Type, Authorization'
    });
    res.end(json);
}

// Body oku
function bodyOku(req, maxBoyut = 1024 * 1024) {
    return new Promise((resolve, reject) => {
        let boyut = 0;
        const chunks = [];

        req.on('data', chunk => {
            boyut += chunk.length;
            if (boyut > maxBoyut) {
                req.destroy();
                reject(Object.assign(new Error('Body cok buyuk'), { statusKod: 413 }));
                return;
            }
            chunks.push(chunk);
        });

        req.on('end', () => {
            const raw = Buffer.concat(chunks).toString();
            if (!raw) { resolve(null); return; }
            try {
                resolve(JSON.parse(raw));
            } catch {
                reject(Object.assign(new Error('Gecersiz JSON'), { statusKod: 400 }));
            }
        });

        req.on('error', reject);
    });
}

// Basit loglama
function logIstek(req, statusKod, sure) {
    const renk = statusKod < 400 ? '\x1b[32m' : '\x1b[31m';
    const sifirla = '\x1b[0m';
    console.log(
        `${renk}${req.method} ${req.url} ${statusKod}${sifirla} - ${sure}ms`
    );
}

// ===== VERI KATMANI =====
let gorevler = [
    { id: 1, baslik: 'Node.js ogren', tamamlandi: false, oncelik: 'yuksek' },
    { id: 2, baslik: 'API yaz', tamamlandi: false, oncelik: 'orta' },
    { id: 3, baslik: 'Test yaz', tamamlandi: true, oncelik: 'dusuk' }
];
let sonrakiId = 4;

// ===== ROUTER =====
const rotalar = {};

function rotaEkle(metod, yol, isleyici) {
    const anahtar = `${metod} ${yol}`;
    rotalar[anahtar] = isleyici;
}

function rotaBul(metod, yol) {
    // Once tam eslestir
    const tamAnahtar = `${metod} ${yol}`;
    if (rotalar[tamAnahtar]) {
        return { isleyici: rotalar[tamAnahtar], params: {} };
    }

    // Sonra parametrik eslesme
    for (const [rota, isleyici] of Object.entries(rotalar)) {
        const [rotaMetod, rotaYol] = rota.split(' ');
        if (rotaMetod !== metod) continue;

        const rotaParcalari = rotaYol.split('/');
        const yolParcalari = yol.split('/');

        if (rotaParcalari.length !== yolParcalari.length) continue;

        const params = {};
        let eslesti = true;

        for (let i = 0; i < rotaParcalari.length; i++) {
            if (rotaParcalari[i].startsWith(':')) {
                params[rotaParcalari[i].slice(1)] = yolParcalari[i];
            } else if (rotaParcalari[i] !== yolParcalari[i]) {
                eslesti = false;
                break;
            }
        }

        if (eslesti) return { isleyici, params };
    }

    return null;
}

// ===== ROUTE TANIMLARI =====

// GET /api/gorevler - Tum gorevleri listele
rotaEkle('GET', '/api/gorevler', (req, res) => {
    const url = new URL(req.url, `http://${req.headers.host}`);
    let sonuc = [...gorevler];

    // Filtreleme
    const durum = url.searchParams.get('durum');
    if (durum === 'tamamlandi') sonuc = sonuc.filter(g => g.tamamlandi);
    if (durum === 'bekleyen') sonuc = sonuc.filter(g => !g.tamamlandi);

    jsonYanit(res, 200, { toplam: sonuc.length, gorevler: sonuc });
});

// GET /api/gorevler/:id
rotaEkle('GET', '/api/gorevler/:id', (req, res, params) => {
    const gorev = gorevler.find(g => g.id === parseInt(params.id));
    if (!gorev) return jsonYanit(res, 404, { hata: 'Gorev bulunamadi' });
    jsonYanit(res, 200, gorev);
});

// POST /api/gorevler
rotaEkle('POST', '/api/gorevler', async (req, res) => {
    const body = await bodyOku(req);
    if (!body || !body.baslik) {
        return jsonYanit(res, 400, { hata: 'baslik alani zorunlu' });
    }

    const yeniGorev = {
        id: sonrakiId++,
        baslik: body.baslik,
        tamamlandi: false,
        oncelik: body.oncelik || 'orta',
        olusturma: new Date().toISOString()
    };

    gorevler.push(yeniGorev);
    jsonYanit(res, 201, yeniGorev);
});

// PUT /api/gorevler/:id
rotaEkle('PUT', '/api/gorevler/:id', async (req, res, params) => {
    const index = gorevler.findIndex(g => g.id === parseInt(params.id));
    if (index === -1) return jsonYanit(res, 404, { hata: 'Gorev bulunamadi' });

    const body = await bodyOku(req);
    gorevler[index] = { ...gorevler[index], ...body, id: gorevler[index].id };
    jsonYanit(res, 200, gorevler[index]);
});

// DELETE /api/gorevler/:id
rotaEkle('DELETE', '/api/gorevler/:id', (req, res, params) => {
    const index = gorevler.findIndex(g => g.id === parseInt(params.id));
    if (index === -1) return jsonYanit(res, 404, { hata: 'Gorev bulunamadi' });

    const silinen = gorevler.splice(index, 1)[0];
    jsonYanit(res, 200, { mesaj: 'Silindi', gorev: silinen });
});

// ===== SUNUCU =====
const sunucu = http.createServer(async (req, res) => {
    const baslangic = Date.now();

    // CORS preflight
    if (req.method === 'OPTIONS') {
        res.writeHead(204, {
            'Access-Control-Allow-Origin': '*',
            'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE',
            'Access-Control-Allow-Headers': 'Content-Type'
        });
        res.end();
        return;
    }

    const url = new URL(req.url, `http://${req.headers.host}`);
    const eslesme = rotaBul(req.method, url.pathname);

    try {
        if (eslesme) {
            await eslesme.isleyici(req, res, eslesme.params);
        } else {
            jsonYanit(res, 404, { hata: 'Endpoint bulunamadi' });
        }
    } catch (error) {
        const kod = error.statusKod || 500;
        jsonYanit(res, kod, { hata: error.message });
    }

    logIstek(req, res.statusCode, Date.now() - baslangic);
});

sunucu.listen(3000, () => {
    console.log('API Sunucusu calisiyor: http://localhost:3000');
    console.log('\nKullanilabilir endpoint\'ler:');
    Object.keys(rotalar).forEach(r => console.log(`  ${r}`));
});

Sonuc​


Gordugunuz gibi, framework olmadan da gayet duzgun bir API sunucusu yazilabiliyor. Ama production'da Express.js veya Fastify gibi framework'ler kullanmanizi siddetle tavsiye ederim cunku routing, middleware zinciri, hata yonetimi, validation gibi bir cok konuda hazir cozumler sunuyorlar. Bu yaziinin amaci altyapiyi anlamaniz, her projenizi sifirdan yazmaniz degil. Sonraki konumuz HTML sayfasi donduren sunucu!
 

Şu an konuyu görüntüleyenler (Toplam : 0, Üye: 0, Misafir: 0)

Geri
Üst