Takip et

Node.js ve HTTP Modülü: Temel Kavramlar Nelerdir?

Node.js HTTP Modülü ile Web Sunucusu Oluşturma Rehberi

Günümüz dijital dünyasında her web sitesi, mobil uygulama ve hatta IoT cihazı, arka planda çalışan bir sunucuya ihtiyaç duyar. Peki, kendi web sunucunuzu sıfırdan oluşturmanın ne kadar kolay olduğunu hiç düşündünüz mü? Özellikle Node.js ve yerleşik HTTP modülü ile bu süreç, düşündüğünüzden çok daha basit ve erişilebilir hale geliyor. Bu kapsamlı rehberde, Node.js’in gücünü kullanarak kendi web sunucunuzu nasıl adım adım kuracağınızı, istekleri nasıl yöneteceğinizi ve hatta ileri düzey optimizasyonları nasıl uygulayacağınızı keşfedeceksiniz. Hazır mısınız? Kendi sunucunuzu inşa etme yolculuğuna başlayalım!

Node.js ve HTTP Modülü: Temel Kavramlar Nelerdir?

Web geliştirme dünyasında sunucular, istemcilerden (genellikle web tarayıcıları) gelen istekleri dinleyen, işleyen ve uygun yanıtları geri gönderen temel bileşenlerdir. Geleneksel olarak bu tür görevler için Apache, Nginx gibi özel sunucu yazılımları veya PHP, Java gibi dillerle yazılmış uygulamalar kullanılırdı. Ancak Node.js, JavaScript’i tarayıcının dışına taşıyarak geliştiricilere tam teşekküllü, yüksek performanslı ve ölçeklenebilir sunucu uygulamaları yazma imkanı sundu. Bu durum, özellikle gerçek zamanlı uygulamalar ve API servisleri için Node.js’i vazgeçilmez kıldı.

Node.js’in temelinde, Google Chrome’un V8 JavaScript motoru yatar. Bu motor, JavaScript kodunu makine koduna derleyerek inanılmaz bir hız sağlar. Node.js’i diğer sunucu teknolojilerinden ayıran en önemli özelliklerden biri ise olay tabanlı (event-driven) ve engellemeyen (non-blocking) I/O modelidir. Geleneksel sunucular her yeni istek için yeni bir iş parçacığı (thread) oluştururken, Node.js tek bir iş parçacığı üzerinde çalışır ve gelen tüm istekleri bir olay döngüsü (event loop) aracılığıyla yönetir. Bu, sunucunun aynı anda binlerce bağlantıyı çok daha az kaynak tüketerek yönetebilmesini sağlar. Örneğin, bir veritabanı sorgusu veya dosya okuma işlemi gibi uzun süren bir operasyon başladığında, Node.js bu işlemin bitmesini beklemez; bunun yerine diğer istekleri işlemeye devam eder ve uzun süren işlem bittiğinde bir geri çağırma (callback) fonksiyonu aracılığıyla bilgilendirilir. Bu mimari, Node.js uygulamalarının genellikle çok daha hızlı ve verimli olmasını sağlar.

Peki, bir web sunucusu oluşturmak için Node.js’in hangi kısmına ihtiyacımız var? İşte burada HTTP modülü devreye giriyor. Node.js, kurulumuyla birlikte birçok yerleşik modülle gelir ve HTTP modülü de bunlardan biridir. Bu modül, Node.js uygulamalarının HTTP sunucuları ve istemcileri oluşturmasına olanak tanıyan temel işlevleri sağlar. Yani, web tarayıcılarının konuştuğu dili (HTTP protokolünü) anlamak ve bu dilde iletişim kurmak için gereken tüm araçları bize sunar. HTTP modülü sayesinde, gelen istekleri dinleyebilir, isteğin URL’sini, metodunu (GET, POST vb.), başlıklarını (headers) ve gövdesini (body) okuyabiliriz. Aynı şekilde, istemciye geri göndereceğimiz yanıtın durum kodunu (200 OK, 404 Not Found), başlıklarını ve içeriğini de bu modül aracılığıyla belirleyebiliriz. Kısacası, HTTP modülü, Node.js tabanlı web sunucumuzun beynini ve iletişim merkezini oluşturur.

Uzman İpucu: Node.js’in olay döngüsü modelini anlamak, uygulamanızın performansını ve ölçeklenebilirliğini optimize etmek için kritik öneme sahiptir. Uzun süreli CPU yoğun işlemlerden kaçınarak veya bunları worker thread’lere taşıyarak uygulamanızın “tıkanmasını” önleyebilirsiniz.

Bu temel kavramları anladıktan sonra, artık ilk Node.js web sunucumuzu kurmaya ve Node.js’in HTTP modülü ile nasıl etkileşime geçtiğini uygulamalı olarak görmeye hazırız. Bu modül, web sunucusu geliştirmenin temellerini öğrenmek için mükemmel bir başlangıç noktasıdır ve birçok popüler Node.js web çatısının (Express.js, Koa.js vb.) temelini oluşturur. Dolayısıyla, bu modülü iyi anlamak, ileri düzey web geliştirme becerileri edinmeniz için sağlam bir zemin hazırlayacaktır. Şimdi, bu teorik bilgileri pratiğe dökelim ve kendi sunucumuzu hayata geçirelim.

İlk Node.js Web Sunucunuzu Adım Adım Nasıl Kurarsınız?

Kendi web sunucunuzu oluşturma fikri kulağa karmaşık gelebilir, ancak Node.js’in HTTP modülü sayesinde bu süreç şaşırtıcı derecede basittir. Bu bölümde, “Merhaba Dünya!” mesajını döndüren temel bir web sunucusunu nasıl kuracağınızı adım adım öğreneceksiniz. Bu, Node.js ile sunucu tarafı programlamaya atacağınız ilk ve en önemli adımdır.

1. Node.js Kurulumu ve Proje Başlatma

Öncelikle bilgisayarınızda Node.js’in kurulu olduğundan emin olmalısınız. Eğer kurulu değilse, Node.js resmi web sitesinden işletim sisteminize uygun sürümü indirip kurabilirsiniz. Kurulumu tamamladıktan sonra, bir terminal veya komut istemcisi açarak aşağıdaki komutlarla Node.js ve npm (Node Package Manager) sürümlerini kontrol edebilirsiniz:


      node -v
      npm -v
    

Bu komutlar size kurulu sürümleri gösterecektir. Ardından, projeniz için yeni bir dizin oluşturun ve bu dizine geçin:


      mkdir my-first-server
      cd my-first-server
    

Bu dizinde, sunucu kodumuzu içeren bir JavaScript dosyası oluşturacağız. Örneğin, server.js adında bir dosya oluşturabilirsiniz.

2. HTTP Modülünü İçeri Aktarma ve Sunucu Oluşturma

