Provádění požadavků HTTP pomocí třídy HttpClient
V tomto článku se dozvíte, jak provádět požadavky HTTP a zpracovávat odpovědi pomocí HttpClient
třídy.
Důležité
Všechny ukázkové požadavky HTTP cílí na jednu z následujících adres URL:
- https://jsonplaceholder.typicode.com: Bezplatné falešné rozhraní API pro testování a vytváření prototypů.
- https://www.example.com: Tato doména se používá v ilustrativních příkladech v dokumentech.
Koncové body HTTP obvykle vrací data JSON (JavaScript Object Notation), ale ne vždy. Pro usnadnění práce poskytuje volitelný balíček NuGet System.Net.Http.Json několik rozšiřujících metod a HttpClient
HttpContent
provádí automatické serializace a deserializace pomocí System.Text.Json
. Příklady, které upozorní na místa, kde jsou tato rozšíření k dispozici.
Tip
Veškerý zdrojový kód z tohoto článku je k dispozici v úložišti GitHub: .NET Docs .
Vytvoření HttpClient
Většina následujících příkladů znovu používá stejnou HttpClient
instanci, a proto je potřeba ji nakonfigurovat pouze jednou. Chcete-li vytvořit , HttpClient
použijte HttpClient
konstruktor třídy. Další informace naleznete v tématu Pokyny pro použití HttpClient.
// HttpClient lifecycle management best practices:
// https://learn.microsoft.com/dotnet/fundamentals/networking/http/httpclient-guidelines#recommended-use
private static HttpClient sharedClient = new()
{
BaseAddress = new Uri("https://jsonplaceholder.typicode.com"),
};
Předchozí kód:
- Vytvoří instanci nové
HttpClient
instance jako proměnnoustatic
. Podle pokynů se doporučuje opakovaně používatHttpClient
instance během životního cyklu aplikace. - HttpClient.BaseAddress Nastaví na
"https://jsonplaceholder.typicode.com"
.
Tato HttpClient
instance používá základní adresu při provádění následných požadavků. Pokud chcete použít jinou konfiguraci, zvažte následující:
- Nastavení HttpClient.DefaultRequestHeaders.
- Použití nedefaultu HttpClient.Timeout.
- Určení .HttpClient.DefaultRequestVersion
Tip
Alternativně můžete vytvářet HttpClient
instance pomocí přístupu vzoru továrny, který umožňuje nakonfigurovat libovolný počet klientů a využívat je jako služby injektáže závislostí. Další informace najdete v tématu Klientská továrna HTTP s .NET.
Vytvoření požadavku HTTP
Pokud chcete vytvořit požadavek HTTP, zavoláte některá z následujících rozhraní API:
Metoda HTTP: | rozhraní API |
---|---|
GET |
HttpClient.GetAsync |
GET |
HttpClient.GetByteArrayAsync |
GET |
HttpClient.GetStreamAsync |
GET |
HttpClient.GetStringAsync |
POST |
HttpClient.PostAsync |
PUT |
HttpClient.PutAsync |
PATCH |
HttpClient.PatchAsync |
DELETE |
HttpClient.DeleteAsync |
†USER SPECIFIED |
HttpClient.SendAsync |
†A
USER SPECIFIED
požadavek indikuje, žeSendAsync
metoda přijímá všechny platné HttpMethod.
Upozorňující
Vytváření požadavků HTTP se považuje za práci vázané na vstupně-výstupní operace sítě. I když existuje synchronní HttpClient.Send metoda, doporučuje se místo toho použít asynchronní rozhraní API, pokud nemáte dobrý důvod, proč ne.
Poznámka:
Při cílení na zařízení s Androidem (jako je vývoj pro .NET MAUI) je nutné přidat android:usesCleartextTraffic="true"
do <application></application>
AndroidManifest.xml. To umožňuje přenosy s vymazáním textu, jako jsou požadavky HTTP, které jsou jinak zakázány ve výchozím nastavení kvůli zásadám zabezpečení Androidu. Představte si následující příklad nastavení XML:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<application android:usesCleartextTraffic="true"></application>
<!-- omitted for brevity -->
</manifest>
Další informace najdete v tématu Povolení síťového provozu s vymazáním textu pro doménu localhost.
Obsah HTTP
Typ HttpContent se používá k reprezentaci těla entity HTTP a odpovídající hlavičky obsahu. Pro metody HTTP (nebo metody požadavku), které vyžadují tělo , POST
PUT
a PATCH
, použijete HttpContent třídu k určení textu požadavku. Většina příkladů ukazuje, jak připravit podtřídu StringContent datovou částí JSON, ale pro různé typy obsahu (MIME) existují i jiné podtřídy.
- ByteArrayContent: Poskytuje obsah HTTP založený na bajtovém poli.
- FormUrlEncodedContent: Poskytuje obsah HTTP pro řazené kolekce členů názvů a hodnot kódované pomocí
"application/x-www-form-urlencoded"
typu MIME. - JsonContent: Poskytuje obsah HTTP založený na formátu JSON.
- MultipartContent: Poskytuje kolekci objektů HttpContent, které se serializují pomocí
"multipart/*"
specifikace typu MIME. - MultipartFormDataContent: Poskytuje kontejner pro obsah kódovaný pomocí
"multipart/form-data"
typu MIME. - ReadOnlyMemoryContent: Poskytuje obsah HTTP založený na .ReadOnlyMemory<T>
- StreamContent: Poskytuje obsah HTTP založený na datovém proudu.
- StringContent: Poskytuje obsah HTTP založený na řetězci.
Třída HttpContent
se také používá k reprezentaci textu HttpResponseMessageodpovědi , přístupného ve HttpResponseMessage.Content vlastnosti.
Metoda HTTP Get
GET
Požadavek by neměl posílat text a používá se (jak název metody označuje) k načtení (nebo získání) dat z prostředku. Pokud chcete vytvořit požadavek HTTP GET
s použitím identifikátoru HttpClient
URI, použijte metodu HttpClient.GetAsync :
static async Task GetAsync(HttpClient httpClient)
{
using HttpResponseMessage response = await httpClient.GetAsync("todos/3");
response.EnsureSuccessStatusCode()
.WriteRequestToConsole();
var jsonResponse = await response.Content.ReadAsStringAsync();
Console.WriteLine($"{jsonResponse}\n");
// Expected output:
// GET https://jsonplaceholder.typicode.com/todos/3 HTTP/1.1
// {
// "userId": 1,
// "id": 3,
// "title": "fugiat veniam minus",
// "completed": false
// }
}
Předchozí kód:
GET
Odešle požadavek na"https://jsonplaceholder.typicode.com/todos/3"
.- Zajišťuje, že odpověď bude úspěšná.
- Zapíše podrobnosti žádosti do konzoly.
- Přečte text odpovědi jako řetězec.
- Zapíše text odpovědi JSON do konzoly.
Jedná WriteRequestToConsole
se o vlastní metodu rozšíření, která není součástí architektury, ale pokud vás zajímá, jak je implementovaná, zvažte následující kód jazyka C#:
static class HttpResponseMessageExtensions
{
internal static void WriteRequestToConsole(this HttpResponseMessage response)
{
if (response is null)
{
return;
}
var request = response.RequestMessage;
Console.Write($"{request?.Method} ");
Console.Write($"{request?.RequestUri} ");
Console.WriteLine($"HTTP/{request?.Version}");
}
}
Tato funkce slouží k zápisu podrobností žádosti do konzoly v následujícím formátu:
<HTTP Request Method> <Request URI> <HTTP/Version>
GET
Například požadavek na https://jsonplaceholder.typicode.com/todos/3
výstup následující zprávy:
GET https://jsonplaceholder.typicode.com/todos/3 HTTP/1.1
Http Get z JSON
Koncový https://jsonplaceholder.typicode.com/todos bod vrátí pole JSON objektů "todo". Jejich struktura JSON vypadá takto:
[
{
"userId": 1,
"id": 1,
"title": "example title",
"completed": false
},
{
"userId": 1,
"id": 2,
"title": "another example title",
"completed": true
},
]
Objekt C# Todo
je definován takto:
public record class Todo(
int? UserId = null,
int? Id = null,
string? Title = null,
bool? Completed = null);
Jedná se o typ s volitelnými record class
Id
vlastnostmi , Title
, Completed
a UserId
vlastnostmi. Další informace o record
typu najdete v tématu Úvod k typům záznamů v jazyce C#. Pokud chcete automaticky deserializovat GET
požadavky do objektu jazyka C# silného typu, použijte metodu GetFromJsonAsync rozšíření, která je součástí balíčku NuGet System.Net.Http.Json .
static async Task GetFromJsonAsync(HttpClient httpClient)
{
var todos = await httpClient.GetFromJsonAsync<List<Todo>>(
"todos?userId=1&completed=false");
Console.WriteLine("GET https://jsonplaceholder.typicode.com/todos?userId=1&completed=false HTTP/1.1");
todos?.ForEach(Console.WriteLine);
Console.WriteLine();
// Expected output:
// GET https://jsonplaceholder.typicode.com/todos?userId=1&completed=false HTTP/1.1
// Todo { UserId = 1, Id = 1, Title = delectus aut autem, Completed = False }
// Todo { UserId = 1, Id = 2, Title = quis ut nam facilis et officia qui, Completed = False }
// Todo { UserId = 1, Id = 3, Title = fugiat veniam minus, Completed = False }
// Todo { UserId = 1, Id = 5, Title = laboriosam mollitia et enim quasi adipisci quia provident illum, Completed = False }
// Todo { UserId = 1, Id = 6, Title = qui ullam ratione quibusdam voluptatem quia omnis, Completed = False }
// Todo { UserId = 1, Id = 7, Title = illo expedita consequatur quia in, Completed = False }
// Todo { UserId = 1, Id = 9, Title = molestiae perspiciatis ipsa, Completed = False }
// Todo { UserId = 1, Id = 13, Title = et doloremque nulla, Completed = False }
// Todo { UserId = 1, Id = 18, Title = dolorum est consequatur ea mollitia in culpa, Completed = False }
}
V předchozím kódu:
- Žádost je podána
GET
do"https://jsonplaceholder.typicode.com/todos?userId=1&completed=false"
.- Řetězec dotazu představuje kritéria filtrování požadavku.
- Odpověď se po úspěšném dokončení automaticky deserializuje na
List<Todo>
. - Podrobnosti žádosti se zapisují do konzoly spolu s každým
Todo
objektem.
Příspěvek HTTP
Požadavek POST
odešle data na server ke zpracování. Hlavička Content-Type
požadavku označuje, jaký typ MIME text odesílá. Pokud chcete vytvořit požadavek HTTP POST
s ohledem na HttpClient
metodu a metodu HttpClient.PostAsync Uri, použijte:
static async Task PostAsync(HttpClient httpClient)
{
using StringContent jsonContent = new(
JsonSerializer.Serialize(new
{
userId = 77,
id = 1,
title = "write code sample",
completed = false
}),
Encoding.UTF8,
"application/json");
using HttpResponseMessage response = await httpClient.PostAsync(
"todos",
jsonContent);
response.EnsureSuccessStatusCode()
.WriteRequestToConsole();
var jsonResponse = await response.Content.ReadAsStringAsync();
Console.WriteLine($"{jsonResponse}\n");
// Expected output:
// POST https://jsonplaceholder.typicode.com/todos HTTP/1.1
// {
// "userId": 77,
// "id": 201,
// "title": "write code sample",
// "completed": false
// }
}
Předchozí kód:
- StringContent Připraví instanci s textem JSON požadavku (typ
"application/json"
MIME). POST
Odešle požadavek na"https://jsonplaceholder.typicode.com/todos"
.- Zajistí, že odpověď proběhne úspěšně, a zapíše podrobnosti požadavku do konzoly.
- Zapíše text odpovědi jako řetězec do konzoly.
Publikování HTTP ve formátu JSON
Pokud chcete automaticky serializovat POST
argumenty požadavku a deserializovat odpovědi na objekty C# silného typu, použijte PostAsJsonAsync rozšiřující metodu, která je součástí balíčku NuGet System.Net.Http.Json .
static async Task PostAsJsonAsync(HttpClient httpClient)
{
using HttpResponseMessage response = await httpClient.PostAsJsonAsync(
"todos",
new Todo(UserId: 9, Id: 99, Title: "Show extensions", Completed: false));
response.EnsureSuccessStatusCode()
.WriteRequestToConsole();
var todo = await response.Content.ReadFromJsonAsync<Todo>();
Console.WriteLine($"{todo}\n");
// Expected output:
// POST https://jsonplaceholder.typicode.com/todos HTTP/1.1
// Todo { UserId = 9, Id = 201, Title = Show extensions, Completed = False }
}
Předchozí kód:
- Serializuje
Todo
instanci jako JSON a odešlePOST
požadavek na"https://jsonplaceholder.typicode.com/todos"
. - Zajistí, že odpověď proběhne úspěšně, a zapíše podrobnosti požadavku do konzoly.
- Deserializuje tělo odpovědi do
Todo
instance a zapíše doTodo
konzoly.
HTTP Put
Metoda PUT
požadavku buď nahradí existující prostředek, nebo vytvoří nový pomocí datové části textu požadavku. Pokud chcete vytvořit požadavek HTTP PUT
s použitím identifikátoru HttpClient
URI, použijte metodu HttpClient.PutAsync :
static async Task PutAsync(HttpClient httpClient)
{
using StringContent jsonContent = new(
JsonSerializer.Serialize(new
{
userId = 1,
id = 1,
title = "foo bar",
completed = false
}),
Encoding.UTF8,
"application/json");
using HttpResponseMessage response = await httpClient.PutAsync(
"todos/1",
jsonContent);
response.EnsureSuccessStatusCode()
.WriteRequestToConsole();
var jsonResponse = await response.Content.ReadAsStringAsync();
Console.WriteLine($"{jsonResponse}\n");
// Expected output:
// PUT https://jsonplaceholder.typicode.com/todos/1 HTTP/1.1
// {
// "userId": 1,
// "id": 1,
// "title": "foo bar",
// "completed": false
// }
}
Předchozí kód:
- StringContent Připraví instanci s textem JSON požadavku (typ
"application/json"
MIME). PUT
Odešle požadavek na"https://jsonplaceholder.typicode.com/todos/1"
.- Zajišťuje, že odpověď proběhne úspěšně, a zapíše do konzoly podrobnosti požadavku a text odpovědi JSON.
HTTP Put as JSON
Pokud chcete automaticky serializovat PUT
argumenty požadavku a deserializovat odpovědi na objekty jazyka C# silného typu, použijte PutAsJsonAsync rozšiřující metodu, která je součástí balíčku NuGet System.Net.Http.Json .
static async Task PutAsJsonAsync(HttpClient httpClient)
{
using HttpResponseMessage response = await httpClient.PutAsJsonAsync(
"todos/5",
new Todo(Title: "partially update todo", Completed: true));
response.EnsureSuccessStatusCode()
.WriteRequestToConsole();
var todo = await response.Content.ReadFromJsonAsync<Todo>();
Console.WriteLine($"{todo}\n");
// Expected output:
// PUT https://jsonplaceholder.typicode.com/todos/5 HTTP/1.1
// Todo { UserId = , Id = 5, Title = partially update todo, Completed = True }
}
Předchozí kód:
- Serializuje
Todo
instanci jako JSON a odešlePUT
požadavek na"https://jsonplaceholder.typicode.com/todos/5"
. - Zajistí, že odpověď proběhne úspěšně, a zapíše podrobnosti požadavku do konzoly.
- Deserializuje tělo odpovědi do
Todo
instance a zapíše doTodo
konzoly.
Oprava HTTP
Požadavek PATCH
je částečná aktualizace existujícího prostředku. Nevytáčí nový prostředek a není určený k nahrazení existujícího prostředku. Místo toho aktualizuje prostředek pouze částečně. Pokud chcete vytvořit požadavek HTTP PATCH
s použitím identifikátoru HttpClient
URI, použijte metodu HttpClient.PatchAsync :
static async Task PatchAsync(HttpClient httpClient)
{
using StringContent jsonContent = new(
JsonSerializer.Serialize(new
{
completed = true
}),
Encoding.UTF8,
"application/json");
using HttpResponseMessage response = await httpClient.PatchAsync(
"todos/1",
jsonContent);
response.EnsureSuccessStatusCode()
.WriteRequestToConsole();
var jsonResponse = await response.Content.ReadAsStringAsync();
Console.WriteLine($"{jsonResponse}\n");
// Expected output
// PATCH https://jsonplaceholder.typicode.com/todos/1 HTTP/1.1
// {
// "userId": 1,
// "id": 1,
// "title": "delectus aut autem",
// "completed": true
// }
}
Předchozí kód:
- StringContent Připraví instanci s textem JSON požadavku (typ
"application/json"
MIME). PATCH
Odešle požadavek na"https://jsonplaceholder.typicode.com/todos/1"
.- Zajišťuje, že odpověď proběhne úspěšně, a zapíše do konzoly podrobnosti požadavku a text odpovědi JSON.
Pro požadavky v System.Net.Http.Json
balíčku NuGet neexistují PATCH
žádné metody rozšíření.
Odstranění HTTP
Požadavek DELETE
odstraní existující prostředek. DELETE
Požadavek je idempotentní, ale není bezpečný, což znamená, že více DELETE
požadavků na stejné prostředky přináší stejný výsledek, ale požadavek ovlivňuje stav prostředku. Pokud chcete vytvořit požadavek HTTP DELETE
s použitím identifikátoru HttpClient
URI, použijte metodu HttpClient.DeleteAsync :
static async Task DeleteAsync(HttpClient httpClient)
{
using HttpResponseMessage response = await httpClient.DeleteAsync("todos/1");
response.EnsureSuccessStatusCode()
.WriteRequestToConsole();
var jsonResponse = await response.Content.ReadAsStringAsync();
Console.WriteLine($"{jsonResponse}\n");
// Expected output
// DELETE https://jsonplaceholder.typicode.com/todos/1 HTTP/1.1
// {}
}
Předchozí kód:
DELETE
Odešle požadavek na"https://jsonplaceholder.typicode.com/todos/1"
.- Zajistí, že odpověď proběhne úspěšně, a zapíše podrobnosti požadavku do konzoly.
Tip
Odpověď na DELETE
požadavek (stejně jako PUT
požadavek) může nebo nemusí obsahovat text.
Hlavička HTTP
Požadavek HEAD
je podobný GET
požadavku. Místo vrácení prostředku vrátí pouze hlavičky přidružené k prostředku. Odpověď na HEAD
požadavek nevrací tělo. Pokud chcete vytvořit požadavek HTTP HEAD
s daným identifikátorem HttpClient
URI, použijte HttpClient.SendAsync metodu s nastavenou HttpMethod HttpMethod.Head
hodnotou :
static async Task HeadAsync(HttpClient httpClient)
{
using HttpRequestMessage request = new(
HttpMethod.Head,
"https://www.example.com");
using HttpResponseMessage response = await httpClient.SendAsync(request);
response.EnsureSuccessStatusCode()
.WriteRequestToConsole();
foreach (var header in response.Headers)
{
Console.WriteLine($"{header.Key}: {string.Join(", ", header.Value)}");
}
Console.WriteLine();
// Expected output:
// HEAD https://www.example.com/ HTTP/1.1
// Accept-Ranges: bytes
// Age: 550374
// Cache-Control: max-age=604800
// Date: Wed, 10 Aug 2022 17:24:55 GMT
// ETag: "3147526947"
// Server: ECS, (cha / 80E2)
// X-Cache: HIT
}
Předchozí kód:
HEAD
Odešle požadavek na"https://www.example.com/"
.- Zajistí, že odpověď proběhne úspěšně, a zapíše podrobnosti požadavku do konzoly.
- Iteruje všechny hlavičky odpovědi a zapisuje je do konzoly.
Možnosti PROTOKOLU HTTP
Požadavek OPTIONS
slouží k identifikaci metod HTTP, které server nebo koncový bod podporuje. Pokud chcete vytvořit požadavek HTTP OPTIONS
s daným identifikátorem HttpClient
URI, použijte HttpClient.SendAsync metodu s nastavenou HttpMethod HttpMethod.Options
hodnotou :
static async Task OptionsAsync(HttpClient httpClient)
{
using HttpRequestMessage request = new(
HttpMethod.Options,
"https://www.example.com");
using HttpResponseMessage response = await httpClient.SendAsync(request);
response.EnsureSuccessStatusCode()
.WriteRequestToConsole();
foreach (var header in response.Content.Headers)
{
Console.WriteLine($"{header.Key}: {string.Join(", ", header.Value)}");
}
Console.WriteLine();
// Expected output
// OPTIONS https://www.example.com/ HTTP/1.1
// Allow: OPTIONS, GET, HEAD, POST
// Content-Type: text/html; charset=utf-8
// Expires: Wed, 17 Aug 2022 17:28:42 GMT
// Content-Length: 0
}
Předchozí kód:
OPTIONS
Odešle požadavek HTTP na"https://www.example.com/"
adresu .- Zajistí, že odpověď proběhne úspěšně, a zapíše podrobnosti požadavku do konzoly.
- Iteruje přes všechny hlavičky obsahu odpovědi a každý z nich zapisuje do konzoly.
Trasování HTTP
Požadavek TRACE
může být užitečný pro ladění, protože poskytuje smyčku na úrovni aplikace zpět zprávy požadavku. Pokud chcete vytvořit požadavek HTTP TRACE
, vytvořte pomocí HttpRequestMessage příkazu HttpMethod.Trace
:
using HttpRequestMessage request = new(
HttpMethod.Trace,
"{ValidRequestUri}");
Upozornění
Metoda TRACE
HTTP není podporována všemi servery HTTP. Pokud se používá nechtěně, může vystavit ohrožení zabezpečení. Další informace naleznete v tématu Open Web Application Security Project (OWASP): Trasování mezi weby.
Zpracování odpovědi HTTP
Pokaždé, když zpracováváte odpověď HTTP, komunikujete s typem HttpResponseMessage . Při vyhodnocování platnosti odpovědi se používá několik členů. Stavový kód HTTP je k dispozici prostřednictvím HttpResponseMessage.StatusCode vlastnosti. Představte si, že jste odeslali požadavek na instanci klienta:
using HttpResponseMessage response = await httpClient.SendAsync(request);
Abyste měli jistotu response
, že je OK
(stavový kód HTTP 200), můžete ho vyhodnotit, jak je znázorněno v následujícím příkladu:
if (response is { StatusCode: HttpStatusCode.OK })
{
// Omitted for brevity...
}
Existují další stavové kódy HTTP, které představují úspěšnou odpověď, například CREATED
(stavový kód HTTP 201), ACCEPTED
(stavový kód HTTP 202), NO CONTENT
(stavový kód HTTP 204) a RESET CONTENT
(stavový kód HTTP 205). Vlastnost můžete použít HttpResponseMessage.IsSuccessStatusCode také k vyhodnocení těchto kódů, což zajišťuje, že stavový kód odpovědi je v rozsahu 200–299:
if (response.IsSuccessStatusCode)
{
// Omitted for brevity...
}
Pokud potřebujete, aby architektura vyvolá HttpRequestException, můžete volat metodu HttpResponseMessage.EnsureSuccessStatusCode() :
response.EnsureSuccessStatusCode();
Tento kód vyvolá HttpRequestException
stavový kód odpovědi v rozsahu 200–299.
Platné odpovědi http na obsah
S platnou odpovědí můžete získat přístup k textu odpovědi pomocí Content vlastnosti. Tělo je k dispozici jako HttpContent instance, kterou můžete použít pro přístup k textu jako stream, bajtové pole nebo řetězec:
await using Stream responseStream =
await response.Content.ReadAsStreamAsync();
V předchozím kódu responseStream
se dá použít ke čtení textu odpovědi.
byte[] responseByteArray = await response.Content.ReadAsByteArrayAsync();
V předchozím kódu responseByteArray
se dá použít ke čtení textu odpovědi.
string responseString = await response.Content.ReadAsStringAsync();
V předchozím kódu responseString
se dá použít ke čtení textu odpovědi.
Když konečně víte, že koncový bod HTTP vrátí JSON, můžete tělo odpovědi deserializovat do libovolného platného objektu C# pomocí balíčku NuGet System.Net.Http.Json :
T? result = await response.Content.ReadFromJsonAsync<T>();
V předchozím kódu result
je tělo odpovědi deserializováno jako typ T
.
Zpracování chyb HTTP
Pokud požadavek HTTP selže, vyvolá se HttpRequestException . Zachycení samotné výjimky nemusí být dostatečné, protože existují další potenciální výjimky, které byste mohli chtít zvážit. Volající kód mohl například použít token zrušení, který byl zrušen před dokončením požadavku. V tomto scénáři byste zachytili TaskCanceledException:
using var cts = new CancellationTokenSource();
try
{
// Assuming:
// httpClient.Timeout = TimeSpan.FromSeconds(10)
using var response = await httpClient.GetAsync(
"http://localhost:5001/sleepFor?seconds=100", cts.Token);
}
catch (OperationCanceledException ex) when (cts.IsCancellationRequested)
{
// When the token has been canceled, it is not a timeout.
Console.WriteLine($"Canceled: {ex.Message}");
}
Podobně platí, že pokud při vytváření požadavku HTTP server nereaguje před HttpClient.Timeout překročením stejné výjimky, vyvolá se stejná výjimka. V tomto scénáři však můžete rozlišit, že došlo k vypršení časového limitu Exception.InnerException vyhodnocením při zachycení TaskCanceledException:
try
{
// Assuming:
// httpClient.Timeout = TimeSpan.FromSeconds(10)
using var response = await httpClient.GetAsync(
"http://localhost:5001/sleepFor?seconds=100");
}
catch (OperationCanceledException ex) when (ex.InnerException is TimeoutException tex)
{
Console.WriteLine($"Timed out: {ex.Message}, {tex.Message}");
}
Pokud v předchozím kódu došlo k vypršení časového limitu vnitřní výjimky TimeoutException a požadavek nebyl zrušen tokenem zrušení.
Pokud chcete vyhodnotit stavový kód HTTP při zachytávání HttpRequestException, můžete tuto vlastnost vyhodnotit HttpRequestException.StatusCode :
try
{
// Assuming:
// httpClient.Timeout = TimeSpan.FromSeconds(10)
using var response = await httpClient.GetAsync(
"http://localhost:5001/doesNotExist");
response.EnsureSuccessStatusCode();
}
catch (HttpRequestException ex) when (ex is { StatusCode: HttpStatusCode.NotFound })
{
// Handle 404
Console.WriteLine($"Not found: {ex.Message}");
}
V předchozím kódu je volána metoda vyvolá EnsureSuccessStatusCode() výjimku, pokud odpověď není úspěšná. Vlastnost HttpRequestException.StatusCode se pak vyhodnotí a určí, jestli odpověď byla 404
(stavový kód HTTP 404). Existuje několik pomocných metod HttpClient
, které implicitně volají EnsureSuccessStatusCode
vaším jménem, zvažte následující rozhraní API:
Tip
Všechny HttpClient
metody používané k provádění požadavků HTTP, které nevrací HttpResponseMessage
implicitně volání EnsureSuccessStatusCode
vaším jménem.
Při volání těchto metod můžete zpracovat HttpRequestException
a vyhodnotit HttpRequestException.StatusCode vlastnost k určení stavového kódu HTTP odpovědi:
try
{
// These extension methods will throw HttpRequestException
// with StatusCode set when the HTTP request status code isn't 2xx:
//
// GetByteArrayAsync
// GetStreamAsync
// GetStringAsync
using var stream = await httpClient.GetStreamAsync(
"https://localhost:5001/doesNotExists");
}
catch (HttpRequestException ex) when (ex is { StatusCode: HttpStatusCode.NotFound })
{
// Handle 404
Console.WriteLine($"Not found: {ex.Message}");
}
Můžou existovat scénáře, ve kterých potřebujete v kódu vyvolat HttpRequestException kód. Konstruktor HttpRequestException() je veřejný a můžete ho použít k vyvolání výjimky s vlastní zprávou:
try
{
using var response = await httpClient.GetAsync(
"https://localhost:5001/doesNotExists");
// Throw for anything higher than 400.
if (response is { StatusCode: >= HttpStatusCode.BadRequest })
{
throw new HttpRequestException(
"Something went wrong", inner: null, response.StatusCode);
}
}
catch (HttpRequestException ex) when (ex is { StatusCode: HttpStatusCode.NotFound })
{
Console.WriteLine($"Not found: {ex.Message}");
}
Proxy server HTTP
Proxy server HTTP je možné nakonfigurovat jedním ze dvou způsobů. Pro vlastnost je zadána HttpClient.DefaultProxy výchozí hodnota. Případně můžete pro vlastnost zadat proxy HttpClientHandler.Proxy server.
Globální výchozí proxy server
Jedná se HttpClient.DefaultProxy
o statickou vlastnost, která určuje výchozí proxy server, který všechny HttpClient
instance používají, pokud není v předaném konstruktoru HttpClientHandler explicitně nastaven žádný proxy server.
Výchozí instance vrácená touto vlastností inicializuje následující jinou sadu pravidel v závislosti na vaší platformě:
- Pro Windows: Načte konfiguraci proxy serveru z proměnných prostředí nebo pokud nejsou definovány, z nastavení proxy serveru uživatele.
- Pro macOS: Načte konfiguraci proxy serveru z proměnných prostředí nebo pokud nejsou definované, z nastavení proxy serveru systému.
- Pro Linux: Načte konfiguraci proxy serveru z proměnných prostředí nebo v případě, že nejsou definovány, tato vlastnost inicializuje nekonfigurovanou instanci, která obchází všechny adresy.
Proměnné prostředí používané k DefaultProxy
inicializaci na platformách se systémem Windows a Unix jsou:
HTTP_PROXY
: proxy server použitý pro požadavky HTTP.HTTPS_PROXY
: proxy server používaný na žádostech HTTPS.ALL_PROXY
: Proxy server používaný v požadavcích HTTP a/nebo HTTPS v případěHTTP_PROXY
, že nejsou definovány neboHTTPS_PROXY
nejsou definovány.NO_PROXY
: Čárkami oddělený seznam názvů hostitelů, které by měly být vyloučeny z proxy serveru. Hvězdičky se nepodporují u zástupných znaků; pro případ, že chcete shodovat subdoménu, použijte úvodní tečku. Příklady:NO_PROXY=.example.com
(s úvodní tečkou) se shodujíwww.example.com
, ale nebudou se shodovatexample.com
.NO_PROXY=example.com
(bez úvodní tečky) se neshodujewww.example.com
. Toto chování se může v budoucnu znovu vrátit, aby se lépe shodovaly s jinými ekosystémy.
V systémech, kde proměnné prostředí rozlišují malá a velká písmena, mohou být názvy proměnných malými nebo velkými písmeny. Nejdřív se zaškrtnou malá písmena.
Proxy server může být název hostitele nebo IP adresa, případně za ním dvojtečka a číslo portu, nebo to může být http
adresa URL, volitelně včetně uživatelského jména a hesla pro ověření proxy serveru. Adresa URL musí začínat písmenem http
, nikoli https
a nesmí obsahovat žádný text za názvem hostitele, IP adresou nebo portem.
Proxy na klienta
Vlastnost HttpClientHandler.Proxy identifikuje objekt, který WebProxy se má použít ke zpracování požadavků na internetové prostředky. Chcete-li určit, že se nemá použít žádný proxy server, nastavte Proxy
vlastnost na instanci proxy vrácenou metodou GlobalProxySelection.GetEmptyWebProxy() .
Konfigurační soubor místního počítače nebo aplikace může určovat, že se používá výchozí proxy server. Pokud je zadaná vlastnost Proxy, přepíší nastavení proxy z vlastnosti Proxy místní počítač nebo konfigurační soubor aplikace a obslužná rutina použije zadané nastavení proxy serveru. Pokud není v konfiguračním souboru zadán žádný proxy server a vlastnost Proxy není zadána, obslužná rutina použije nastavení proxy serveru zděděné z místního počítače. Pokud neexistují žádná nastavení proxy serveru, požadavek se odešle přímo na server.
Třída HttpClientHandler parsuje seznam obejití proxy serveru se zástupnými znaky zděděnými z nastavení místního počítače. Třída například HttpClientHandler
parsuje seznam obejití "nt*"
z prohlížečů jako regulární výraz "nt.*"
. Adresa URL http://nt.com
proxy by tedy obešla pomocí HttpClientHandler
třídy.
Třída HttpClientHandler
podporuje obejití místního proxy serveru. Třída považuje cíl za místní, pokud jsou splněny některé z následujících podmínek:
- Cíl obsahuje plochý název (v adrese URL nejsou žádné tečky).
- Cíl obsahuje adresu zpětné smyčky (Loopback nebo IPv6Loopback) nebo cíl obsahuje přiřazenou IPAddress k místnímu počítači.
- Přípona domény cíle odpovídá příponě domény místního počítače (DomainName).
Další informace o konfiguraci proxy serveru najdete v tématech: