C# içinde HttpClient ile HTTP istekleri için proxy yapılandırmak; bir HttpClientHandler örneği oluşturmayı, proxy adresini ve isteğe bağlı kimlik bilgilerini içeren bir WebProxy nesnesini bu handler'ın Proxy özelliğine atamayı ve ardından yapılandırılmış handler'ı HttpClient yapıcısına geçirmeyi kapsar. Bu kurulum, uygulamaların giden web trafiğini bir ara sunucu üzerinden yönlendirmesini sağlar; bu da ağ güvenliği, erişim denetimi, loglama veya coğrafi kısıtlamaların aşılması için gereklidir.
HttpClient, HttpClientHandler ve WebProxy nedir
HttpClient, .NET'te HTTP isteği göndermek ve HTTP yanıtı almak için kullanılan ana sınıftır. Uzun ömürlü örnekler ve eşzamanlı istekler için tasarlanmıştır.
HttpClientHandler, HttpClient'ın istekleri göndermek için kullandığı alttaki message handler'dır. Proxy yapılandırması, kimlik bilgileri ve SSL/TLS ayarları dahil olmak üzere ağ ayarları için yapılandırma seçenekleri sunar.
WebProxy, bir proxy sunucusunun URI'sini belirten ve proxy bypass listeleri ile kimlik bilgilerinin yapılandırılmasına izin veren bir sınıftır.
HttpClient örnek yönetimi
HttpClient örnekleri, soket tükenmesi sorunlarını önlemek için genellikle birden fazla istekte yeniden kullanılmalıdır. Her istek için yeni bir HttpClient oluşturmak performans sorunlarına ve kaynak tükenmesine yol açabilir. Yaygın bir yaklaşım, uygulamanın tüm yaşam döngüsü boyunca tek bir HttpClient örneği kullanmak veya ASP.NET Core uygulamalarında IHttpClientFactory kullanmaktır.
Temel proxy yapılandırması
Temel bir HTTP veya HTTPS proxy'si yapılandırmak için bir HttpClientHandler örneği oluşturun, Proxy özelliğini proxy'nin URI'si ile başlatılmış yeni bir WebProxy nesnesine ayarlayın ve bu handler'ı HttpClient yapıcısına geçirin.
using System;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
public class ProxySetup
{
public static async Task Main(string[] args)
{
string proxyAddress = "http://your.proxy.server:8080"; // Kendi proxy adresinizle değiştirin
string targetUrl = "http://httpbin.org/get"; // Test için genel bir endpoint
// WebProxy örneği oluştur
var webProxy = new WebProxy(proxyAddress, BypassOnLocal: false);
// HttpClientHandler oluştur ve WebProxy'yi ata
var handler = new HttpClientHandler
{
Proxy = webProxy,
UseProxy = true // Proxy kullanımını açıkça etkinleştir
};
// Yapılandırılmış handler ile HttpClient oluştur
using (var httpClient = new HttpClient(handler))
{
try
{
HttpResponseMessage response = await httpClient.GetAsync(targetUrl);
response.EnsureSuccessStatusCode(); // HTTP durum kodu hata ise istisna fırlatır
string responseBody = await response.Content.ReadAsStringAsync();
Console.WriteLine("Request successful. Response snippet:");
Console.WriteLine(responseBody.Substring(0, Math.Min(responseBody.Length, 500))); // İlk 500 karakteri yazdır
}
catch (HttpRequestException e)
{
Console.WriteLine($"Request error: {e.Message}");
}
catch (WebException e)
{
Console.WriteLine($"Proxy or network error: {e.Message}");
}
}
}
}
Bu örnekte:
* WebProxy(proxyAddress, BypassOnLocal: false) bir proxy nesnesi oluşturur. BypassOnLocal: false, yerel adreslere (örneğin localhost) yapılan isteklerin de, sonradan açıkça hariç tutulmadıkça, proxy üzerinden gitmesini sağlar.
* handler.UseProxy = true, handler'a yapılandırılmış proxy'yi kullanmasını açıkça bildirir.
Kimlik doğrulamalı proxy
Proxy sunucusu kimlik doğrulama gerektiriyorsa (örneğin kullanıcı adı ve parola), WebProxy nesnesinin Credentials özelliğini bir NetworkCredential örneğiyle ayarlayın.
using System;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
public class AuthenticatedProxySetup
{
public static async Task Main(string[] args)
{
string proxyAddress = "http://your.authenticated.proxy.server:8080"; // Değiştirin
string proxyUsername = "your_username"; // Değiştirin
string proxyPassword = "your_password"; // Değiştirin
string targetUrl = "http://httpbin.org/get";
var credentials = new NetworkCredential(proxyUsername, proxyPassword);
var webProxy = new WebProxy(proxyAddress, BypassOnLocal: false)
{
Credentials = credentials
};
var handler = new HttpClientHandler
{
Proxy = webProxy,
UseProxy = true
};
using (var httpClient = new HttpClient(handler))
{
try
{
HttpResponseMessage response = await httpClient.GetAsync(targetUrl);
response.EnsureSuccessStatusCode();
string responseBody = await response.Content.ReadAsStringAsync();
Console.WriteLine("Request successful with authenticated proxy.");
Console.WriteLine(responseBody.Substring(0, Math.Min(responseBody.Length, 500)));
}
catch (HttpRequestException e)
{
Console.WriteLine($"Request error: {e.Message}");
}
catch (WebException e)
{
Console.WriteLine($"Proxy or network error: {e.Message}");
}
}
}
}
Sistemin varsayılan proxy'sini kullanma
HttpClientHandler, genellikle işletim sisteminde veya Internet Explorer ayarlarında tanımlanan sistem varsayılan proxy ayarlarını kullanacak şekilde yapılandırılabilir. Bu, kurumsal ortamlarda çoğunlukla istenen davranıştır.
using System;
using System.Net.Http;
using System.Threading.Tasks;
public class SystemDefaultProxySetup
{
public static async Task Main(string[] args)
{
string targetUrl = "http://httpbin.org/get";
var handler = new HttpClientHandler
{
UseSystemProxy = true // Sistemin varsayılan proxy ayarlarını kullan
};
using (var httpClient = new HttpClient(handler))
{
try
{
HttpResponseMessage response = await httpClient.GetAsync(targetUrl);
response.EnsureSuccessStatusCode();
string responseBody = await response.Content.ReadAsStringAsync();
Console.WriteLine("Request successful using system default proxy.");
Console.WriteLine(responseBody.Substring(0, Math.Min(responseBody.Length, 500)));
}
catch (HttpRequestException e)
{
Console.WriteLine($"Request error: {e.Message}");
}
catch (Exception e)
{
Console.WriteLine($"Error: {e.Message}");
}
}
}
}
UseSystemProxy = true ayarı, HttpClientHandler'ı işletim sistemi düzeyinde tanımlanmış proxy ayarlarını bulup kullanacak şekilde otomatik olarak yapılandırır. UseSystemProxy true ise Proxy özelliği yok sayılır.
Belirli adresler için proxy'yi atlama
WebProxy sınıfı, belirli adreslerde proxy'nin atlanması için mekanizmalar sunar.
BypassProxyOnLocal
WebProxy yapıcısında veya özelliğinde BypassProxyOnLocal = true ayarlamak, yerel intranet kaynakları için proxy'nin kullanılmamasını sağlar. Bu, iç trafiğin gereksiz yere harici bir proxy üzerinden yönlendirilmesini önlemek için genellikle tercih edilir.
var webProxy = new WebProxy("http://your.proxy.server:8080")
{
BypassProxyOnLocal = true // Yerel adresler için proxy kullanma
};
BypassList
Daha ayrıntılı denetim için BypassList özelliği, proxy'nin atlanması gereken URI'leri tanımlayan düzenli ifadelerden oluşan bir dizi belirtmenize izin verir.
using System;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
public class ProxyBypassListSetup
{
public static async Task Main(string[] args)
{
string proxyAddress = "http://your.proxy.server:8080";
string targetUrl = "http://internal.api.com/data"; // Örnek dahili URL
string externalUrl = "http://external.api.com/data"; // Örnek harici URL
// Düzenli ifadelerle bypass listesi tanımla
string[] bypassList = new string[]
{
"internal\\.api\\.com", // internal.api.com için bypass
"\\.local$" // .local ile biten tüm hostlar için bypass
};
var webProxy = new WebProxy(proxyAddress)
{
BypassList = bypassList,
BypassProxyOnLocal = false // Gerekirse yerel bypass'ı BypassList üzerinden yönet
};
var handler = new HttpClientHandler
{
Proxy = webProxy,
UseProxy = true
};
using (var httpClient = new HttpClient(handler))
{
Console.WriteLine($"Attempting request to {targetUrl} (should bypass proxy)...");
try
{
HttpResponseMessage response = await httpClient.GetAsync(targetUrl);
response.EnsureSuccessStatusCode();
Console.WriteLine($"Request to {targetUrl} successful. (Check proxy logs if available)");
}
catch (HttpRequestException e)
{
Console.WriteLine($"Request to {targetUrl} error: {e.Message}");
}
Console.WriteLine($"\nAttempting request to {externalUrl} (should use proxy)...");
try
{
HttpResponseMessage response = await httpClient.GetAsync(externalUrl);
response.EnsureSuccessStatusCode();
Console.WriteLine($"Request to {externalUrl} successful. (Check proxy logs if available)");
}
catch (HttpRequestException e)
{
Console.WriteLine($"Request to {externalUrl} error: {e.Message}");
}
}
}
}
HttpClientHandler ile SocketsHttpHandler karşılaştırması
.NET Core 2.1, HttpClient için varsayılan handler olarak SocketsHttpHandler'ı getirdi; bu handler daha iyi performans ve platformlar arası tutarlılık sunar. HttpClientHandler hâlâ mevcuttur ve açıkça kullanılabilir, ancak yeni geliştirmelerde genellikle SocketsHttpHandler tercih edilir. SocketsHttpHandler kullanıldığında proxy yapılandırması biraz farklıdır.
| Özellik | HttpClientHandler |
SocketsHttpHandler (.NET Core/.NET 5+ için önerilir) |
|---|---|---|
| Proxy türü | WebProxy |
IWebProxy (çoğunlukla WebProxy veya özel bir uygulama) |
| Yapılandırma | Proxy özelliğini bir WebProxy örneğiyle ayarlayın. |
Proxy özelliğini bir IWebProxy örneğiyle ayarlayın. |
| Sistem proxy'si | UseSystemProxy = true |
UseProxy = true ve Proxy = WebRequest.DefaultWebProxy ya da sistem varsayılanı için null. |
| Kimlik doğrulama | WebProxy.Credentials |
WebProxy.Credentials (WebProxy kullanılıyorsa) |
| SOCKS proxy | Doğrudan desteklenmez. | Proxy özelliği new WebProxy("socks5://...") olarak ayarlanarak doğrudan SOCKS5 desteği |
| .NET'te varsayılan | .NET Framework'te varsayılan. | .NET Core 2.1+ / .NET 5+ sürümlerinde varsayılan. |
SocketsHttpHandler ile proxy yapılandırma
using System;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
public class SocketsHttpHandlerProxySetup
{
public static async Task Main(string[] args)
{
string proxyAddress = "http://your.proxy.server:8080";
string targetUrl = "http://httpbin.org/get";
var webProxy = new WebProxy(proxyAddress);
// SocketsHttpHandler modern .NET'te varsayılandır, ancak açıkça kullanılabilir
var handler = new SocketsHttpHandler
{
Proxy = webProxy, // IWebProxy örneğini ata
UseProxy = true, // Proxy kullanımını açıkça etkinleştir
AllowAutoRedirect = true, // Diğer SocketsHttpHandler özelliklerine örnek
PooledConnectionLifetime = TimeSpan.FromMinutes(5)
};
using (var httpClient = new HttpClient(handler))
{
try
{
HttpResponseMessage response = await httpClient.GetAsync(targetUrl);
response.EnsureSuccessStatusCode();
string responseBody = await response.Content.ReadAsStringAsync();
Console.WriteLine("Request successful using SocketsHttpHandler.");
Console.WriteLine(responseBody.Substring(0, Math.Min(responseBody.Length, 500)));
}
catch (HttpRequestException e)
{
Console.WriteLine($"Request error: {e.Message}");
}
catch (Exception e)
{
Console.WriteLine($"Error: {e.Message}");
}
}
}
}
SocketsHttpHandler ile sistemin varsayılan proxy'sini kullanmak için UseProxy = true ve Proxy = WebRequest.DefaultWebProxy ayarlayın. Proxy null ve UseProxy true ise SocketsHttpHandler sistemin varsayılan proxy'sini kullanmayı dener.
Hata yönetimi ve hata ayıklama
Proxy yapılandırmasında sorun yaşarsanız şunları değerlendirin:
* Ağ bağlantısı: Uygulamanın çalıştığı sunucunun proxy sunucusuna erişebildiğini doğrulayın.
* Proxy sunucusunun durumu: Proxy sunucusunun çalışır durumda ve doğru yapılandırılmış olduğundan emin olun.
* Kimlik doğrulama: Proxy kimlik bilgilerini tekrar kontrol edin. Hatalı kimlik bilgileri çoğunlukla HTTP 407 Proxy Authentication Required hatasına yol açar.
* Güvenlik duvarı kuralları: Proxy'ye giden veya proxy'den gelen trafiği engelleyebilecek yerel ve ağ güvenlik duvarı kurallarını kontrol edin.
* Proxy logları: Proxy sunucusunun loglarına erişiminiz varsa bağlantı denemelerini ve hataları inceleyin.
* İstisnalar: Ayrıntılı hata mesajları için HttpRequestException ve (.NET Framework'te HttpClientHandler için) WebException istisnalarını yakalayın.
Güvenlik değerlendirmeleri
- Güven: Trafiği yalnızca güvendiğiniz proxy sunucuları üzerinden yönlendirin. Kötü niyetli proxy'ler hassas verileri araya girip okuyabilir, değiştirebilir veya kaydedebilir.
- Kimlik bilgileri: Proxy kimlik bilgilerini güvenli biçimde saklayın, doğrudan kaynak koduna yazmaktan kaçının. Ortam değişkenlerini, yapılandırma dosyalarını veya secret yönetim servislerini kullanın.
- SSL/TLS: Proxy'nin SSL/TLS trafiğini doğru işlediğinden emin olun. Proxy SSL denetimi (Man-in-the-Middle) yapıyorsa uygulamanın ek bir kök sertifika otoritesine güvenmesi gerekebilir.
HttpClientHandler, özel sertifika doğrulaması içinServerCertificateCustomValidationCallbacközelliğine sahiptir, ancak bu özellik dikkatle kullanılmalıdır.
