Deno ve Bun'da Proxy Kullanımı: Geliştirici Rehberi

Deno ve Bun'da fetch ile proxy kullanmanın yollarını, geo-targeting, sticky session, SOCKS5 ve production ipuçlarını kod örnekleriyle öğrenin.

Using Proxies in Deno and Bun: A Code-First Guide for Modern JavaScript

Deno ve Bun'da proxy kullanımı, modern JavaScript runtime'larında web scraping ve API istekleri yaparken karşılaşılan IP engellemelerini aşmanın en pratik yoludur. Node.js'in http.Agent veya https-proxy-agent paketlerine alışkın geliştiriciler, Deno ve Bun'a geçtiklerinde fetch()'in proxy'yi varsayılan olarak yok saydığını fark ederler. Bu rehber, Deno'da Deno.createHttpClient ve Bun'da fetch(url, { proxy }) kullanarak residential proxy'leri nasıl yapılandıracağınızı, geo-targeting ve sticky session'ları nasıl kodlayacağınızı ve production'da karşılaşacağınız tuzakları nasıl aşacağınızı gösterir.

Deno ve Bun'da Proxy Kullanımı: Neden fetch() Proxy'leri Yok Sayar?

Web platformunun fetch() spesifikasyonu (WHATWG Fetch Standard), proxy yapılandırması tanımlamaz. Tarayıcılar proxy'yi işletim sistemi seviyesinde ele alır; JavaScript API'si buna müdahil olmaz. Bu nedenle hem Deno hem de Bun, fetch()'i proxy destekli olacak şekilde genişletir — ama farklı yollardan.

Deno, Deno.createHttpClient ile özel bir HTTP istemcisi oluşturur ve bunu fetch(url, { client }) ile geçirir. Bun ise daha sade bir yaklaşım benimser: fetch(url, { proxy: 'http://...' }) tek satırda proxy'yi devreye alır. Her iki yöntem de HTTP_PROXY ve HTTPS_PROXY ortam değişkenlerini destekler, ancak per-client yapılandırma her zaman ortam değişkenlerine tercih edilmelidir — çünkü aynı process içinde farklı proxy'ler kullanmanız gerekebilir.

Deno'da Deno.createHttpClient ile Proxy Kullanımı

Deno'da proxy kullanmak için önce bir HttpClient oluşturursunuz, ardından bunu fetch'in client seçeneğine geçirirsiniz. Proxy URL'si Basic Auth içerebilir ve basicAuth alanı ile kullanıcı adı/şifre ayrı da belirtilebilir.

// deno-proxy.ts
// Çalıştırma: deno run --allow-net deno-proxy.ts

const PROXY_URL = "http://gate.proxyhat.com:8080";
const PROXY_USER = "user-country-US-session-abc123";
const PROXY_PASS = "your_password";

const client = Deno.createHttpClient({
  proxy: {
    url: PROXY_URL,
    basicAuth: {
      username: PROXY_USER,
      password: PROXY_PASS,
    },
  },
  // Özelleştirilmiş CA sertifikaları (kurumsal proxy veya self-signed TLS)
  caCerts: Deno.readTextFileSync("./custom-ca.pem").split(/-----END CERTIFICATE-----/)
    .filter(c => c.includes("BEGIN CERTIFICATE"))
    .map(c => c + "-----END CERTIFICATE-----"),
});

try {
  const res = await fetch("https://httpbin.org/ip", { client });
  const data = await res.json();
  console.log("Proxy IP:", data.origin);
} catch (err) {
  console.error("İstek başarısız:", err.message);
} finally {
  client.close(); // Kaynak sızıntısını önle
}

Dikkat edin: user-country-US-session-abc123 formatı, ProxyHat'ın kullanıcı adı içinde hem geo-targeting hem de sticky session belirtmenin yoludur. Bu istek bir ABD IP'sinden gelir ve abc123 session ID'si boyunca aynı IP kalır. client.close() çağrısı, Deno 1.38+ sürümlerinde connection pool'u serbest bırakır ve dosya tanımlayıcı sızıntısını önler.

