Поделиться через


HttpClient

Важные API

Используйте HttpClient и остальную часть API пространства имен Windows.Web.Http для отправки и получения информации с помощью протоколов HTTP 2.0 и HTTP 1.1.

Обзор пространства имен HttpClient и Пространства имен Windows.Web.Http

Классы в пространстве имен Windows.Web.Http и связанных пространствах имен Windows.Web.Http.Headers и Windows.Web.Http.Filters предоставляют интерфейс программирования для приложений универсальная платформа Windows (UWP), которые выполняют базовые запросы GET или реализуют более сложные функции HTTP, перечисленные ниже.

  • Методы для общих команд (DELETE, GET, PUT и POST). Каждый из этих запросов отправляется как асинхронная операция.

  • Поддержка распространенных параметров и шаблонов проверки подлинности.

  • Доступ к сведениям о протоколе SSL для транспорта.

  • Возможность включать настраиваемые фильтры в расширенные приложения.

  • Возможность получения, задания и удаления файлов cookie.

  • Сведения о ходе выполнения HTTP-запроса, доступные в асинхронных методах.

Класс Windows.Web.Http.HttpRequestMessage представляет сообщение HTTP-запроса, отправленное Windows.Web.Http.HttpClient. Класс Windows.Web.Http.HttpResponseMessage представляет сообщение HTTP-ответа, полученное из HTTP-запроса. HTTP-сообщения определяются в RFC 2616 IETF.