server.js dosyanızın içine aşağıdaki kodu ekleyin. Bu kod parçası, Node.js’in HTTP modülünü kullanarak basit bir web sunucusu oluşturmanın temelini atar:


      // 1. HTTP modülünü içeri aktarıyoruz
      const http = require('http');

      // 2. Sunucunun dinleyeceği port numarasını ve ana bilgisayar adını tanımlıyoruz
      const hostname = '127.0.0.1'; // localhost
      const port = 3000;

      // 3. Bir sunucu oluşturuyoruz
      const server = http.createServer((req, res) => {
          // Gelen her istek için çalışacak fonksiyon
          console.log(Gelen istek: ${req.method} ${req.url});

          // Yanıtın HTTP durum kodunu ayarlıyoruz (200 OK)
          res.statusCode = 200;
          // Yanıt başlığını ayarlıyoruz: İçerik tipi düz metin (plain text)
          res.setHeader('Content-Type', 'text/plain; charset=utf-8');

          // Yanıtı gönderiyoruz
          res.end('Merhaba Dunya! Node.js Sunucum Calisiyor!\n');
      });

      // 4. Sunucuyu belirtilen port ve ana bilgisayar üzerinde dinlemeye başlıyoruz
      server.listen(port, hostname, () => {
          console.log(Sunucu http://${hostname}:${port}/ adresinde çalışıyor);
      });
    

Şimdi bu kod bloğunu adım adım inceleyelim:

  • const http = require('http');: Bu satır, Node.js’in yerleşik HTTP modülünü projemize dahil eder. require() fonksiyonu, Node.js’te modülleri içeri aktarmak için kullanılır.
  • const hostname = '127.0.0.1'; ve const port = 3000;: Bu satırlar, sunucumuzun hangi IP adresinde (127.0.0.1 genellikle localhost’u temsil eder) ve hangi port numarası üzerinde (3000 popüler bir geliştirme portudur) dinleyeceğini belirtir.
  • const server = http.createServer((req, res) => { ... });: Burası işin kalbidir. http.createServer() metodu, yeni bir HTTP sunucusu nesnesi oluşturur. Bu metoda bir geri çağırma fonksiyonu (callback function) geçirilir. Bu fonksiyon, sunucuya her yeni istek geldiğinde çalışır.
    • req (request – istek) objesi, istemciden gelen istekle ilgili tüm bilgileri (URL, HTTP metodu, başlıklar, veri vb.) içerir.
    • res (response – yanıt) objesi, sunucunun istemciye geri göndereceği yanıtı oluşturmak için kullanılır.
  • console.log(Gelen istek: ${req.method} ${req.url});: Bu satır, her istek geldiğinde terminale isteğin metodunu ve URL’sini yazdırır. Bu, geliştirme sırasında çok faydalıdır.
  • res.statusCode = 200;: Yanıtın HTTP durum kodunu 200 olarak ayarlarız. 200, isteğin başarılı bir şekilde işlendiği anlamına gelir.
  • res.setHeader('Content-Type', 'text/plain; charset=utf-8');: Yanıt başlıklarını ayarlarız. Content-Type başlığı, istemciye gönderilen verinin tipini bildirir. Burada düz metin (plain text) gönderdiğimizi belirtiyoruz. charset=utf-8 ise Türkçe karakterlerin düzgün görünmesini sağlar.
  • res.end('Merhaba Dunya! Node.js Sunucum Calisiyor!\n');: Bu satır, yanıtın gövdesini (body) belirler ve yanıtı istemciye gönderir. res.end() çağrıldığında, yanıt işlemi tamamlanır ve bağlantı kapatılır.
  • server.listen(port, hostname, () => { ... });: Bu metod, yukarıda tanımladığımız sunucuyu belirtilen port ve ana bilgisayar üzerinde dinlemeye başlatır. Sunucu başarıyla dinlemeye başladığında, içindeki geri çağırma fonksiyonu çalışır ve terminale bir mesaj yazdırılır.

3. Sunucuyu Çalıştırma ve Test Etme

Kodunuzu kaydettikten sonra, terminalinizde proje dizininizdeyken aşağıdaki komutu çalıştırın:


      node server.js
    

Terminalde “Sunucu http://127.0.0.1:3000/ adresinde çalışıyor” mesajını görmelisiniz. Şimdi bir web tarayıcısı açın ve adres çubuğuna http://localhost:3000 yazın. Tarayıcınızda “Merhaba Dunya! Node.js Sunucum Calisiyor!” mesajını görmelisiniz. Terminalinize geri döndüğünüzde ise tarayıcınızdan gelen isteğin (GET /) loglandığını fark edeceksiniz.

Tebrikler! Kendi Node.js web sunucunuzu başarıyla kurdunuz ve çalıştırdınız. Bu basit “Merhaba Dünya” sunucusu, tüm karmaşık web uygulamalarının temelini oluşturur. Bir sonraki bölümde, bu temel sunucuyu daha işlevsel hale getirerek farklı URL’lere (yollara) nasıl yanıt vereceğimizi ve istekleri nasıl yöneteceğimizi öğreneceğiz.

İstekleri ve Yanıtları Anlamak: Dinamik Routing Nasıl Yapılır?

Önceki bölümde basit bir “Merhaba Dünya” sunucusu oluşturduk. Ancak gerçek dünya uygulamalarında, kullanıcılar farklı URL’lere (yollara) gider ve her birine özel içerik sunmak isteriz. İşte bu noktada routing (yönlendirme) kavramı devreye girer. Routing, gelen HTTP isteklerini URL’lerine ve metotlarına (GET, POST, PUT, DELETE vb.) göre farklı işleyicilere yönlendirme işlemidir. Node.js’in HTTP modülü ile bu yönlendirmeyi manuel olarak nasıl yapacağımızı öğrenelim.

İstek Objeleri (req) ile Çalışmak

Sunucu geri çağırma fonksiyonumuzdaki req (request) objesi, istemciden gelen istekle ilgili değerli bilgiler içerir. En sık kullanacaklarımız şunlardır:

  • req.url: İsteğin URL yolunu döndürür (örneğin, /hakkinda, /api/users).
  • req.method: İsteğin HTTP metodunu döndürür (örneğin, GET, POST).
  • req.headers: İsteğin başlıklarını içeren bir obje.
  • req.body: POST veya PUT gibi isteklerde gönderilen veri (bu veri varsayılan olarak okunmaz, akış olarak gelir ve ayrıca işlenmesi gerekir).

Yanıt Objeleri (res) ile Çalışmak

res (response) objesi ise istemciye geri gönderilecek yanıtı yapılandırmak için kullanılır. Temel özelliklerini zaten gördük:

  • res.statusCode: HTTP durum kodu (200, 404, 500 vb.).
  • res.setHeader(name, value): Yanıt başlığı eklemek için.
  • res.end(data): Yanıtı tamamlar ve isteğe veri gönderir.

Dinamik Routing Uygulaması

Şimdi server.js dosyamızı güncelleyerek farklı URL’ler için farklı yanıtlar gönderen bir routing mekanizması oluşturalım:


      const http = require('http');

      const hostname = '127.0.0.1';
      const port = 3000;

      const server = http.createServer((req, res) => {
          console.log(Gelen istek: ${req.method} ${req.url});

          // Yanıtın Content-Type'ını varsayılan olarak HTML yapalım
          res.setHeader('Content-Type', 'text/html; charset=utf-8');

          if (req.url === '/') {
              // Ana sayfa isteği
              res.statusCode = 200;
              res.end('

Ana Sayfa

Node.js ile ilk sunucunuza hos geldiniz!

'); } else if (req.url === '/hakkinda') { // Hakkında sayfası isteği res.statusCode = 200; res.end('

Hakkinda Sayfasi

Bu, Node.js HTTP modulu ile olusturulmus basit bir web sunucusudur.

'); } else if (req.url === '/api/kullanicilar' && req.method === 'GET') { // API isteği: Kullanıcıları listele res.statusCode = 200; res.setHeader('Content-Type', 'application/json; charset=utf-8'); // JSON yanıtı const users = [ { id: 1, name: 'Alice' }, { id: 2, name: 'Bob' } ]; res.end(JSON.stringify(users)); // JavaScript objesini JSON string'ine dönüştür } else if (req.url === '/api/kullanicilar' && req.method === 'POST') { // API isteği: Yeni kullanıcı oluştur let body = ''; req.on('data', chunk => { body += chunk.toString(); // Gelen veriyi birleştir }); req.on('end', () => { try { const newUser = JSON.parse(body); console.log('Yeni kullanıcı oluşturuldu:', newUser); res.statusCode = 201; // 201 Created res.setHeader('Content-Type', 'application/json; charset=utf-8'); res.end(JSON.stringify({ message: 'Kullanıcı başarıyla oluşturuldu', user: newUser })); } catch (error) { res.statusCode = 400; // 400 Bad Request res.setHeader('Content-Type', 'application/json; charset=utf-8'); res.end(JSON.stringify({ message: 'Geçersiz JSON formatı' })); } }); } else { // Bulunamayan sayfa res.statusCode = 404; res.end('

404 Sayfa Bulunamadi

Aradiginiz sayfa mevcut degil.

'); } }); server.listen(port, hostname, () => { console.log(Sunucu http://${hostname}:${port}/ adresinde çalışıyor); });

Bu güncellenmiş kodda neler değişti?

  • if (req.url === '/') { ... } gibi koşullu ifadeler kullanarak req.url değerine göre farklı kod bloklarını çalıştırıyoruz. Bu, temel routing mantığını oluşturur.
  • /hakkinda yolu için farklı bir HTML içeriği gönderiyoruz.
  • /api/kullanicilar yolu için hem GET hem de POST metodlarını ele alıyoruz.
    • GET /api/kullanicilar isteğinde, Content-Type‘ı application/json olarak ayarlıyor ve bir JavaScript dizisini JSON.stringify() kullanarak JSON formatında geri gönderiyoruz.
    • POST /api/kullanicilar isteğinde, istemciden gelen veriyi (genellikle JSON formatında) nasıl okuyacağımızı gösteriyoruz. req.on('data', ...) ile veri parçalarını (chunks) topluyor, req.on('end', ...) ile tüm veri geldiğinde işlemi tamamlıyoruz. Gelen JSON verisini JSON.parse() ile JavaScript objesine dönüştürüyor ve uygun bir yanıt gönderiyoruz. Hata durumlarını da (geçersiz JSON gibi) ele alıyoruz.
  • Son olarak, hiçbir koşula uymayan istekler için 404 Sayfa Bulunamadı yanıtı gönderiyoruz.

Bu routing mekanizması, sunucunuzun farklı isteklere akıllıca yanıt vermesini sağlar. Tarayıcınızda http://localhost:3000/, http://localhost:3000/hakkinda ve http://localhost:3000/api/kullanicilar adreslerini ziyaret ederek farkı görebilirsiniz. POST isteğini test etmek için Postman veya benzeri bir API test aracı kullanmanız gerekecektir.

Uzman İpucu: Karmaşık uygulamalarda, bu manuel routing yaklaşımı hızla yönetilemez hale gelebilir. Bu nedenle Express.js gibi daha yüksek seviyeli çerçeveler, routing için çok daha güçlü ve okunabilir API’ler sunar. Ancak HTTP modülü ile temelini anlamak, bu çerçevelerin nasıl çalıştığını kavramanıza yardımcı olur.

Bu bölümle birlikte, Node.js HTTP modülü ile sadece statik mesajlar değil, aynı zamanda isteğe bağlı olarak farklı içerikler sunabilen ve hatta API isteklerini işleyebilen daha dinamik bir web sunucusu oluşturmayı öğrendiniz. Bir sonraki adımda, sunucumuzun sadece metin değil, aynı zamanda HTML, CSS ve JavaScript gibi statik dosyaları da nasıl sunabileceğini keşfedeceğiz.

Statik Dosyaları Sunmak ve Dinamik İçerik Oluşturmak Mümkün mü?

Şimdiye kadar, Node.js sunucumuz aracılığıyla düz metin veya doğrudan HTML string’leri gönderdik. Ancak modern web uygulamaları, HTML dosyaları, CSS stil sayfaları, JavaScript betikleri ve görseller gibi birçok statik dosyadan oluşur. Bu bölümde, Node.js HTTP modülü ile bu tür statik dosyaları nasıl sunacağımızı ve dinamik içerik oluşturma potansiyelini kısaca ele alacağız.

Statik Dosya Sunumu İçin Dosya Sistemi (fs) Modülü

Node.js’in yerleşik fs (File System) modülü, dosyaları okuma, yazma ve yönetme gibi işlemler için kullanılır. Statik dosya sunumu için bu modülü kullanarak, istemcinin istediği dosyayı sunucumuzun dosya sisteminden okuyup yanıt olarak göndereceğiz. Bu işlem, özellikle küçük ve orta ölçekli uygulamalar veya sadece bir HTML sayfasını sunmak istediğiniz durumlar için oldukça kullanışlıdır.

Öncelikle, projenizin kök dizininde public adında bir klasör oluşturalım. Bu klasörün içine index.html, style.css ve script.js gibi örnek dosyalar ekleyelim:


      // public/index.html
      <!DOCTYPE html>
      <html lang="tr">
      <head>
          <meta charset="UTF-8">
          <meta name="viewport" content="width=device-width, initial-scale=1.0">
          <title>Node.js Statik Sunucu</title>
          <link rel="stylesheet" href="/style.css">
      </head>
      <body>
          <h1>Statik Dosya Sunumu</h1>
          <p>Bu sayfa Node.js sunucusu tarafindan sunulmaktadir.</p>
          <button id="myButton">Bana Tikla</button>
          <script src="/script.js"></script>
      </body>
      </html>
    

      // public/style.css
      body {
          font-family: Arial, sans-serif;
          background-color: #f4f4f4;
          color: #333;
          text-align: center;
          padding-top: 50px;
      }
      h1 {
          color: #0056b3;
      }
      button {
          padding: 10px 20px;
          background-color: #28a745;
          color: white;
          border: none;
          cursor: pointer;
          border-radius: 5px;
      }
    

      // public/script.js
      document.getElementById('myButton').addEventListener('click', () => {
          alert('Butona tikladiniz! JavaScript calisiyor.');
      });
    

Şimdi server.js dosyamızı güncelleyerek bu statik dosyaları sunacak mantığı ekleyelim:


      const http = require('http');
      const fs = require('fs'); // Dosya sistemi modülünü dahil ediyoruz
      const path = require('path'); // Yol modülünü dahil ediyoruz

      const hostname = '127.0.0.1';
      const port = 3000;

      const server = http.createServer((req, res) => {
          console.log(Gelen istek: ${req.method} ${req.url});

          // İstek URL'sine göre dosya yolunu belirliyoruz
          let filePath = '.' + req.url;
          if (filePath === './') {
              filePath = './public/index.html'; // Ana dizin isteği için index.html
          } else {
              filePath = './public' + req.url; // Diğer statik dosyalar için
          }

          // Dosya uzantısına göre Content-Type belirleme fonksiyonu
          const getContentType = (filePath) => {
              const extname = String(path.extname(filePath)).toLowerCase();
              const mimeTypes = {
                  '.html': 'text/html',
                  '.js': 'text/javascript',
                  '.css': 'text/css',
                  '.json': 'application/json',
                  '.png': 'image/png',
                  '.jpg': 'image/jpg',
                  '.gif': 'image/gif',
                  '.svg': 'image/svg+xml',
                  '.ico': 'image/x-icon'
              };
              return mimeTypes[extname] || 'application/octet-stream';
          };

          // Dosyayı okuma ve gönderme işlemi
          fs.readFile(filePath, (error, content) => {
              if (error) {
                  if (error.code === 'ENOENT') {
                      // Dosya bulunamadı hatası
                      res.statusCode = 404;
                      res.setHeader('Content-Type', 'text/html; charset=utf-8');
                      res.end('

404 Sayfa Bulunamadi

Aradiginiz sayfa mevcut degil.

'); } else { // Diğer sunucu hataları res.statusCode = 500; res.setHeader('Content-Type', 'text/html; charset=utf-8'); res.end(

500 Sunucu Hatasi

Sunucuda bir hata olustu: ${error.code}

); } } else { // Dosya başarıyla okundu res.statusCode = 200; res.setHeader('Content-Type', getContentType(filePath) + '; charset=utf-8'); res.end(content, 'utf-8'); } }); }); server.listen(port, hostname, () => { console.log(Sunucu http://${hostname}:${port}/ adresinde çalışıyor); });

Bu kodda önemli değişiklikler:

  • fs ve path modüllerini dahil ettik. path modülü, dosya yollarıyla çalışmayı kolaylaştırır.
  • filePath değişkenini, istenen URL’ye göre ./public/ dizini içinde bir dosya yolu oluşturacak şekilde güncelledik. Ana dizin (/) isteği için index.html‘i varsayılan yaptık.
  • getContentType adında bir yardımcı fonksiyon oluşturduk. Bu fonksiyon, dosya uzantısına (.html, .css, .js vb.) göre uygun Content-Type başlığını belirler. Bu, tarayıcının dosyayı doğru şekilde yorumlaması için kritik öneme sahiptir.
  • fs.readFile(filePath, (error, content) => { ... }); asenkron fonksiyonu ile belirtilen dosyayı okuyoruz.
    • Eğer bir hata olursa (örneğin dosya bulunamazsa – ENOENT), uygun bir HTTP durum kodu (404 veya 500) ve hata mesajı gönderiyoruz.
    • Eğer dosya başarıyla okunursa, 200 durum kodu, doğru Content-Type başlığı ve dosyanın içeriğini (content) yanıt olarak gönderiyoruz.

Sunucuyu yeniden başlatın (Ctrl+C ile durdurup node server.js ile tekrar başlatın) ve http://localhost:3000/ adresine gidin. Artık CSS ile stilize edilmiş, JavaScript etkileşimi olan bir HTML sayfasını göreceksiniz. Tarayıcınızın geliştirici araçlarını açarak network sekmesinde index.html, style.css ve script.js dosyalarının ayrı ayrı yüklendiğini de gözlemleyebilirsiniz.

Dinamik İçerik Oluşturma Potansiyeli

HTTP modülü ile statik dosya sunumu yapabilsek de, daha karmaşık dinamik içerikler için (örneğin, bir veritabanından veri çekip HTML’ye yerleştirmek) bu manuel yaklaşım yetersiz kalabilir. Bu noktada, genellikle “template engine” (şablon motoru) adı verilen araçlar devreye girer. Pug (eski adıyla Jade), EJS (Embedded JavaScript) veya Handlebars gibi şablon motorları, HTML şablonlarının içine JavaScript değişkenlerini veya döngülerini gömmeye olanak tanır. Node.js HTTP modülü, bu şablon motorlarını doğrudan desteklemez, ancak bir şablon motoru modülünü içeri aktarıp onunla birlikte çalışabiliriz. Bu, genellikle Express.js gibi daha üst düzey framework’ler içinde çok daha kolay entegre edilir.

Özetle, Node.js HTTP modülü ve fs modülü ile statik dosyaları sunmak oldukça mümkündür ve basit projeler için harika bir çözümdür. Ancak daha karmaşık routing, ara yazılım (middleware) yönetimi ve dinamik içerik oluşturma ihtiyaçlarınız olduğunda, Express.js gibi framework’ler size çok daha fazla kolaylık ve yapı sunacaktır. Bu temel bilgileri edinmek, o framework’lerin nasıl çalıştığını anlamanız için sağlam bir temel sağlar.

Web Sunucunuzu Daha Performanslı ve Güvenli Hale Nasıl Getirirsiniz?

Basit bir web sunucusu oluşturmak harika bir başlangıçtır, ancak gerçek dünya uygulamalarında performans ve güvenlik kritik öneme sahiptir. Node.js’in HTTP modülü, temel işlevselliği sağlasa da, bu alanlarda manuel olarak bazı önlemler almanız gerekir. Bu bölümde, sunucunuzu daha dayanıklı, hızlı ve güvenli hale getirmek için uygulayabileceğiniz bazı ipuçlarını ve teknikleri inceleyeceğiz.

Performans İpuçları

Node.js, asenkron yapısı sayesinde doğal olarak yüksek performanslıdır, ancak bazı optimizasyonlar daha da iyi sonuçlar verebilir:

  1. Önbellekleme (Caching): Özellikle statik dosyalar için, tarayıcıların veya proxy sunucularının dosyaları tekrar indirmesini önlemek için önbellekleme başlıkları kullanın.
    • Cache-Control: Tarayıcıya bir kaynağın ne kadar süreyle önbelleğe alınabileceğini ve nasıl davranması gerektiğini söyler (örneğin, public, max-age=31536000 bir yıl boyunca önbelleğe al).
    • Expires: Belirli bir tarihe kadar önbelleğe alınmasını sağlar.
    • ETag veya Last-Modified: Tarayıcının, kaynağın değişip değişmediğini sunucuya sormasına olanak tanır. Değişmediyse, sunucu 304 Not Modified yanıtı göndererek tekrar veri göndermez.
    
                  // Örnek: Statik dosya sunumunda Cache-Control ekleme
                  res.setHeader('Cache-Control', 'public, max-age=3600'); // 1 saat önbelleğe al
                  res.setHeader('ETag', 'some-unique-hash-of-file-content'); // Dosya içeriğine göre bir hash
                  res.end(content, 'utf-8');
                
  2. Gzip Sıkıştırma: Büyük metin tabanlı dosyaları (HTML, CSS, JS) istemciye göndermeden önce sıkıştırmak, ağ trafiğini azaltır ve yükleme sürelerini hızlandırır. Node.js’in zlib modülü ile bunu manuel olarak yapabilir veya bir ara yazılım kütüphanesi kullanabilirsiniz.
    
                  const zlib = require('zlib');
                  // ... sunucu içinde
                  if (req.headers['accept-encoding'] && req.headers['accept-encoding'].includes('gzip')) {
                      res.setHeader('Content-Encoding', 'gzip');
                      zlib.gzip(content, (err, result) => {
                          if (!err) res.end(result);
                          else res.end(content); // Hata durumunda sıkıştırmadan gönder
                      });
                  } else {
                      res.end(content);
                  }
                
  3. Keep-Alive Bağlantıları: HTTP/1.1 varsayılan olarak bağlantıları “keep-alive” tutar, yani aynı istemci birden fazla istek için aynı TCP bağlantısını kullanabilir. Bu, her istek için yeni bir bağlantı kurma maliyetini ortadan kaldırır. Node.js HTTP modülü bunu otomatik olarak yönetir, ancak sunucu ayarlarında server.timeout ve server.keepAliveTimeout gibi değerleri optimize etmek isteyebilirsiniz.
  4. Asenkron İşlemleri Optimize Etme: Veritabanı sorguları, dosya işlemleri gibi I/O yoğun görevlerde geri çağırma fonksiyonlarını veya Promises/async-await yapısını doğru kullanmak, olay döngüsünü engellememek için hayati öneme sahiptir.

Güvenlik İpuçları

Web sunucuları sürekli olarak saldırı tehdidi altındadır. Temel HTTP modülü ile çalışırken dikkate almanız gereken bazı güvenlik önlemleri:

  1. Girdi Doğrulama (Input Validation): İstemciden gelen her türlü veriyi (URL parametreleri, POST gövdesi, başlıklar) asla güvenilir kabul etmeyin. Sunucunuzda bu verileri mutlaka doğrulayın ve temizleyin (sanitize). SQL enjeksiyonu, XSS (Cross-Site Scripting) gibi saldırıları önlemek için bu kritik öneme sahiptir.
    
                  // Örnek: URL parametresi doğrulama (basit)
                  const url = require('url');
                  const myUrl = url.parse(req.url, true);
                  const userId = parseInt(myUrl.query.id);
                  if (isNaN(userId)) {
                      res.statusCode = 400;
                      res.end('Gecersiz Kullanici ID');
                      return;
                  }
                  // ... userId ile güvenli bir şekilde devam et
                
  2. Hata Yönetimi (Error Handling): Uygulamanızdaki hataların istemcilere hassas bilgiler sızdırmadığından emin olun. Üretim ortamında ayrıntılı hata mesajları yerine genel hata mesajları gösterin. Sunucunuzun çökmesini önlemek için try-catch blokları ve process.on('uncaughtException', ...) gibi global hata yakalayıcılar kullanın.
    
                  process.on('uncaughtException', (err) => {
                      console.error('Yakalanmayan hata:', err);
                      // Üretim ortamında sunucuyu kapatmak yerine, hata loglayıp çalışmaya devam etmeye çalışın
                      // veya graceful shutdown (düzenli kapatma) uygulayın
                  });
    
                  // ... sunucu içinde
                  try {
                      // Potansiyel hata olabilecek kod
                  } catch (error) {
                      res.statusCode = 500;
                      res.end('Sunucu ic hatasi');
                  }
                
  3. HTTP Başlıklarını Güvenli Hale Getirme: Güvenlik açıklarını azaltmak için bazı HTTP başlıklarını ayarlayın:
    • X-Content-Type-Options: nosniff: Tarayıcının Content-Type başlığını değiştirmesini engeller.
    • X-Frame-Options: DENY: Clickjacking saldırılarını önlemek için sayfanızın başka bir sitede bir <iframe> içinde görüntülenmesini engeller.
    • Content-Security-Policy (CSP): XSS saldırılarına karşı güçlü bir koruma sağlar. Hangi kaynaklardan komut dosyaları, stiller vb. yüklenmesine izin verildiğini belirtir.
    
                  res.setHeader('X-Content-Type-Options', 'nosniff');
                  res.setHeader('X-Frame-Options', 'DENY');
                  // res.setHeader('Content-Security-Policy', "default-src 'self'"); // Daha karmaşık olabilir
                
  4. HTTPS Kullanımı: Hassas verilerin şifrelenmesi için HTTP yerine HTTPS kullanmak zorunludur. Node.js’in https modülü, SSL/TLS sertifikaları ile güvenli sunucular oluşturmanıza olanak tanır.
    
                  // HTTPS sunucusu örneği (sertifika ve anahtar gerektirir)
                  const https = require('https');
                  const fs = require('fs');
    
                  const options = {
                      key: fs.readFileSync('path/to/your/private.key'),
                      cert: fs.readFileSync('path/to/your/certificate.crt')
                  };
    
                  https.createServer(options, (req, res) => {
                      // ... aynı HTTP sunucu mantığı
                  }).listen(8443, () => {
                      console.log('HTTPS sunucusu 8443 portunda çalışıyor');
                  });
                

Mobil Uyumlu Tasarım İçin HTML ve CSS İpuçları

Sunucu tarafındaki performans ve güvenlik kadar, istemci tarafındaki kullanıcı deneyimi de önemlidir. Mobil cihazlarda iyi görünen ve çalışan web siteleri oluşturmak için:

  1. Duyarlı Tasarım (Responsive Design): CSS Media Query’ler kullanarak farklı ekran boyutlarına göre stil kuralları uygulayın.
    
                  /* style.css dosyanıza ekleyebilirsiniz */
                  /* Genel stiller */
                  body {
                      font-size: 16px;
                  }
    
                  /* Küçük ekranlar için (örneğin mobil cihazlar) */
                  @media (max-width: 600px) {
                      body {
                          font-size: 14px;
                          padding: 10px;
                      }
                      h1 {
                          font-size: 1.5em;
                      }
                  }
    
                  /* Orta ekranlar için (örneğin tabletler) */
                  @media (min-width: 601px) and (max-width: 1024px) {
                      body {
                          font-size: 15px;
                      }
                      h1 {
                          font-size: 2em;
                      }
                  }
                
  2. Meta Viewport Etiketi: HTML’nizin <head> bölümüne aşağıdaki etiketi ekleyerek tarayıcıya sayfanın cihaz genişliğine göre ölçeklenmesi gerektiğini bildirin:
    
                  <meta name="viewport" content="width=device-width, initial-scale=1.0">
                
  3. Mobil Öncelikli Geliştirme (Mobile-First): Tasarım ve geliştirmeye en küçük ekran boyutundan başlayarak, daha büyük ekranlara doğru ilerlemek, daha temiz ve performanslı bir kod tabanı sağlar.

Bu performans ve güvenlik ipuçları, Node.js HTTP modülü ile oluşturduğunuz sunucunun sadece çalışmasını değil, aynı zamanda gerçek dünya senaryolarında güvenilir ve verimli bir şekilde hizmet vermesini de sağlayacaktır. Unutmayın ki güvenlik ve performans sürekli bir süreçtir ve uygulamanız büyüdükçe bu alanlara daha fazla yatırım yapmanız gerekecektir.

Sonuç ve Sıkça Sorulan Sorular

Bu kapsamlı rehber boyunca, Node.js’in gücünü ve yerleşik HTTP modülünün esnekliğini kullanarak sıfırdan bir web sunucusu oluşturmayı adım adım öğrendik. Temel “Merhaba Dünya” sunucusundan başlayarak, istekleri ve yanıtları nasıl yöneteceğimizi, farklı URL’ler için dinamik routing nasıl yapacağımızı ve hatta statik dosyaları nasıl sunacağımızı keşfettik. Ayrıca, sunucunuzu daha dayanıklı, hızlı ve güvenli hale getirmek için performans ve güvenlik ipuçlarını da ele aldık. Mobil uyumlu tasarımın önemine değinerek, kullanıcı deneyimini iyileştirmenin yollarını da gördük.

Node.js HTTP modülü, web sunucusu geliştirmenin temellerini anlamak için mükemmel bir araçtır. Daha karmaşık uygulamalar için Express.js, Koa.js gibi framework’ler bu modülün üzerine inşa edilmiştir ve size daha fazla kolaylık, yapı ve genişletilebilirlik sunar. Ancak temel modülü anlamak, bu framework’lerin perde arkasında nasıl çalıştığına dair değerli bir içgörü sağlar ve sizi daha yetkin bir Node.js geliştiricisi yapar. Kendi sunucunuzu oluşturma yolculuğunuzda edindiğiniz bu bilgilerle, artık daha karmaşık web projelerine adım atmaya hazırsınız. Unutmayın, pratik yapmak ve farklı senaryoları denemek, öğrenmenin en iyi yoludur. İyi kodlamalar!

Sıkça Sorulan Sorular (SSS)

Node.js HTTP modülü ile Express.js arasındaki temel fark nedir?

Node.js HTTP modülü, bir HTTP sunucusu oluşturmak için gereken en temel işlevleri (istek/yanıt işleme, port dinleme vb.) sağlayan yerleşik bir modüldür. Express.js ise, HTTP modülünün üzerine inşa edilmiş, routing, ara yazılım (middleware) yönetimi, şablon motoru entegrasyonu gibi birçok ek özellik ve kolaylık sunan bir web framework’üdür. HTTP modülü “ham” bir API iken, Express.js geliştirme sürecini hızlandıran ve daha organize hale getiren bir soyutlama katmanı sunar.

HTTP modülü ile kurduğum sunucuyu üretim ortamında kullanabilir miyim?

Teorik olarak evet, ancak pratik olarak küçük ve çok basit projeler dışında önerilmez. HTTP modülü ile kurulan sunucular, hata yönetimi, güvenlik başlıkları, oturum yönetimi, dosya yükleme, veritabanı entegrasyonu gibi birçok gelişmiş özelliği manuel olarak uygulamanızı gerektirir. Bu da zaman alıcı ve hataya açık olabilir. Üretim ortamında genellikle Express.js gibi daha olgun ve kapsamlı framework’ler tercih edilir, çünkü bunlar bu tür görevler için sağlam ve test edilmiş çözümler sunar.

Node.js sunucumun performansını artırmak için başka neler yapabilirim?

Performansı artırmak için birkaç yol vardır:

  • Ölçeklendirme: Node.js tek iş parçacıklı olduğu için, CPU’nun tüm çekirdeklerini kullanmak üzere cluster modülünü kullanarak birden fazla Node.js işlemi çalıştırabilirsiniz.
  • Veritabanı ve Harici API Optimizasyonları: Veritabanı sorgularınızı optimize edin, harici API çağrılarını önbelleğe alın veya paralel hale getirin.
  • Statik Dosya Sunumu İçin Nginx/CDN Kullanımı: Statik dosyaları doğrudan Node.js sunmak yerine, Nginx gibi bir ters proxy sunucu veya bir İçerik Dağıtım Ağı (CDN) kullanarak sunmak, Node.js sunucunuzun yükünü azaltır ve daha hızlı yanıt süreleri sağlar.
  • Kod Optimizasyonu: Performansı etkileyen “hot path” kod bloklarını optimize edin, gereksiz hesaplamalardan kaçının.

Sunucumda hata oluştuğunda ne yapmalıyım?

Hata yönetimi kritik öneme sahiptir.

  • try-catch blokları: Senkron kodlardaki hataları yakalamak için kullanın.
  • Promises/async-await ile hata yakalama: Asenkron işlemlerde .catch() metodu veya try-catch ile await kullanın.
  • Global Hata Yakalayıcılar: Node.js’in process.on('uncaughtException', ...) ve process.on('unhandledRejection', ...) olaylarını kullanarak yakalanmayan hataları ve reddedilen Promise’ları yakalayın. Bu sayede sunucunuzun aniden çökmesini engelleyebilir ve hataları loglayarak sorun giderme sürecini kolaylaştırabilirsiniz.
  • Hata mesajlarını gizleme: Üretim ortamında, istemcilere ayrıntılı hata mesajları göndermek yerine genel bir hata mesajı (örneğin “Sunucuda bir hata oluştu”) gösterin. Detaylı hata mesajları hassas bilgiler içerebilir.

HTTPS bağlantılarını nasıl kurabilirim?

HTTPS, HTTP modülü yerine Node.js’in https modülü kullanılarak kurulur. Bu modül, sunucunuzu SSL/TLS sertifikaları ile güvenli hale getirmenizi sağlar. Bir HTTPS sunucusu oluşturmak için, bir SSL sertifikasına (.crt veya .pem uzantılı) ve özel anahtarına (.key uzantılı) ihtiyacınız vardır. Bu dosyaları bir sertifika yetkilisinden (CA) alabilir veya geliştirme için kendinden imzalı sertifikalar oluşturabilirsiniz. Daha sonra bu sertifika ve anahtarı https.createServer() metoduna seçenekler olarak ileterek güvenli sunucunuzu başlatabilirsiniz.

Yorumlar
İçeriği beğendiniz mi? Bir tartışma başlatın veya görüşlerinizi paylaşın.
Yorum Yaz

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir

Gönder

E-posta Bülteni
Yazılım Topluluğuna Katılın
En son güncellemeleri, yaratıcı ipuçlarını ve özel kaynakları doğrudan e-posta kutunuza alın. Tasarım ve inovasyonun geleceğini birlikte keşfedelim.
Mobil sürümden çık