Deno'da SOCKS5 Proxy

SOCKS5 gerektiğinde port 1080 kullanılır:

// deno-socks5.ts
const client = Deno.createHttpClient({
  proxy: {
    url: "socks5://gate.proxyhat.com:1080",
    basicAuth: {
      username: "user-country-DE-city-berlin",
      password: "your_password",
    },
  },
});

const res = await fetch("https://httpbin.org/ip", { client });
console.log(await res.json());
client.close();

Bun'da fetch ile Proxy Kullanımı

Bun, proxy'yi fetch'in ikinci parametresine proxy anahtarı ile alır. Bu, Node.js'te https-proxy-agent kurmadan proxy kullanmanın en temiz yoludur.

// bun-proxy.ts
// Çalıştırma: bun run bun-proxy.ts

const proxyUrl = "http://user-country-DE-session-sess01:pass@gate.proxyhat.com:8080";

try {
  const res = await fetch("https://httpbin.org/ip", {
    proxy: proxyUrl,
  });
  const data = await res.json();
  console.log("Proxy IP:", data.origin);
} catch (err) {
  console.error("İstek başarısız:", err);
}

Bun'da SOCKS5 de aynı şekilde çalışır — sadece URL şemasını ve portu değiştirin:

// bun-socks5.ts
const res = await fetch("https://httpbin.org/ip", {
  proxy: "socks5://user-country-GB-session-sess02:pass@gate.proxyhat.com:1080",
});
console.log(await res.json());

HTTP_PROXY / HTTPS_PROXY Ortam Değişkenleri

Her iki runtime da HTTP_PROXY ve HTTPS_PROXY ortam değişkenlerini tanır. CLI araçları veya CI/CD pipeline'larında bu yöntem pratiktir:

# Terminal
export HTTPS_PROXY="http://user-country-US:pass@gate.proxyhat.com:8080"

# Deno
deno run --allow-net --allow-env script.ts

# Bun
bun run script.ts

Ancak per-client yapılandırma, ortam değişkenlerine göre üç nedenden dolayı tercih edilir:

  • Farklı proxy'ler: Aynı process içinde ABD ve Almanya proxy'si aynı anda kullanılabilir.
  • Güvenlik: Proxy kimlik bilgileri ps çıktısında görünmez.
  • Test edilebilirlik: Proxy URL'si kod içinde açıkça görünür, mock edilebilir.

Residential Proxy'ler Neden Gerekli? Yüksek Engelleme Riski Olan Hedefler

Datacenter IP'leri, Cloudflare ve benzeri anti-bot sistemleri tarafından kolayca tanınır. Residential proxy'ler ise gerçek ISP'lerden gelir ve engelleme oranı önemli ölçüde düşüktür. Örneğin, e-ticaret fiyat izleme veya SERP scraping gibi görevlerde datacenter proxy'lerle başarı oranı %30-50'ye düşebilirken, residential proxy'lerle %90+ başarı oranı mümkündür.

Aşağıdaki örnek, bir sticky session havuzunu eşzamanlı isteklerle döndürür ve her istek için AbortController ile 10 saniyelik timeout belirler:

// rotate-sessions.ts — Deno ve Bun'da çalışır

const GATEWAY = "gate.proxyhat.com:8080";
const PROXY_USER = "your_user";
const PROXY_PASS = "your_pass";
const TARGETS = [
  "https://httpbin.org/ip",
  "https://httpbin.org/headers",
  "https://httpbin.org/user-agent",
  "https://httpbin.org/uuid",
  "https://httpbin.org/delay/2",
];

// Her hedef için benzersiz sticky session ID oluştur
function buildProxyUrl(sessionId: string, country = "US"): string {
  return `http://${PROXY_USER}-country-${country}-session-${sessionId}:${PROXY_PASS}@${GATEWAY}`;
}

