Průvodce migrací HttpWebRequest na HttpClient
Cílem tohoto článku je vést vývojáře procesem migrace z HttpWebRequest, ServicePointa ServicePointManager do HttpClient. Migrace je nezbytná kvůli zastaralosti starších rozhraní API a mnoha výhod, které HttpClientnabízí , včetně lepšího výkonu, lepší správy prostředků a modernějšího a flexibilnějšího návrhu rozhraní API. Podle kroků popsaných v tomto dokumentu budou vývojáři moci hladce převést své základy kódu a plně využít výhod funkcí poskytovaných HttpClient.
Upozorňující
Migrace z HttpWebRequest
, ServicePoint
a ServicePointManager
do HttpClient
není jen "pěkné mít" zlepšení výkonu. Je důležité si uvědomit, že výkon stávající WebRequest
logiky se při přechodu na .NET (Core) pravděpodobně výrazně sníží. Je to proto WebRequest
, že se udržuje jako minimální vrstva kompatibility, což znamená, že nemá mnoho optimalizací, jako je opakované použití připojení v mnoha případech. Přechod na HttpClient
je proto nezbytný k zajištění výkonu a správy prostředků vaší aplikace až do moderních standardů.
Migrace z HttpWebRequest do HttpClient
Začněme několika příklady:
Jednoduchý požadavek GET s využitím HttpWebRequest
Tady je příklad, jak může kód vypadat:
HttpWebRequest request = WebRequest.CreateHttp(uri);
using WebResponse response = await request.GetResponseAsync();
Jednoduchý požadavek GET s využitím HttpClient
Tady je příklad, jak může kód vypadat:
HttpClient client = new();
using HttpResponseMessage message = await client.GetAsync(uri);
Jednoduchý požadavek POST s využitím HttpWebRequest
Tady je příklad, jak může kód vypadat:
HttpWebRequest request = WebRequest.CreateHttp(uri);
request.Method = "POST";
request.ContentType = "text/plain";
await using Stream stream = await request.GetRequestStreamAsync();
await stream.WriteAsync("Hello World!"u8.ToArray());
using WebResponse response = await request.GetResponseAsync();
Jednoduchý požadavek POST s využitím HttpClient
Tady je příklad, jak může kód vypadat:
HttpClient client = new();
using HttpResponseMessage responseMessage = await client.PostAsync(uri, new StringContent("Hello World!"));
Průvodce migrací HttpWebRequest na HttpClient, SocketsHttpHandler
HttpWebRequest Staré rozhraní API | Nové rozhraní API | Notes |
---|---|---|
Accept |
Accept | Příklad: Nastavte hlavičky požadavku. |
Address |
RequestUri | Příklad: Načíst přesměrovaný identifikátor URI. |
AllowAutoRedirect |
AllowAutoRedirect | Příklad: Nastavení vlastností SocketsHttpHandler |
AllowReadStreamBuffering |
Žádné přímé ekvivalentní rozhraní API | Použití vlastností ukládání do vyrovnávací paměti |
AllowWriteStreamBuffering |
Žádné přímé ekvivalentní rozhraní API | Použití vlastností ukládání do vyrovnávací paměti |
AuthenticationLevel |
Žádné přímé ekvivalentní rozhraní API | Příklad: Povolení vzájemného ověřování |
AutomaticDecompression |
AutomaticDecompression | Příklad: Nastavení vlastností SocketsHttpHandler |
CachePolicy |
Žádné přímé ekvivalentní rozhraní API | Příklad: Použít hlavičky CachePolicy. |
ClientCertificates |
SslOptions.ClientCertificates | Použití vlastností souvisejících s certifikáty v HttpClient |
Connection |
Connection | Příklad: Nastavte hlavičky požadavku. |
ConnectionGroupName |
Žádné ekvivalentní rozhraní API | Žádné alternativní řešení |
ContentLength |
ContentLength | Příklad: Nastavení záhlaví obsahu |
ContentType |
ContentType | Příklad: Nastavení záhlaví obsahu |
ContinueDelegate |
Žádné ekvivalentní rozhraní API | Alternativní řešení neexistuje. |
ContinueTimeout |
Expect100ContinueTimeout | Příklad: Nastavte vlastnosti SocketsHttpHandler. |
CookieContainer |
CookieContainer | Příklad: Nastavte vlastnosti SocketsHttpHandler. |
Credentials |
Credentials | Příklad: Nastavte vlastnosti SocketsHttpHandler. |
Date |
Date | Příklad: Nastavte hlavičky požadavku. |
DefaultCachePolicy |
Žádné přímé ekvivalentní rozhraní API | Příklad: Použít hlavičky CachePolicy. |
DefaultMaximumErrorResponseLength |
Žádné přímé ekvivalentní rozhraní API | Příklad: Nastavení MaximumErrorResponseLength v HttpClient. |
DefaultMaximumResponseHeadersLength |
Žádné ekvivalentní rozhraní API | MaxResponseHeadersLength místo toho lze použít. |
DefaultWebProxy |
Žádné ekvivalentní rozhraní API | Proxy místo toho lze použít. |
Expect |
Expect | Příklad: Nastavte hlavičky požadavku. |
HaveResponse |
Žádné ekvivalentní rozhraní API | Implikuje se tím, HttpResponseMessage že má instanci. |
Headers |
Headers | Příklad: Nastavte hlavičky požadavku. |
Host |
Host | Příklad: Nastavte hlavičky požadavku. |
IfModifiedSince |
IfModifiedSince | Příklad: Nastavte hlavičky požadavku. |
ImpersonationLevel |
Žádné přímé ekvivalentní rozhraní API | Příklad: Změna zosobněníLevel. |
KeepAlive |
Žádné přímé ekvivalentní rozhraní API | Příklad: Nastavte hlavičky požadavku. |
MaximumAutomaticRedirections |
MaxAutomaticRedirections | Příklad: Nastavení vlastností SocketsHttpHandler |
MaximumResponseHeadersLength |
MaxResponseHeadersLength | Příklad: Nastavení vlastností SocketsHttpHandler |
MediaType |
Žádné přímé ekvivalentní rozhraní API | Příklad: Nastavení záhlaví obsahu |
Method |
Method | Příklad: Použití vlastností HttpRequestMessage. |
Pipelined |
Žádné ekvivalentní rozhraní API | HttpClient nepodporuje pipelining. |
PreAuthenticate |
PreAuthenticate | |
ProtocolVersion |
HttpRequestMessage.Version |
Příklad: Použití vlastností HttpRequestMessage. |
Proxy |
Proxy | Příklad: Nastavení vlastností SocketsHttpHandler |
ReadWriteTimeout |
Žádné přímé ekvivalentní rozhraní API | Použití SocketsHttpHandler a ConnectCallback. |
Referer |
Referrer | Příklad: Nastavte hlavičky požadavku. |
RequestUri |
RequestUri | Příklad: Použití vlastností HttpRequestMessage. |
SendChunked |
TransferEncodingChunked | Příklad: Nastavte hlavičky požadavku. |
ServerCertificateValidationCallback |
SslOptions.RemoteCertificateValidationCallback | Příklad: Nastavení vlastností SocketsHttpHandler |
ServicePoint |
Žádné ekvivalentní rozhraní API | ServicePoint není součástí HttpClient . |
SupportsCookieContainer |
Žádné ekvivalentní rozhraní API | To je vždy true pro HttpClient . |
Timeout |
Timeout | |
TransferEncoding |
TransferEncoding | Příklad: Nastavte hlavičky požadavku. |
UnsafeAuthenticatedConnectionSharing |
Žádné ekvivalentní rozhraní API | Žádné alternativní řešení |
UseDefaultCredentials |
Žádné přímé ekvivalentní rozhraní API | Příklad: Nastavení vlastností SocketsHttpHandler |
UserAgent |
UserAgent | Příklad: Nastavte hlavičky požadavku. |
Migrace využití ServicePoint(Manager)
Měli byste vědět, že ServicePointManager
je statická třída, což znamená, že všechny změny provedené ve svých vlastnostech budou mít globální vliv na všechny nově vytvořené ServicePoint
objekty v aplikaci. Když například upravíte vlastnost jako ConnectionLimit
nebo Expect100Continue
, bude mít vliv na každou novou instanci ServicePointu.
Upozorňující
V moderním rozhraní .NET HttpClient
nebere v úvahu žádné konfigurace nastavené na ServicePointManager
.
ServicePointManager mapování vlastností
ServicePointManager Staré rozhraní API | Nové rozhraní API | Notes |
---|---|---|
CheckCertificateRevocationList |
SslOptions.CertificateRevocationCheckMode | Příklad: Povolení kontroly seznamu CRL pomocí SocketsHttpHandler |
DefaultConnectionLimit |
MaxConnectionsPerServer | Příklad: Nastavení vlastností SocketsHttpHandler |
DnsRefreshTimeout |
Žádné ekvivalentní rozhraní API | Příklad: Povolení kruhového dotazování Dns |
EnableDnsRoundRobin |
Žádné ekvivalentní rozhraní API | Příklad: Povolení kruhového dotazování Dns |
EncryptionPolicy |
SslOptions.EncryptionPolicy | Příklad: Nastavení vlastností SocketsHttpHandler |
Expect100Continue |
ExpectContinue | Příklad: Nastavte hlavičky požadavku. |
MaxServicePointIdleTime |
PooledConnectionIdleTimeout | Příklad: Nastavení vlastností SocketsHttpHandler |
MaxServicePoints |
Žádné ekvivalentní rozhraní API | ServicePoint není součástí HttpClient . |
ReusePort |
Žádné přímé ekvivalentní rozhraní API | Použití SocketsHttpHandler a ConnectCallback. |
SecurityProtocol |
SslOptions.EnabledSslProtocols | Příklad: Nastavení vlastností SocketsHttpHandler |
ServerCertificateValidationCallback |
SslOptions.RemoteCertificateValidationCallback | Oba jsou RemoteCertificateValidationCallback |
UseNagleAlgorithm |
Žádné přímé ekvivalentní rozhraní API | Použití SocketsHttpHandler a ConnectCallback. |
Upozorňující
V moderním .NET jsou výchozí hodnoty pro UseNagleAlgorithm
vlastnosti a Expect100Continue
vlastnosti nastaveny na false
. Tyto hodnoty byly true
ve výchozím nastavení v rozhraní .NET Framework.
ServicePointManager mapování metod
ServicePointManager Staré rozhraní API | Nové rozhraní API | Notes |
---|---|---|
FindServicePoint |
Žádné ekvivalentní rozhraní API | Žádné alternativní řešení |
SetTcpKeepAlive |
Žádné přímé ekvivalentní rozhraní API | Použití SocketsHttpHandler a ConnectCallback. |
ServicePoint mapování vlastností
ServicePoint Staré rozhraní API | Nové rozhraní API | Notes |
---|---|---|
Address |
HttpRequestMessage.RequestUri |
Toto je identifikátor URI požadavku, tyto informace najdete v části HttpRequestMessage . |
BindIPEndPointDelegate |
Žádné přímé ekvivalentní rozhraní API | Použití SocketsHttpHandler a ConnectCallback. |
Certificate |
Žádné přímé ekvivalentní rozhraní API | Tyto informace lze načíst z RemoteCertificateValidationCallback . Příklad: Načtení certifikátu |
ClientCertificate |
Žádné ekvivalentní rozhraní API | Příklad: Povolení vzájemného ověřování |
ConnectionLeaseTimeout |
SocketsHttpHandler.PooledConnectionLifetime |
Ekvivalentní nastavení v HttpClient |
ConnectionLimit |
MaxConnectionsPerServer | Příklad: Nastavení vlastností SocketsHttpHandler |
ConnectionName |
Žádné ekvivalentní rozhraní API | Žádné alternativní řešení |
CurrentConnections |
Žádné ekvivalentní rozhraní API | Viz Telemetrie sítí v .NET. |
Expect100Continue |
ExpectContinue | Příklad: Nastavte hlavičky požadavku. |
IdleSince |
Žádné ekvivalentní rozhraní API | Žádné alternativní řešení |
MaxIdleTime |
PooledConnectionIdleTimeout | Příklad: Nastavení vlastností SocketsHttpHandler |
ProtocolVersion |
HttpRequestMessage.Version |
Příklad: Použití vlastností HttpRequestMessage. |
ReceiveBufferSize |
Žádné přímé ekvivalentní rozhraní API | Použití SocketsHttpHandler a ConnectCallback. |
SupportsPipelining |
Žádné ekvivalentní rozhraní API | HttpClient nepodporuje pipelining. |
UseNagleAlgorithm |
Žádné přímé ekvivalentní rozhraní API | Použití SocketsHttpHandler a ConnectCallback. |
ServicePoint mapování metod
ServicePoint Staré rozhraní API | Nové rozhraní API | Notes |
---|---|---|
CloseConnectionGroup |
Žádný ekvivalent | Žádné alternativní řešení |
SetTcpKeepAlive |
Žádné přímé ekvivalentní rozhraní API | Použití SocketsHttpHandler a ConnectCallback. |
Použití vlastností HttpClient a HttpRequestMessage
Při práci s HttpClient v .NET máte přístup k nejrůznějším vlastnostem, které umožňují konfigurovat a přizpůsobovat požadavky a odpovědi HTTP. Porozumění těmto vlastnostem vám může pomoct maximálně využít HttpClient a zajistit efektivní a bezpečnou komunikaci vaší aplikace s webovými službami.
Příklad: Použití vlastností HttpRequestMessage
Tady je příklad, jak společně používat HttpClient a HttpRequestMessage:
var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Post, "https://example.com"); // Method and RequestUri usage
var request = new HttpRequestMessage() // Alternative way to set RequestUri and Method
{
RequestUri = new Uri("https://example.com"),
Method = HttpMethod.Post
};
request.Headers.Add("Custom-Header", "value");
request.Content = new StringContent("somestring");
using var response = await client.SendAsync(request);
var protocolVersion = response.RequestMessage.Version; // Fetch `ProtocolVersion`.
Příklad: Fetch redirected URI
Tady je příklad, jak načíst přesměrovaný identifikátor URI (stejný jako HttpWebRequest.Address
):
var client = new HttpClient();
using var response = await client.GetAsync(uri);
var redirectedUri = response.RequestMessage.RequestUri;
Použití SocketsHttpHandler a ConnectCallback
Tato ConnectCallback
vlastnost SocketsHttpHandler
umožňuje vývojářům přizpůsobit proces vytvoření připojení TCP. To může být užitečné pro scénáře, kdy potřebujete řídit překlad DNS nebo použít konkrétní možnosti soketu na připojení. Pomocí ConnectCallback
, můžete zachytit a upravit proces připojení před jeho použitím HttpClient
.
Příklad: Vytvoření vazby IP adresy k soketu
Ve starém přístupu, který používáte HttpWebRequest
, jste možná použili vlastní logiku k vytvoření vazby konkrétní IP adresy na soket. Tady je postup, jak dosáhnout podobných funkcí pomocí HttpClient
a ConnectCallback
:
Starý kód používající HttpWebRequest
:
HttpWebRequest request = WebRequest.CreateHttp(uri);
request.ServicePoint.BindIPEndPointDelegate = (servicePoint, remoteEndPoint, retryCount) =>
{
// Bind to a specific IP address
IPAddress localAddress = IPAddress.Parse("192.168.1.100");
return new IPEndPoint(localAddress, 0);
};
using HttpWebResponse response = (HttpWebResponse)request.GetResponse();
Nový kód používající HttpClient
a ConnectCallback
:
var handler = new SocketsHttpHandler
{
ConnectCallback = async (context, cancellationToken) =>
{
// Bind to a specific IP address
IPAddress localAddress = IPAddress.Parse("192.168.1.100");
var socket = new Socket(localAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
try
{
socket.Bind(new IPEndPoint(localAddress, 0));
await socket.ConnectAsync(context.DnsEndPoint, cancellationToken);
return new NetworkStream(socket, ownsSocket: true);
}
catch
{
socket.Dispose();
throw;
}
}
};
var client = new HttpClient(handler);
using var response = await client.GetAsync(uri);
Příklad: Použití konkrétních možností soketů
Pokud potřebujete použít specifické možnosti soketu, jako je povolení udržování protokolu TCP, můžete použít ConnectCallback
ke konfiguraci soketu před jeho použitím HttpClient
. Ve skutečnosti ConnectCallback
je flexibilnější konfigurace možností soketů.
Starý kód používající HttpWebRequest
:
ServicePointManager.ReusePort = true;
HttpWebRequest request = WebRequest.CreateHttp(uri);
request.ServicePoint.SetTcpKeepAlive(true, 60000, 1000);
request.ServicePoint.ReceiveBufferSize = 8192;
request.ServicePoint.UseNagleAlgorithm = false;
using HttpWebResponse response = (HttpWebResponse)request.GetResponse();
Nový kód používající HttpClient
a ConnectCallback
:
var handler = new SocketsHttpHandler
{
ConnectCallback = async (context, cancellationToken) =>
{
var socket = new Socket(SocketType.Stream, ProtocolType.Tcp);
try
{
// Setting TCP Keep Alive
socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.KeepAlive, true);
socket.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.TcpKeepAliveTime, 60);
socket.SetSocketOption(SocketOptionLevel.Tcp, SocketOptionName.TcpKeepAliveInterval, 1);
// Setting ReceiveBufferSize
socket.ReceiveBufferSize = 8192;
// Enabling ReusePort
socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseUnicastPort, true);
// Disabling Nagle Algorithm
socket.NoDelay = true;
await socket.ConnectAsync(context.DnsEndPoint, cancellationToken);
return new NetworkStream(socket, ownsSocket: true);
}
catch
{
socket.Dispose();
throw;
}
}
};
var client = new HttpClient(handler);
using var response = await client.GetAsync(uri);
Příklad: Povolení kruhového dotazování DNS
Kruhové dotazování DNS je technika, která se používá k distribuci síťového provozu mezi více serverů otočením seznamu IP adres přidružených k jednomu názvu domény. To pomáhá při vyrovnávání zatížení a zlepšení dostupnosti služeb. Pokud používáte HttpClient, můžete implementovat DNS Round Robin ručním zpracováním překladu DNS a rotací přes IP adresy pomocí ConnectCallback vlastnost SocketsHttpHandler.
Chcete-li povolit dns Round Robin s HttpClient, můžete použít ConnectCallback vlastnost ručně přeložit záznamy DNS a otočit přes IP adresy. Tady je příklad:HttpWebRequest
HttpClient
Starý kód používající HttpWebRequest
:
ServicePointManager.DnsRefreshTimeout = 60000;
ServicePointManager.EnableDnsRoundRobin = true;
HttpWebRequest request = WebRequest.CreateHttp(uri);
using HttpWebResponse response = (HttpWebResponse)request.GetResponse();
Ve starším HttpWebRequest
rozhraní API bylo povolení kruhového dotazování DNS jednoduché kvůli integrované podpoře této funkce. Novější HttpClient
rozhraní API ale neposkytuje stejné integrované funkce. Navzdory tomu můžete dosáhnout podobného chování implementací DnsRoundRobinConnector
, která se ručně otočí přes IP adresy vrácené překladem DNS.
Nový kód pomocí HttpClient
:
// This is available as NuGet Package: https://www.nuget.org/packages/DnsRoundRobin/
// The original source code can be found also here: https://github.com/MihaZupan/DnsRoundRobin
public sealed class DnsRoundRobinConnector : IDisposable
Implementace najdete DnsRoundRobinConnector
tady.
DnsRoundRobinConnector
Zvyk:
private static readonly DnsRoundRobinConnector s_roundRobinConnector = new(
dnsRefreshInterval: TimeSpan.FromSeconds(10),
endpointConnectTimeout: TimeSpan.FromSeconds(5));
static async Task DnsRoundRobinConnectAsync()
{
var handler = new SocketsHttpHandler
{
ConnectCallback = async (context, cancellation) =>
{
Socket socket = await DnsRoundRobinConnector.Shared.ConnectAsync(context.DnsEndPoint, cancellation);
// Or you can create and use your custom DnsRoundRobinConnector instance
// Socket socket = await s_roundRobinConnector.ConnectAsync(context.DnsEndPoint, cancellation);
return new NetworkStream(socket, ownsSocket: true);
}
};
var client = new HttpClient(handler);
HttpResponseMessage response = await client.GetAsync(Uri);
}
Příklad: Nastavení vlastností SocketsHttpHandler
SocketsHttpHandler je výkonná a flexibilní obslužná rutina v .NET, která poskytuje pokročilé možnosti konfigurace pro správu připojení HTTP. Nastavením různých vlastností SocketsHttpHandler můžete doladit chování klienta HTTP tak, aby splňovalo konkrétní požadavky, jako je optimalizace výkonu, vylepšení zabezpečení a vlastní zpracování připojení.
Tady je příklad konfigurace SocketsHttpHandler s různými vlastnostmi a jeho použití s HttpClient:
var cookieContainer = new CookieContainer();
cookieContainer.Add(new Cookie("cookieName", "cookieValue"));
var handler = new SocketsHttpHandler
{
AllowAutoRedirect = true,
AutomaticDecompression = DecompressionMethods.All,
Expect100ContinueTimeout = TimeSpan.FromSeconds(1),
CookieContainer = cookieContainer,
Credentials = new NetworkCredential("user", "pass"),
MaxAutomaticRedirections = 10,
MaxResponseHeadersLength = 1,
Proxy = new WebProxy("http://proxyserver:8080"), // Don't forget to set UseProxy
UseProxy = true,
};
var client = new HttpClient(handler);
using var response = await client.GetAsync(uri);
Příklad: Změna zosobněníLevel
Tato funkce je specifická pro určité platformy a je poněkud zastaralá. Pokud potřebujete alternativní řešení, můžete se podívat na tuto část kódu.
Použití vlastností souvisejících s certifikátem a TLS v HttpClient
Při práci s klienty HttpClient
může být potřeba zpracovávat klientské certifikáty pro různé účely, například vlastní ověření certifikátů serveru nebo načtení certifikátu serveru. HttpClient
poskytuje několik vlastností a možností efektivní správy certifikátů.
Příklad: Kontrola seznamu odvolaných certifikátů pomocí SocketsHttpHandler
Tato CheckCertificateRevocationList
vlastnost SocketsHttpHandler.SslOptions
umožňuje vývojářům povolit nebo zakázat kontrolu seznamů odvolaných certifikátů (CRL) během metody handshake protokolu SSL/TLS. Povolením této vlastnosti zajistíte, že klient ověří, jestli byl certifikát serveru odvolán, což zvyšuje zabezpečení připojení.
Starý kód používající HttpWebRequest
:
ServicePointManager.CheckCertificateRevocationList = true;
HttpWebRequest request = WebRequest.CreateHttp(uri);
using HttpWebResponse response = (HttpWebResponse)request.GetResponse();
Nový kód pomocí HttpClient
:
bool checkCertificateRevocationList = true;
var handler = new SocketsHttpHandler
{
SslOptions =
{
CertificateRevocationCheckMode = checkCertificateRevocationList ? X509RevocationMode.Online : X509RevocationMode.NoCheck,
}
};
var client = new HttpClient(handler);
using var response = await client.GetAsync(uri);
Příklad: Načtení certifikátu
Chcete-li načíst certifikát z objektu RemoteCertificateValidationCallback
HttpClient
in , můžete použít ServerCertificateCustomValidationCallback
vlastnost HttpClientHandler
nebo SocketsHttpHandler.SslOptions
. Toto zpětné volání umožňuje zkontrolovat certifikát serveru během metody handshake PROTOKOLU SSL/TLS.
Starý kód používající HttpWebRequest
:
HttpWebRequest request = WebRequest.CreateHttp(uri);
using HttpWebResponse response = (HttpWebResponse)request.GetResponse();
X509Certificate? serverCertificate = request.ServicePoint.Certificate;
Nový kód pomocí HttpClient
:
X509Certificate? serverCertificate = null;
var handler = new SocketsHttpHandler
{
SslOptions = new SslClientAuthenticationOptions
{
RemoteCertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) =>
{
serverCertificate = certificate;
// Leave the validation as-is.
return sslPolicyErrors == SslPolicyErrors.None;
}
}
};
var client = new HttpClient(handler);
using var response = await client.GetAsync("https://example.com");
Příklad: Povolení vzájemného ověřování
Vzájemné ověřování, označované také jako obousměrné ověřování SSL nebo klientského certifikátu, je proces zabezpečení, ve kterém se klient i server vzájemně ověřují. Tím zajistíte, že obě strany budou tím, kdo tvrdí, že jsou, a poskytují další vrstvu zabezpečení pro citlivou komunikaci. V HttpClient
systému můžete povolit vzájemné ověřování tak HttpClientHandler
, že nakonfigurujete nebo SocketsHttpHandler
zahrnete klientský certifikát a ověříte certifikát serveru.
Chcete-li povolit vzájemné ověřování, postupujte takto:
- Načtěte klientský certifikát.
- Nakonfigurujte HttpClientHandler nebo SocketsHttpHandler tak, aby zahrnoval klientský certifikát.
- Pokud je potřeba vlastní ověření, nastavte zpětné volání ověření certifikátu serveru.
Tady je příklad použití SocketsHttpHandler:
var handler = new SocketsHttpHandler
{
SslOptions = new SslClientAuthenticationOptions
{
ClientCertificates = new X509CertificateCollection
{
// Load the client certificate from a file
new X509Certificate2("path_to_certificate.pfx", "certificate_password")
},
RemoteCertificateValidationCallback = (sender, certificate, chain, sslPolicyErrors) =>
{
// Custom validation logic for the server certificate
return sslPolicyErrors == SslPolicyErrors.None;
}
}
};
var client = new HttpClient(handler);
using var response = await client.GetAsync(uri);
Použití vlastností záhlaví
Hlavičky hrají zásadní roli při komunikaci HTTP a poskytují základní metadata o požadavku a odpovědi. Při práci s rozhraním HttpClient
.NET můžete nastavit a spravovat různé vlastnosti hlaviček, abyste mohli řídit chování požadavků a odpovědí HTTP. Když pochopíte, jak efektivně používat tyto vlastnosti hlaviček, pomůže vám to zajistit efektivní a bezpečnou komunikaci vaší aplikace s webovými službami.
Nastavení hlaviček požadavků
Hlavičky požadavku slouží k poskytnutí dalších informací serveru o provedené žádosti. Mezi běžné případy použití patří určení typu obsahu, nastavení ověřovacích tokenů a přidání vlastních hlaviček. Hlavičky požadavku můžete nastavit pomocí DefaultRequestHeaders
vlastnosti HttpClient
nebo vlastnosti Headers objektu HttpRequestMessage
.
Příklad: Nastavení hlaviček vlastních požadavků
Nastavení výchozích hlaviček vlastních požadavků v HttpClient
var client = new HttpClient();
client.DefaultRequestHeaders.Add("Custom-Header", "value");
Nastavení hlaviček vlastních požadavků v HttpRequestMessage
var request = new HttpRequestMessage(HttpMethod.Get, uri);
request.Headers.Add("Custom-Header", "value");
Příklad: Nastavení běžných hlaviček požadavků
Při práci s rozhraním HttpRequestMessage
.NET je nastavení běžných hlaviček požadavků nezbytné pro poskytnutí dalších informací serveru o provedené žádosti. Tyto hlavičky můžou zahrnovat ověřovací tokeny a další. Správná konfigurace těchto hlaviček zajistí, že server správně zpracuje vaše požadavky HTTP.
Úplný seznam běžných vlastností dostupných v HttpRequestHeadersčásti Vlastnosti.
Chcete-li nastavit běžné hlavičky požadavku v HttpRequestMessage
, můžete použít Headers
vlastnost objektu HttpRequestMessage
. Tato vlastnost poskytuje přístup k kolekci HttpRequestHeaders
, kde můžete podle potřeby přidávat nebo upravovat záhlaví.
Nastavení běžných výchozích hlaviček požadavků v HttpClient
using System.Net.Http.Headers;
var client = new HttpClient();
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", "token");
Nastavení běžných hlaviček požadavků v HttpRequestMessage
using System.Net.Http.Headers;
var request = new HttpRequestMessage(HttpMethod.Get, uri);
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", "token");
Příklad: Nastavení záhlaví obsahu
Hlavičky obsahu slouží k poskytnutí dalších informací o textu požadavku nebo odpovědi HTTP. Při práci s rozhraním HttpClient
.NET můžete nastavit hlavičky obsahu tak, aby určily typ média, kódování a další metadata související s odesílaným nebo přijatým obsahem. Správná konfigurace hlaviček obsahu zajišťuje, aby server a klient mohli obsah správně interpretovat a zpracovávat.
var client = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Post, uri);
// Create the content and set the content headers
var jsonData = "{\"key\":\"value\"}";
var content = new StringContent(jsonData, Encoding.UTF8, "application/json");
// The following headers are set automatically by `StringContent`. If you wish to override their values, you can do it like so:
// content.Headers.ContentType = new MediaTypeHeaderValue("application/json; charset=utf-8");
// content.Headers.ContentLength = Encoding.UTF8.GetByteCount(jsonData);
// Assign the content to the request
request.Content = content;
using var response = await client.SendAsync(request);
Příklad: Nastavení MaximumErrorResponseLength v HttpClient
Použití MaximumErrorResponseLength
umožňuje vývojářům určit maximální délku obsahu odpovědi na chybu, který obslužná rutina uloží do vyrovnávací paměti. To je užitečné pro řízení množství dat, která se čtou a ukládají v paměti, když se ze serveru obdrží chybová odpověď. Pomocí této techniky můžete zabránit nadměrnému využití paměti a zlepšit výkon aplikace při zpracování velkých chybových odpovědí.
Existuje několik způsobů, jak to udělat, podíváme TruncatedReadStream
se na techniku v tomto příkladu:
internal sealed class TruncatedReadStream(Stream innerStream, long maxSize) : Stream
{
private long _maxRemainingLength = maxSize;
public override bool CanRead => true;
public override bool CanSeek => false;
public override bool CanWrite => false;
public override long Length => throw new NotSupportedException();
public override long Position { get => throw new NotSupportedException(); set => throw new NotSupportedException(); }
public override void Flush() => throw new NotSupportedException();
public override int Read(byte[] buffer, int offset, int count)
{
return Read(new Span<byte>(buffer, offset, count));
}
public override int Read(Span<byte> buffer)
{
int readBytes = innerStream.Read(buffer.Slice(0, (int)Math.Min(buffer.Length, _maxRemainingLength)));
_maxRemainingLength -= readBytes;
return readBytes;
}
public override Task<int> ReadAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
{
return ReadAsync(new Memory<byte>(buffer, offset, count), cancellationToken).AsTask();
}
public override async ValueTask<int> ReadAsync(Memory<byte> buffer, CancellationToken cancellationToken = default)
{
int readBytes = await innerStream.ReadAsync(buffer.Slice(0, (int)Math.Min(buffer.Length, _maxRemainingLength)), cancellationToken)
.ConfigureAwait(false);
_maxRemainingLength -= readBytes;
return readBytes;
}
public override long Seek(long offset, SeekOrigin origin) => throw new NotSupportedException();
public override void SetLength(long value) => throw new NotSupportedException();
public override void Write(byte[] buffer, int offset, int count) => throw new NotSupportedException();
public override ValueTask DisposeAsync() => innerStream.DisposeAsync();
protected override void Dispose(bool disposing)
{
if (disposing)
{
innerStream.Dispose();
}
}
}
Příklad použití TruncatedReadStream
:
int maxErrorResponseLength = 1 * 1024; // 1 KB
HttpClient client = new HttpClient();
using HttpResponseMessage response = await client.GetAsync(Uri);
if (response.Content is not null)
{
Stream responseReadStream = await response.Content.ReadAsStreamAsync();
// If MaxErrorResponseLength is set and the response status code is an error code, then wrap the response stream in a TruncatedReadStream
if (maxErrorResponseLength >= 0 && !response.IsSuccessStatusCode)
{
responseReadStream = new TruncatedReadStream(responseReadStream, maxErrorResponseLength);
}
// Read the response stream
Memory<byte> buffer = new byte[1024];
int readValue = await responseReadStream.ReadAsync(buffer);
}
Příklad: Použití hlaviček CachePolicy
Upozorňující
HttpClient
nemá integrovanou logiku pro ukládání odpovědí do mezipaměti. Neexistuje žádné alternativní řešení než implementace veškeré mezipaměti sami. Jednoduše nastavíte hlavičky, které nedosáhnou ukládání do mezipaměti.
Při migraci z HttpWebRequest
do HttpClient
je důležité správně zpracovávat hlavičky související s mezipamětí, jako pragma
cache-control
je a . Tyto hlavičky určují, jak se odpovědi ukládají do mezipaměti a načítají, a zajišťují, aby se vaše aplikace chovala podle očekávání z hlediska výkonu a aktuálnosti dat.
V HttpWebRequest
, můžete použít CachePolicy
vlastnost k nastavení těchto hlaviček. V případě požadavku HttpClient
však musíte tyto hlavičky nastavit ručně.
Starý kód používající HttpWebRequest
:
HttpWebRequest request = WebRequest.CreateHttp(uri);
request.CachePolicy = new HttpRequestCachePolicy(HttpRequestCacheLevel.NoCacheNoStore);
using HttpWebResponse response = (HttpWebResponse)request.GetResponse();
Ve starším HttpWebRequest
rozhraní API bylo použití CachePolicy
jednoduché kvůli integrované podpoře této funkce. Novější HttpClient
rozhraní API ale neposkytuje stejné integrované funkce. Navzdory tomu můžete dosáhnout podobného chování implementací AddCacheControlHeaders
ručně přidávaných hlaviček souvisejících s mezipamětí.
Nový kód pomocí HttpClient
:
public static class CachePolicy
{
public static void AddCacheControlHeaders(HttpRequestMessage request, RequestCachePolicy policy)
Implementace najdete AddCacheControlHeaders
tady.
AddCacheControlHeaders
Zvyk:
static async Task AddCacheControlHeaders()
{
HttpClient client = new HttpClient();
HttpRequestMessage requestMessage = new HttpRequestMessage(HttpMethod.Get, Uri);
CachePolicy.AddCacheControlHeaders(requestMessage, new HttpRequestCachePolicy(HttpRequestCacheLevel.NoCacheNoStore));
HttpResponseMessage response = await client.SendAsync(requestMessage);
}
Použití vlastností ukládání do vyrovnávací paměti
Při migraci z HttpWebRequest na HttpClient
, je důležité pochopit rozdíly v tom, jak tyto dvě rozhraní API zpracovávají ukládání do vyrovnávací paměti.
Starý kód používající HttpWebRequest
:
V HttpWebRequest
aplikaci máte přímou kontrolu nad ukládáním vlastností do vyrovnávací paměti prostřednictvím AllowWriteStreamBuffering
vlastností a AllowReadStreamBuffering
vlastností. Tyto vlastnosti umožňují nebo zakazují ukládání dat do vyrovnávací paměti odesílaných na server a jejich příjem ze serveru.
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(uri);
request.AllowReadStreamBuffering = true; // Default is `false`.
request.AllowWriteStreamBuffering = false; // Default is `true`.
Nový kód pomocí HttpClient
:
V HttpClient
, neexistují žádné přímé ekvivalenty AllowWriteStreamBuffering
a AllowReadStreamBuffering
vlastnosti.
HttpClient sama o sobě neukládá do vyrovnávací paměti těla požadavků, místo toho deleguje odpovědnost na použitou HttpContent
. Obsah, jako StringContent
je nebo ByteArrayContent
jsou logicky již v paměti, zatímco použití StreamContent
ve výchozím nastavení nebude mít žádnou vyrovnávací paměť. Pokud chcete vynutit ukládání obsahu do vyrovnávací paměti, můžete před odesláním požadavku volat HttpContent.LoadIntoBufferAsync
. Tady je příklad:
HttpClient client = new HttpClient();
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, uri);
request.Content = new StreamContent(yourStream);
await request.Content.LoadIntoBufferAsync();
HttpResponseMessage response = await client.SendAsync(request);
Ukládání HttpClient
do vyrovnávací paměti pro čtení je ve výchozím nastavení povolené. Abyste se tomu vyhnuli, můžete určit HttpCompletionOption.ResponseHeadersRead
příznak nebo použít pomocnou rutinu GetStreamAsync
.
HttpClient client = new HttpClient();
using HttpResponseMessage response = await client.GetAsync(uri, HttpCompletionOption.ResponseHeadersRead);
await using Stream responseStream = await response.Content.ReadAsStreamAsync();
// Or simply
await using Stream responseStream = await client.GetStreamAsync(uri);