Пространство имен Windows.Web.Http представляет содержимое HTTP в виде текста сущности HTTP и заголовков, включая файлы cookie. Содержимое HTTP может быть связано с HTTP-запросом или HTTP-ответом. Пространство имен Windows.Web.Http предоставляет ряд различных классов для представления содержимого HTTP.

  • HttpBufferContent. Содержимое в качестве буфера
  • HttpFormUrlEncodedContent. Содержимое как имя и кортежи значений, закодированные с помощью типа MIME приложения/x-www-form-urlencoded MIME
  • HttpMultipartContent. Содержимое в форме типа MIME multipart/*.
  • HttpMultipartFormDataContent. Содержимое, закодированное как тип MIME для нескольких частей или форм.
  • HttpStreamContent. Содержимое в виде потока (внутренний тип используется методом HTTP GET для получения данных и метода HTTP POST для отправки данных)
  • HttpStringContent. Содержимое в виде строки.
  • IHttpContent — базовый интерфейс для разработчиков, создающих собственные объекты содержимого.

Фрагмент кода в разделе "Отправка простого запроса GET по протоколу HTTP" использует класс HttpStringContent для представления ОТВЕТА HTTP из HTTP-запроса GET в виде строки.

Пространство имен Windows.Web.Http.Headers поддерживает создание заголовков HTTP и файлов cookie, которые затем связаны как свойства с объектами HttpRequestMessage и HttpResponseMessage.

Отправка простого запроса GET по протоколу HTTP

Как упоминалось ранее в этой статье, пространство имен Windows.Web.Http позволяет приложениям UWP отправлять запросы GET. Следующий фрагмент кода демонстрирует, как отправлять запрос GET на адрес http://www.contoso.com с помощью класса Windows.Web.Http.HttpClient и класса Windows.Web.Http.HttpResponseMessage для считывания ответа из запроса GET.

//Create an HTTP client object
Windows.Web.Http.HttpClient httpClient = new Windows.Web.Http.HttpClient();

//Add a user-agent header to the GET request. 
var headers = httpClient.DefaultRequestHeaders;

//The safe way to add a header value is to use the TryParseAdd method and verify the return value is true,
//especially if the header value is coming from user input.
string header = "ie";
if (!headers.UserAgent.TryParseAdd(header))
{
    throw new Exception("Invalid header value: " + header);
}

header = "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; WOW64; Trident/6.0)";
if (!headers.UserAgent.TryParseAdd(header))
{
    throw new Exception("Invalid header value: " + header);
}

Uri requestUri = new Uri("http://www.contoso.com");

//Send the GET request asynchronously and retrieve the response as a string.
Windows.Web.Http.HttpResponseMessage httpResponse = new Windows.Web.Http.HttpResponseMessage();
string httpResponseBody = "";

try
{
    //Send the GET request
    httpResponse = await httpClient.GetAsync(requestUri);
    httpResponse.EnsureSuccessStatusCode();
    httpResponseBody = await httpResponse.Content.ReadAsStringAsync();
}
catch (Exception ex)
{
    httpResponseBody = "Error: " + ex.HResult.ToString("X") + " Message: " + ex.Message;
}
// pch.h
#pragma once
#include <winrt/Windows.Foundation.h>
#include <winrt/Windows.Web.Http.Headers.h>

// main.cpp : Defines the entry point for the console application.
#include "pch.h"
#include <iostream>
using namespace winrt;
using namespace Windows::Foundation;

int main()
{
    init_apartment();

    // Create an HttpClient object.
    Windows::Web::Http::HttpClient httpClient;

    // Add a user-agent header to the GET request.
    auto headers{ httpClient.DefaultRequestHeaders() };

    // The safe way to add a header value is to use the TryParseAdd method, and verify the return value is true.
    // This is especially important if the header value is coming from user input.
    std::wstring header{ L"ie" };
    if (!headers.UserAgent().TryParseAdd(header))
    {
        throw L"Invalid header value: " + header;
    }

    header = L"Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; WOW64; Trident/6.0)";
    if (!headers.UserAgent().TryParseAdd(header))
    {
        throw L"Invalid header value: " + header;
    }

    Uri requestUri{ L"http://www.contoso.com" };

    // Send the GET request asynchronously, and retrieve the response as a string.
    Windows::Web::Http::HttpResponseMessage httpResponseMessage;
    std::wstring httpResponseBody;

    try
    {
        // Send the GET request.
        httpResponseMessage = httpClient.GetAsync(requestUri).get();
        httpResponseMessage.EnsureSuccessStatusCode();
        httpResponseBody = httpResponseMessage.Content().ReadAsStringAsync().get();
    }
    catch (winrt::hresult_error const& ex)
    {
        httpResponseBody = ex.message();
    }
    std::wcout << httpResponseBody;
}

Использование запроса POST для отправки двоичных данных по HTTP

Пример кода C++/WinRT ниже демонстрирует использование данных формы и запроса POST для отправки небольшого объема двоичных данных в виде файла, передаваемого на веб-сервер. В этом коде класс HttpBufferContent представляет двоичные данные, а класс HttpMultipartFormDataContent — данные составной формы.

Примечание.

Использовать вызов get (как показано в примере кода ниже) недопустимо для потока пользовательского интерфейса. В таком случае используйте способ, описанный в статье Concurrency and asynchronous operations with C++/WinRT (Параллелизм и синхронные операций с помощью C++/WinRT).

// pch.h
#pragma once
#include <winrt/Windows.Foundation.h>
#include <winrt/Windows.Security.Cryptography.h>
#include <winrt/Windows.Storage.Streams.h>
#include <winrt/Windows.Web.Http.Headers.h>

// main.cpp : Defines the entry point for the console application.
#include "pch.h"
#include <iostream>
#include <sstream>
using namespace winrt;
using namespace Windows::Foundation;
using namespace Windows::Storage::Streams;

int main()
{
    init_apartment();

    auto buffer{
        Windows::Security::Cryptography::CryptographicBuffer::ConvertStringToBinary(
            L"A sentence of text to encode into binary to serve as sample data.",
            Windows::Security::Cryptography::BinaryStringEncoding::Utf8
        )
    };
    Windows::Web::Http::HttpBufferContent binaryContent{ buffer };
    // You can use the 'image/jpeg' content type to represent any binary data;
    // it's not necessarily an image file.
    binaryContent.Headers().Append(L"Content-Type", L"image/jpeg");

    Windows::Web::Http::Headers::HttpContentDispositionHeaderValue disposition{ L"form-data" };
    binaryContent.Headers().ContentDisposition(disposition);
    // The 'name' directive contains the name of the form field representing the data.
    disposition.Name(L"fileForUpload");
    // Here, the 'filename' directive is used to indicate to the server a file name
    // to use to save the uploaded data.
    disposition.FileName(L"file.dat");

    Windows::Web::Http::HttpMultipartFormDataContent postContent;
    postContent.Add(binaryContent); // Add the binary data content as a part of the form data content.

    // Send the POST request asynchronously, and retrieve the response as a string.
    Windows::Web::Http::HttpResponseMessage httpResponseMessage;
    std::wstring httpResponseBody;

    try
    {
        // Send the POST request.
        Uri requestUri{ L"https://www.contoso.com/post" };
        Windows::Web::Http::HttpClient httpClient;
        httpResponseMessage = httpClient.PostAsync(requestUri, postContent).get();
        httpResponseMessage.EnsureSuccessStatusCode();
        httpResponseBody = httpResponseMessage.Content().ReadAsStringAsync().get();
    }
    catch (winrt::hresult_error const& ex)
    {
        httpResponseBody = ex.message();
    }
    std::wcout << httpResponseBody;
}

Чтобы передать содержимое двоичного файла (а не явные двоичные данные, как это было сделано выше) с помощью запроса POST, воспользуйтесь объектом HttpStreamContent. Создайте его и передайте значение, возвращенное вызовом, в виде аргумента для конструктора в метод StorageFile.OpenReadAsync. Этот метод возвращает поток для данных в вашем двоичном файле.

Кроме того, если вы передаете файл большого размера (больше 10 МБ), мы рекомендуем использовать интерфейсы API среды выполнения Windows для передачи в фоновом режиме.

Передача данных JSON с помощью запроса POST по HTTP

В следующем примере данные JSON передаются на конечную точку, а затем выводится текст ответа.

using System;
using System.Diagnostics;
using System.Threading.Tasks;
using Windows.Storage.Streams;
using Windows.Web.Http;

private async Task TryPostJsonAsync()
{
    try
    {
        // Construct the HttpClient and Uri. This endpoint is for test purposes only.
        HttpClient httpClient = new HttpClient();
        Uri uri = new Uri("https://www.contoso.com/post");

        // Construct the JSON to post.
        HttpStringContent content = new HttpStringContent(
            "{ \"firstName\": \"Eliot\" }",
            UnicodeEncoding.Utf8,
            "application/json");

        // Post the JSON and wait for a response.
        HttpResponseMessage httpResponseMessage = await httpClient.PostAsync(
            uri,
            content);

        // Make sure the post succeeded, and write out the response.
        httpResponseMessage.EnsureSuccessStatusCode();
        var httpResponseBody = await httpResponseMessage.Content.ReadAsStringAsync();
        Debug.WriteLine(httpResponseBody);
    }
    catch (Exception ex)
    {
        // Write out any exceptions.
        Debug.WriteLine(ex);
    }
}
// pch.h
#pragma once
#include <winrt/Windows.Foundation.h>
#include <winrt/Windows.Security.Cryptography.h>
#include <winrt/Windows.Storage.Streams.h>
#include <winrt/Windows.Web.Http.Headers.h>

// main.cpp : Defines the entry point for the console application.
#include "pch.h"
#include <iostream>
#include <sstream>
using namespace winrt;
using namespace Windows::Foundation;
using namespace Windows::Storage::Streams;

int main()
{
    init_apartment();

    Windows::Web::Http::HttpResponseMessage httpResponseMessage;
    std::wstring httpResponseBody;

    try
    {
        // Construct the HttpClient and Uri. This endpoint is for test purposes only.
        Windows::Web::Http::HttpClient httpClient;
        Uri requestUri{ L"https://www.contoso.com/post" };

        // Construct the JSON to post.
        Windows::Web::Http::HttpStringContent jsonContent(
            L"{ \"firstName\": \"Eliot\" }",
            UnicodeEncoding::Utf8,
            L"application/json");

        // Post the JSON, and wait for a response.
        httpResponseMessage = httpClient.PostAsync(
            requestUri,
            jsonContent).get();

        // Make sure the post succeeded, and write out the response.
        httpResponseMessage.EnsureSuccessStatusCode();
        httpResponseBody = httpResponseMessage.Content().ReadAsStringAsync().get();
        std::wcout << httpResponseBody.c_str();
    }
    catch (winrt::hresult_error const& ex)
    {
        std::wcout << ex.message().c_str();
    }
}

Исключения в Windows.Web.Http

Исключение возникает, когда недопустимая строка для универсального идентификатора ресурса (URI) передается конструктору объекта Windows.Foundation.Uri.

.NET: тип Windows.Foundation.Uri отображается в C# и VB как System.Uri.

В C# и Visual Basic эту ошибку можно избежать с помощью класса System.Uri в .NET 4.5 и одного из методов System.Uri.TryCreate для проверки строки, полученной от пользователя до создания URI.

В C++не существует метода для анализа строки в URI. Если приложение получает входные данные от пользователя для Windows.Foundation.Uri, конструктор должен находиться в блоке try/catch. Если возникает исключение, приложение может уведомить пользователя и запросить новое имя узла.

Windows.Web.Http не имеет удобной функции. Поэтому приложению с помощью HttpClient и других классов в этом пространстве имен необходимо использовать значение HRESULT.

В приложениях, использующих C++ /WinRT, структура winrt::hresult_error представляет исключение, возникающее во время выполнения приложений. Функция winrt::hresult_error::code возвращает значение HRESULT, назначенное определенному исключению. Функция winrt::hresult_error::message возвращает строку, которая предоставляется системой и связывается со значением HRESULT. Дополнительные сведения см. в статье Обработка ошибок в C++/WinRT.

Возможные значения HRESULT перечислены в файле заголовка Winerror.h . Ваше приложение может фильтровать полученные данные по определенному значению перечисления HRESULT, чтобы действовать в зависимости от причины исключения.

В приложениях, использующих платформа .NET Framework 4.5 в C#, VB.NET, System.Exception представляет ошибку во время выполнения приложения при возникновении исключения. Свойство System.Exception.HResult возвращает HRESULT , назначенное конкретному исключению. Свойство System.Exception.Message возвращает сообщение, описывающее исключение.

C++/CX замещается C++/WinRT. Но в приложениях на C++/CX объект Platform::Exception представляет ошибку во время выполнения приложения, когда возникает исключение. Свойство Platform::Exception::HResult возвращает hrESULT, назначенное конкретному исключению. Свойство Platform::Exception::Message возвращает указанную системой строку, связанную со значением HRESULT .

Для многих ошибок при проверке параметров HRESULT возвращает значение E\_INVALIDARG. Для некоторых недопустимых вызовов методов возвращаемым HRESULT является E_ILLEGAL_METHOD_CALL.