async function fetchWithTimeout(
  url: string,
  proxyUrl: string,
  timeoutMs = 10000,
): Promise<{ ok: boolean; status: number; body: string; session: string }> {
  const controller = new AbortController();
  const timer = setTimeout(() => controller.abort(), timeoutMs);

  try {
    // Deno için client oluştur; Bun için proxy option'ı kullan
    const isDeno = typeof Deno !== "undefined" && typeof Deno.createHttpClient === "function";

    let res: Response;
    if (isDeno) {
      const client = Deno.createHttpClient({
        proxy: { url: proxyUrl },
      });
      res = await fetch(url, { client, signal: controller.signal });
      client.close();
    } else {
      res = await fetch(url, { proxy: proxyUrl, signal: controller.signal });
    }

    const body = await res.text();
    return { ok: res.ok, status: res.status, body, session: sessionId };
  } catch (err) {
    if (err.name === "AbortError") {
      return { ok: false, status: 0, body: "TIMEOUT", session: sessionId };
    }
    throw err;
  } finally {
    clearTimeout(timer);
  }
}

// 5 eşzamanlı sticky session ile paralel istek
const sessionIds = Array.from({ length: TARGETS.length }, (_, i) => `sess-${Date.now()}-${i}`);

const results = await Promise.all(
  TARGETS.map((url, i) => fetchWithTimeout(url, buildProxyUrl(sessionIds[i])))
);

for (const r of results) {
  console.log(`[${r.session}] ${r.status} — ${r.ok ? "OK" : "FAIL"} — ${r.body.slice(0, 80)}`);
}

Bu örnekte her istek farklı bir sticky session kullanır, böylece her biri farklı bir residential IP'den gelir. Promise.all ile eşzamanlı çalışır ve AbortController ile 10 saniye sonra takılı kalan istekler iptal edilir. 100 eşzamanlı session'a kadar ölçeklendirilebilir.

Production İpuçları: Retry, Backoff, Connection Reuse

Exponential Backoff ile Retry

// retry.ts — Deno ve Bun uyumlu

async function fetchWithRetry(
  url: string,
  proxyUrl: string,
  maxRetries = 3,
  baseDelayMs = 1000,
): Promise<Response> {
  let lastError: Error | null = null;

  for (let attempt = 0; attempt <= maxRetries; attempt++) {
    try {
      const isDeno = typeof Deno !== "undefined" && typeof Deno.createHttpClient === "function";

      if (isDeno) {
        const client = Deno.createHttpClient({ proxy: { url: proxyUrl } });
        const res = await fetch(url, { client });
        client.close();
        if (res.status === 429 || res.status >= 500) {
          throw new Error(`HTTP ${res.status}`);
        }
        return res;
      } else {
        const res = await fetch(url, { proxy: proxyUrl });
        if (res.status === 429 || res.status >= 500) {
          throw new Error(`HTTP ${res.status}`);
        }
        return res;
      }
    } catch (err) {
      lastError = err;
      if (attempt < maxRetries) {
        const delay = baseDelayMs * Math.pow(2, attempt) + Math.random() * 500;
        console.warn(`Deneme ${attempt + 1} başarısız: ${err.message}. ${Math.round(delay)}ms bekleniyor...`);
        await new Promise(r => setTimeout(r, delay));
      }
    }
  }

  throw lastError;
}

// Kullanım
const res = await fetchWithRetry(
  "https://httpbin.org/get",
  "http://user-country-US-session-abc123:pass@gate.proxyhat.com:8080",
);
console.log(await res.json());

Connection Reuse ve Circuit Breaker

Deno'da Deno.createHttpClient ile oluşturulan client, connection pool'u yeniden kullanır. Aynı session ID ile birden çok istek yapıyorsanız, client'ı kapatmayın — yeniden kullanın. Bun'da ise fetch her çağrıda yeni bir bağlantı kurabilir; connection reuse için Bun.connect veya undici kullanmayı düşünebilirsiniz.

