1f9b284de2
Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> # Conflicts: # Code/Editor/Plugins/ComponentEntityEditorPlugin/ComponentEntityEditorPlugin_precompiled.h # Code/Editor/Plugins/EditorCommon/EditorCommon_precompiled.h # Code/Editor/Plugins/EditorCommon/stdafx.cpp # Code/Editor/Plugins/FFMPEGPlugin/FFMPEGPlugin_precompiled.h # Code/Editor/Plugins/PerforcePlugin/PerforcePlugin_precompiled.h # Code/Editor/Plugins/ProjectSettingsTool/ProjectSettingsTool_precompiled.h # Code/Framework/AzToolsFramework/AzToolsFramework/AzToolsFramework_precompiled.h # Code/Tools/AssetProcessor/native/precompiled.h # Code/Tools/Standalone/StandaloneTools_precompiled.h # Gems/AssetMemoryAnalyzer/Code/Source/AssetMemoryAnalyzer_precompiled.h # Gems/Atom/Asset/ImageProcessingAtom/Code/Source/ImageProcessing_precompiled.h # Gems/Atom/RHI/DX12/Code/Source/RHI/Atom_RHI_DX12_precompiled.h # Gems/Atom/RHI/Metal/Code/Include/Platform/Mac/Atom_RHI_Metal_precompiled_Platform.h # Gems/Atom/RHI/Metal/Code/Include/Platform/iOS/Atom_RHI_Metal_precompiled_Platform.h # Gems/Atom/RHI/Metal/Code/Source/Atom_RHI_Metal_precompiled.h # Gems/Atom/RHI/Metal/Code/atom_rhi_metal_common_files.cmake # Gems/Atom/RHI/Null/Code/Source/Atom_RHI_Null_precompiled.h # Gems/Atom/RHI/Null/Code/atom_rhi_null_common_files.cmake # Gems/Atom/RHI/Vulkan/Code/Include/Platform/Android/Atom_RHI_Vulkan_precompiled_Platform.h # Gems/Atom/RHI/Vulkan/Code/Include/Platform/Linux/Atom_RHI_Vulkan_precompiled_Platform.h # Gems/Atom/RHI/Vulkan/Code/Include/Platform/Mac/Atom_RHI_Vulkan_precompiled_Platform.h # Gems/Atom/RHI/Vulkan/Code/Include/Platform/Windows/Atom_RHI_Vulkan_precompiled_Platform.h # Gems/Atom/RHI/Vulkan/Code/Source/Atom_RHI_Vulkan_precompiled.h # Gems/Atom/RHI/Vulkan/Code/Source/RHI/SwapChain.cpp # Gems/Atom/RHI/Vulkan/Code/atom_rhi_vulkan_common_files.cmake # Gems/AtomLyIntegration/AtomFont/Code/Include/AtomLyIntegration/AtomFont/AtomFont_precompiled.h # Gems/Blast/Code/Source/StdAfx.cpp # Gems/Camera/Code/Source/Camera_precompiled.h # Gems/EMotionFX/Code/Source/EMotionFX_precompiled.h # Gems/FastNoise/Code/Source/FastNoise_precompiled.h # Gems/Gestures/Code/Source/Gestures_precompiled.h # Gems/GradientSignal/Code/Source/GradientSignal_precompiled.h # Gems/GraphCanvas/Code/precompiled.h # Gems/ImGui/Code/Source/ImGui_precompiled.h # Gems/InAppPurchases/Code/Source/InAppPurchases_precompiled.h # Gems/LmbrCentral/Code/Source/LmbrCentral_precompiled.h # Gems/LmbrCentral/Code/Tests/ShapeGeometryUtilTest.cpp # Gems/LyShine/Code/Editor/UiCanvasEditor_precompiled.h # Gems/LyShine/Code/Source/Animation/LyShine_precompiled.h # Gems/LyShine/Code/Source/LyShine_precompiled.h # Gems/LyShineExamples/Code/Source/LyShineExamples_precompiled.h # Gems/Maestro/Code/Source/Cinematics/Maestro_precompiled.h # Gems/Maestro/Code/Source/Maestro_precompiled.h # Gems/MessagePopup/Code/Source/MessagePopup_precompiled.h # Gems/Metastream/Code/Source/Metastream_precompiled.h # Gems/Microphone/Code/Source/Microphone_precompiled.h # Gems/Multiplayer/Code/Source/Multiplayer_precompiled.h # Gems/PhysX/Code/NumericalMethods/Source/NumericalMethods_precompiled.h # Gems/PhysX/Code/Source/PhysXUnsupported_precompiled.h # Gems/PhysX/Code/Source/PhysX_precompiled.h # Gems/PhysX/Code/physx_unsupported_files.cmake # Gems/PhysXDebug/Code/Source/PhysXDebugUnsupported_precompiled.h # Gems/PhysXDebug/Code/Source/PhysXDebug_precompiled.h # Gems/ScriptCanvas/Code/Editor/precompiled.h # Gems/ScriptCanvas/Code/Source/precompiled.h # Gems/ScriptCanvasDeveloper/Code/Source/precompiled.h # Gems/ScriptCanvasPhysics/Code/Source/ScriptCanvasPhysics_precompiled.h # Gems/ScriptEvents/Code/Source/precompiled.h # Gems/ScriptEvents/Code/Tests/Editor/EditorTests.cpp # Gems/ScriptedEntityTweener/Code/Source/ScriptedEntityTweener_precompiled.h # Gems/SliceFavorites/Code/Source/SliceFavorites_precompiled.h # Gems/StartingPointCamera/Code/Source/StartingPointCamera_precompiled.h # Gems/StartingPointInput/Code/Source/StartingPointInput_precompiled.h # Gems/StartingPointMovement/Code/Source/StartingPointMovement_precompiled.h # Gems/SurfaceData/Code/Source/SurfaceData_precompiled.h # Gems/TextureAtlas/Code/Source/TextureAtlas_precompiled.h # Gems/TickBusOrderViewer/Code/Source/TickBusOrderViewer_precompiled.h # Gems/Twitch/Code/Source/Twitch_precompiled.h # Gems/VirtualGamepad/Code/Source/VirtualGamepad_precompiled.h # Gems/WhiteBox/Code/Source/WhiteBoxUnsupported_precompiled.h # Gems/WhiteBox/Code/Source/WhiteBox_precompiled.h
198 lines
7.3 KiB
C++
198 lines
7.3 KiB
C++
/*
|
|
* Copyright (c) Contributors to the Open 3D Engine Project.
|
|
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
|
*
|
|
*/
|
|
|
|
#include <AzFramework/AzFramework_Traits_Platform.h>
|
|
#include <AzCore/PlatformDef.h>
|
|
|
|
// The AWS Native SDK AWSAllocator triggers a warning due to accessing members of std::allocator directly.
|
|
// AWSAllocator.h(70): warning C4996: 'std::allocator<T>::pointer': warning STL4010: Various members of std::allocator are deprecated in C++17.
|
|
// Use std::allocator_traits instead of accessing these members directly.
|
|
// You can define _SILENCE_CXX17_OLD_ALLOCATOR_MEMBERS_DEPRECATION_WARNING or _SILENCE_ALL_CXX17_DEPRECATION_WARNINGS to acknowledge that you have received this warning.
|
|
AZ_PUSH_DISABLE_WARNING(4251 4996, "-Wunknown-warning-option")
|
|
#include <aws/core/http/HttpClient.h>
|
|
#include <aws/core/http/HttpClientFactory.h>
|
|
#include <aws/core/http/HttpRequest.h>
|
|
#include <aws/core/http/HttpResponse.h>
|
|
#include <aws/core/client/ClientConfiguration.h>
|
|
AZ_POP_DISABLE_WARNING
|
|
|
|
#include <AWSNativeSDKInit/AWSNativeSDKInit.h>
|
|
#include <AzCore/std/string/conversions.h>
|
|
#include "HttpRequestManager.h"
|
|
|
|
namespace HttpRequestor
|
|
{
|
|
const char* Manager::s_loggingName = "GemHttpRequestManager";
|
|
|
|
Manager::Manager()
|
|
{
|
|
AZStd::thread_desc desc;
|
|
desc.m_name = s_loggingName;
|
|
desc.m_cpuId = AFFINITY_MASK_USERTHREADS;
|
|
m_runThread = true;
|
|
// Shutdown will be handled by the InitializationManager - no need to call in the destructor
|
|
AWSNativeSDKInit::InitializationManager::InitAwsApi();
|
|
auto function = AZStd::bind(&Manager::ThreadFunction, this);
|
|
m_thread = AZStd::thread(function, &desc);
|
|
}
|
|
|
|
Manager::~Manager()
|
|
{
|
|
// NativeSDK Shutdown does not need to be called here - will be taken care of by the InitializationManager
|
|
m_runThread = false;
|
|
m_requestConditionVar.notify_all();
|
|
if (m_thread.joinable())
|
|
{
|
|
m_thread.join();
|
|
}
|
|
|
|
}
|
|
|
|
void Manager::AddRequest(Parameters && httpRequestParameters)
|
|
{
|
|
{
|
|
AZStd::lock_guard<AZStd::mutex> lock(m_requestMutex);
|
|
m_requestsToHandle.push(AZStd::move(httpRequestParameters));
|
|
}
|
|
m_requestConditionVar.notify_all();
|
|
}
|
|
|
|
void Manager::AddTextRequest(TextParameters && httpTextRequestParameters)
|
|
{
|
|
{
|
|
AZStd::lock_guard<AZStd::mutex> lock(m_requestMutex);
|
|
m_textRequestsToHandle.push(AZStd::move(httpTextRequestParameters));
|
|
}
|
|
m_requestConditionVar.notify_all();
|
|
}
|
|
|
|
void Manager::ThreadFunction()
|
|
{
|
|
// Run the thread as long as directed
|
|
while (m_runThread)
|
|
{
|
|
HandleRequestBatch();
|
|
}
|
|
}
|
|
|
|
void Manager::HandleRequestBatch()
|
|
{
|
|
// Lock mutex and wait for work to be signalled via the condition variable
|
|
AZStd::unique_lock<AZStd::mutex> lock(m_requestMutex);
|
|
m_requestConditionVar.wait(lock, [&] { return !m_runThread || !m_requestsToHandle.empty() || !m_textRequestsToHandle.empty(); });
|
|
|
|
// Swap queues
|
|
AZStd::queue<Parameters> requestsToHandle;
|
|
requestsToHandle.swap(m_requestsToHandle);
|
|
|
|
AZStd::queue<TextParameters> textRequestsToHandle;
|
|
textRequestsToHandle.swap(m_textRequestsToHandle);
|
|
|
|
// Release lock
|
|
lock.unlock();
|
|
|
|
// Handle requests
|
|
while (!requestsToHandle.empty())
|
|
{
|
|
HandleRequest(requestsToHandle.front());
|
|
requestsToHandle.pop();
|
|
}
|
|
|
|
while (!textRequestsToHandle.empty())
|
|
{
|
|
HandleTextRequest(textRequestsToHandle.front());
|
|
textRequestsToHandle.pop();
|
|
}
|
|
}
|
|
|
|
void Manager::HandleRequest(const Parameters& httpRequestParameters)
|
|
{
|
|
Aws::Client::ClientConfiguration config;
|
|
config.enableTcpKeepAlive = AZ_TRAIT_AZFRAMEWORK_AWS_ENABLE_TCP_KEEP_ALIVE_SUPPORTED;
|
|
std::shared_ptr<Aws::Http::HttpClient> httpClient = Aws::Http::CreateHttpClient(config);
|
|
|
|
auto httpRequest = Aws::Http::CreateHttpRequest(httpRequestParameters.GetURI(), httpRequestParameters.GetMethod(), Aws::Utils::Stream::DefaultResponseStreamFactoryMethod);
|
|
|
|
AZ_Assert(httpRequest, "HttpRequest not created!");
|
|
|
|
for (const auto & it : httpRequestParameters.GetHeaders())
|
|
{
|
|
httpRequest->SetHeaderValue(it.first.c_str(), it.second.c_str());
|
|
}
|
|
|
|
if( httpRequestParameters.GetBodyStream() != nullptr)
|
|
{
|
|
httpRequest->AddContentBody(httpRequestParameters.GetBodyStream());
|
|
httpRequest->SetContentLength(AZStd::to_string(httpRequestParameters.GetBodyStream()->str().length()).c_str());
|
|
}
|
|
|
|
auto httpResponse = httpClient->MakeRequest(httpRequest);
|
|
|
|
if (!httpResponse)
|
|
{
|
|
httpRequestParameters.GetCallback()(Aws::Utils::Json::JsonValue(), Aws::Http::HttpResponseCode::INTERNAL_SERVER_ERROR);
|
|
return;
|
|
}
|
|
|
|
if (httpResponse->GetResponseCode() != Aws::Http::HttpResponseCode::OK)
|
|
{
|
|
httpRequestParameters.GetCallback()(Aws::Utils::Json::JsonValue(), httpResponse->GetResponseCode());
|
|
return;
|
|
}
|
|
|
|
Aws::Utils::Json::JsonValue json(httpResponse->GetResponseBody());
|
|
if (json.WasParseSuccessful())
|
|
{
|
|
httpRequestParameters.GetCallback()(AZStd::move(json), httpResponse->GetResponseCode());
|
|
}
|
|
else
|
|
{
|
|
httpRequestParameters.GetCallback()(Aws::Utils::Json::JsonValue(), Aws::Http::HttpResponseCode::INTERNAL_SERVER_ERROR);
|
|
}
|
|
}
|
|
|
|
void Manager::HandleTextRequest(const TextParameters & httpRequestParameters)
|
|
{
|
|
Aws::Client::ClientConfiguration config;
|
|
config.enableTcpKeepAlive = AZ_TRAIT_AZFRAMEWORK_AWS_ENABLE_TCP_KEEP_ALIVE_SUPPORTED;
|
|
std::shared_ptr<Aws::Http::HttpClient> httpClient = Aws::Http::CreateHttpClient(config);
|
|
|
|
auto httpRequest = Aws::Http::CreateHttpRequest(httpRequestParameters.GetURI(), httpRequestParameters.GetMethod(), Aws::Utils::Stream::DefaultResponseStreamFactoryMethod);
|
|
|
|
for (const auto & it : httpRequestParameters.GetHeaders())
|
|
{
|
|
httpRequest->SetHeaderValue(it.first.c_str(), it.second.c_str());
|
|
}
|
|
|
|
if (httpRequestParameters.GetBodyStream() != nullptr)
|
|
{
|
|
httpRequest->AddContentBody(httpRequestParameters.GetBodyStream());
|
|
}
|
|
|
|
auto httpResponse = httpClient->MakeRequest(httpRequest);
|
|
|
|
if (!httpResponse)
|
|
{
|
|
httpRequestParameters.GetCallback()(AZStd::string(), Aws::Http::HttpResponseCode::INTERNAL_SERVER_ERROR);
|
|
return;
|
|
}
|
|
|
|
if (httpResponse->GetResponseCode() != Aws::Http::HttpResponseCode::OK)
|
|
{
|
|
httpRequestParameters.GetCallback()(AZStd::string(), httpResponse->GetResponseCode());
|
|
return;
|
|
}
|
|
|
|
// load up the raw output into a string
|
|
// TODO(aaj): it feels like there should be some limit maybe 1 MB?
|
|
std::istreambuf_iterator<char> eos;
|
|
AZStd::string data(std::istreambuf_iterator<char>(httpResponse->GetResponseBody()), eos);
|
|
httpRequestParameters.GetCallback()(AZStd::move(data), httpResponse->GetResponseCode());
|
|
}
|
|
}
|