Приветствую, Хабр!

В этой статье я разберу небольшую, но очень полезную тему HTTP запросов в UE. Все будет выполнено строго на C++.


Основная часть

Для отправки запроса нам потребуется Singleton объект выглядящий следующим образом:

FHttpModule* Module = &FHttpModule::Get();

Его мы и будем использовать для запросов. Далее необходимо заполнить запрос параметрами и отправить. Тестовый класс назовем Data и поместим туда пару полей. Сам запрос представляет из себя голый объект, который необходимо обернуть в TSharedRef<>.

                                                                                                                                                         
USTRUCT()
struct FData 
{
	GENERATED_BODY()
  
  UPROPERTY()
  int32 ID{-1);
  UPROPERTY()
  FString Name{};
           
};
class ThisClass
{
  //Создание запроса.
  void MakeRequest()
  {
    FHttpModule* Module = &FHttpModule::Get();
    TSharedRef<IHttpRequest,ESPMode::ThreadSafe> Request = Module->CreateRequest();
    Request->OnProcessRequestComplete().BindRaw(this,&ThisClass::OnPostReceivedResponse);// Подвязываемся на делегат получения запроса.
    Request->SetURL(GetFullPathURL()); //Выставляем URL. В моем случае - абстрактный путь куда-нибудь
    Request->SetVerb("POST"); //Непосредственно сам глагол.
    Request->SetHeader(GetDefaultHeader().Key,GetDefaultHeader().Value);//Опять же, абстрактный хеддер. В вашем случае все зависит от API.
    Request->SetContentAsString(GetContent());//Абстрактная строка, некогда бывшая Json файлом. (Об этом Ниже).
    Request->ProcessRequest(); // Отправляем запрос.
  }
  ...
};

После получения запроса будет вызвана следующая функция:

// Три параметра соответственно:
//Request - сам запрос.
//Response - ответ.
//bWasSuccessful - флаг ошибки.
void ThisClass::OnPostReceivedResponse(FHttpRequestPtr Request, FHttpResponsePtr Response, bool bWasSuccessful)
{
  //Если запрос успешен и ответ валиден.
	if(bWasSuccessful && Response.Get())
  {
    Response->GetContentAsString(); //Делаем чтонибудь с ответом.
  }
}

Теперь встал вопрос обработки сей строки. Должен признать, когда я только столкнулся с задачей обработать запрос, то сделал максимально просто: написал парсер, который заполняет json и вытаскивает данные из него. Проблема была в том, что для каждого отдельного json'а приходилось писать парсер, что убивало много времени. В конце концов я нашел нативный инструмент, который каждую структуру, помеченную как USTRUCT(), парсит автоматически.

USTRUCT()
struct FData 
{
	GENERATED_BODY()
  
  int32 ID{-1);
  FString Name{};
};

class ThisClass
{
	void MakeRequest()
  {
  	FHttpModule* Module = &FHttpModule::Get();
		TSharedRef<IHttpRequest,ESPMode::ThreadSafe> Request = Module->CreateRequest();
		Request->OnProcessRequestComplete().BindRaw(this,&ThisClass::OnPostReceivedResponse);// Подвязываемся на делегат получения запроса.
		Request->SetURL(GetFullPathURL()); //Выставляем URL. В моем случае - абстрактный путь куда-нибудь
		Request->SetVerb("POST"); //Непосредственно сам глагол.
		Request->SetHeader(GetDefaultHeader().Key,GetDefaultHeader().Value);//Опять же, абстрактный хеддер. В вашем случае все зависит от API.
    Request->SetContentAsString(GetContent());//Абстрактная строка, некогда бывшая Json файлом.
		Request->ProcessRequest(); // Отправляем запрос.
  }
  void OnPostReceivedResponse(FHttpRequestPtr Request, FHttpResponsePtr Response, bool bWasSuccessful)
  {
    //Если запрос успешен и ответ валиден.
    if(bWasSuccessful && Response.Get())
 	 	{
   		FData Data;
      //Объект сразу закастится к типу FData и будет помещен в out параметр Data. 
      FJsonObjectConverter::JsonObjectStringToUStruct<FData>(Response->GetContentAsString(),&Data);
      Data.ID;//Теперь можно использовать эти данные.
      Data.Name;
    }
  }
  //Таким же образом будет выглядеть преобразование из структуры в строку:
  FString GetContent(const FData& Object)
  {
    FString ReturnStrung;
		FJsonObjectConverter::UStructToJsonObjectString<FData>(Object,&ReturnStrung);
    return ReturnString;
  }
};

Послесловие

Тему отправки и принятия запросов можно продолжить и далее, если задаться вопросами: А как мы поймем что получили все отправленные запросы? И как быть в ситуации, когда нам необходимо сохранять множественные данные, вложенные друг в друга? А что если мы захотим отправить 100 запросов, и каждый ответ нужно обработать отдельно? Не хотелось лишний раз перегружать эту статью, посему если вы поддержите, напишу продолжение.

Задавайте вопросы и кидайте предложения для следующих статей.

Буду рад любой адекватной критике.

Спасибо, что читали!

Комментарии (0)