Basit bir circuit breaker pattern'i:

// circuit-breaker.ts
class CircuitBreaker {
  private failures = 0;
  private lastFailureTime = 0;
  private readonly threshold = 5;
  private readonly resetTimeMs = 30000; // 30 saniye

  get isOpen(): boolean {
    return this.failures >= this.threshold &&
      Date.now() - this.lastFailureTime < this.resetTimeMs;
  }

  recordSuccess(): void {
    this.failures = 0;
  }

  recordFailure(): void {
    this.failures++;
    this.lastFailureTime = Date.now();
  }
}

const breaker = new CircuitBreaker();

async function guardedFetch(url: string, proxyUrl: string): Promise<Response> {
  if (breaker.isOpen) {
    throw new Error("Circuit breaker açık — 30 saniye sonra tekrar deneyin");
  }
  try {
    const isDeno = typeof Deno !== "undefined" && typeof Deno.createHttpClient === "function";
    const res = isDeno
      ? await fetch(url, { client: Deno.createHttpClient({ proxy: { url: proxyUrl } }) })
      : await fetch(url, { proxy: proxyUrl });
    breaker.recordSuccess();
    return res;
  } catch (err) {
    breaker.recordFailure();
    throw err;
  }
}

ProxyHat Node SDK ile Yan Yana Karşılaştırma

ProxyHat, hem Deno hem de Bun altında çalışan bir Node SDK'sı sunar. SDK, proxy yönetimini soyutlar ve otomatik rotasyon, retry ve metrik toplama sağlar. Aşağıda raw proxy kullanımı ile SDK kullanımı yan yana:

// proxyhat-sdk.ts — Deno ve Bun'da çalışır (npm: @proxyhat/sdk)
import { ProxyHat } from "@proxyhat/sdk";

const ph = new ProxyHat({
  username: "your_user",
  password: "your_pass",
  gateway: "gate.proxyhat.com",
  port: 8080,
});

// SDK ile otomatik rotasyon ve retry
const result = await ph.get("https://httpbin.org/ip", {
  country: "US",
  sessionId: "abc123",
  retries: 3,
  timeout: 10000,
});

console.log(result.data);
console.log("Kullanılan IP:", result.meta.ip);
console.log("Geçen süre:", result.meta.durationMs + "ms");
Özellik Raw fetch + proxy ProxyHat SDK
Proxy URL yönetimi Manuel string formatlama Otomatik
Retry / backoff Kendi yazmanız gerekir Yerleşik, yapılandırılabilir
Session yönetimi Manuel session ID üretimi Otomatik sticky session
Metrik toplama Yok Süre, IP, status kodu
SOCKS5 desteği Port 1080 ile manuel Otomatik
CA sertifika yapılandırması Deno'da caCerts, Bun'da yok SDK seviyesinde

SDK, ProxyHat dokümantasyonunda ayrıntılı açıklanmıştır. Raw proxy kullanımı daha fazla kontrol sağlar, ancak SDK boilerplate'i azaltır ve production'da daha az hata yapmanızı sağlar. ProxyHat fiyatlandırması sayfasından residential, mobile ve datacenter planları karşılaştırılabilir.

EtiK Scraping: Yasal ve Etik Hususlar

Proxy kullanımı güçlü bir araçtır, ancak sorumlu kullanılmalıdır. İşte temel ilkeler:

  • Önce resmi API'yi kontrol edin: Bir hedefin API'si varsa, scraping yerine onu kullanın. Daha hızlı, daha güvenilir ve yasal olarak daha güvenlidir.
  • robots.txt'ye saygı gösterin: /robots.txt dosyası, hangi yolların taranmaması gerektiğini belirtir. Bu kurallara uymak etik bir gerekliliktir.
  • Rate limit'e uyun: Saniyede 1-2 istek gibi makul bir hız tutun. Hedef sunucuyu DDoS etmeyin.
  • ABD'de CFAA: Computer Fraud and Abuse Act, yetkisiz erişimi suç sayar. Public veri toplamak genellikle sorun değil, ancak ToS ihlali dava riski taşıyabilir.
  • AB'de GDPR: Kişisel veri içeren içerik topluyorsanız, GDPR uyumluluğu gerekir. IP adresleri bile kişisel veri sayılır.
  • Sadece public veri: Login arkasındaki verileri scraping yapmayın; bu ToS ihlali olabilir.

Daha fazla bilgi için web scraping kullanım senaryosu ve SERP takibi sayfalarımıza bakabilirsiniz. ProxyHat'ın lokasyon sayfası üzerinden 190+ ülkedeki residential IP havuzunu inceleyebilirsiniz.

Key Takeaways

  • Deno'da proxy: Deno.createHttpClient({ proxy: { url, basicAuth } }) ile client oluştur, fetch(url, { client }) ile geçir. İşin bitince client.close() çağır.
  • Bun'da proxy: fetch(url, { proxy: 'http://user:pass@gate.proxyhat.com:8080' }) tek satır yeterli.
  • Geo-targeting + sticky session: Kullanıcı adında user-country-US-session-abc123 formatını kullan. SOCKS5 için port 1080.
  • Ortam değişkenleri: HTTP_PROXY/HTTPS_PROXY çalışır, ama per-client config daha esnek ve güvenli.
  • Residential proxy: Yüksek engelleme riski olan hedefler için datacenter yerine residential kullan. Başarı oranı %90+ olabilir.
  • Production: Exponential backoff ile retry, AbortController ile timeout, circuit breaker ile koruma. Deno'da caCerts ile özel CA.
  • EtiK: Önce API, robots.txt'ye saygı, CFAA ve GDPR'ye dikkat, sadece public veri.

SSS

Deno ve Bun'da proxy kullanımı nedir?

Deno ve Bun'da proxy kullanımı, bu modern JavaScript runtime'larında fetch veya HTTP istemcisi üzerinden proxy sunucusuna bağlanarak IP rotasyonu, geo-targeting ve sticky session gibi özellikleri kullanmaktır. Deno bunu Deno.createHttpClient ile, Bun ise fetch options içine proxy parametresi ekleyerek sağlar.

Deno ve Bun'da proxy kullanımı neden önemlidir?

Web scraping, SERP takibi ve fiyat izleme gibi görevlerde tek bir IP hızlıca engellenir. Proxy kullanımı, istekleri farklı IP'lerden dağıtarak block riskini azaltır, geo-targeting ile bölgesel içeriklere erişim sağlar ve rate limitlerini aşmanıza yardımcı olur. Deno ve Bun gibi modern runtime'larda proxy desteği native API'lerle gelir.

Deno ve Bun'da proxy kullanımı için en iyi proxy tipi nedir?

Yüksek engelleme riski olan hedefler için residential proxy en iyi seçenektir, çünkü gerçek ISP IP'lerinden gelir ve datacenter proxy'lere göre daha az engellenir. Düşük latency gerektiren durumlarda datacenter proxy tercih edilebilir. Mobil proxy ise en yüksek güvenilirliği sunar ancak maliyeti daha yüksektir.

Deno ve Bun'da proxy kullanırken blokları nasıl önlersiniz?

Sticky session ile IP rotasyonu yapın, geo-targeting kullanın, rate limit'e uyun, uygun User-Agent ve header'lar gönderin, retries ile backoff uygulayın ve AbortController ile timeout belirleyin. Ayrıca robots.txt kurallarına saygı gösterin ve mümkünse resmi API'leri tercih edin.

Başlamaya hazır mısınız?

148+ ülkede 50M+ konut IP'sine AI destekli filtreleme ile erişin.

Fiyatlandırmayı GörüntüleKonut Proxy'leri
← Bloga Dön