Network: Implement WebService with emscripten fetch API on wasm

This commit is contained in:
SirLynix
2023-06-14 19:32:01 +02:00
committed by Jérôme Leclercq
parent b28d97b1fa
commit 6bf91e10e5
13 changed files with 369 additions and 74 deletions

View File

@@ -37,7 +37,9 @@ namespace Nz
};
private:
#ifndef NAZARA_PLATFORM_WEB
std::unique_ptr<class CurlLibrary> m_curlLibrary;
#endif
static Network* s_instance;
};

View File

@@ -7,6 +7,8 @@
#ifndef NAZARA_NETWORK_WEBREQUEST_HPP
#define NAZARA_NETWORK_WEBREQUEST_HPP
#include <NazaraUtils/Prerequisites.hpp>
#include <Nazara/Core/Clock.hpp>
#include <Nazara/Network/Config.hpp>
#include <Nazara/Network/Enums.hpp>
#include <Nazara/Network/WebRequestResult.hpp>
@@ -15,7 +17,11 @@
#include <string>
#include <unordered_map>
#ifndef NAZARA_PLATFORM_WEB
struct curl_slist;
#else
struct emscripten_fetch_attr_t;
#endif
namespace Nz
{
@@ -38,10 +44,10 @@ namespace Nz
inline void SetDataCallback(DataCallback callback);
inline void SetHeader(std::string header, std::string value);
void SetJSonContent(std::string_view encodedJSon);
void SetJSonContent(std::string encodedJSon);
void SetMaximumFileSize(UInt64 maxFileSize);
inline void SetResultCallback(ResultCallback callback);
void SetServiceName(const std::string_view& serviceName);
void SetServiceName(std::string serviceName);
void SetURL(const std::string& url);
void SetupGet();
@@ -50,21 +56,36 @@ namespace Nz
WebRequest& operator=(const WebRequest&) = delete;
WebRequest& operator=(WebRequest&&) = default;
static std::unique_ptr<WebRequest> Get(const std::string& url, ResultCallback callback = nullptr);
static std::unique_ptr<WebRequest> Post(const std::string& url, ResultCallback callback = nullptr);
private:
inline bool OnBodyResponse(const char* data, std::size_t length);
#ifndef NAZARA_PLATFORM_WEB
CURL* Prepare();
inline void TriggerCallback();
inline void TriggerCallback(std::string errorMessage);
#else
inline emscripten_fetch_t* GetFetchHandle() const;
inline Nz::Time GetRequestTime() const;
emscripten_fetch_t* Prepare(emscripten_fetch_attr_t* fetchAttr);
inline void StopClock();
#endif
inline void TriggerErrorCallback(std::string errorMessage);
inline void TriggerSuccessCallback();
#ifdef NAZARA_PLATFORM_WEB
std::string m_httpMethod;
std::string m_url;
std::vector<const char*> m_requestHeaders;
#endif
std::string m_content;
std::string m_responseBody;
std::unordered_map<std::string, std::string> m_headers;
WebService& m_webService;
DataCallback m_dataCallback;
#ifndef NAZARA_PLATFORM_WEB
MovablePtr<CURL> m_curlHandle;
MovablePtr<curl_slist> m_headerList;
#else
HighPrecisionClock m_clock;
MovablePtr<emscripten_fetch_t> m_fetchHandle;
#endif
ResultCallback m_resultCallback;
bool m_isUserAgentSet;
};

View File

@@ -32,16 +32,42 @@ namespace Nz
return m_dataCallback(data, length);
}
inline void WebRequest::TriggerCallback()
#ifdef NAZARA_PLATFORM_WEB
inline emscripten_fetch_t* WebRequest::GetFetchHandle() const
{
m_resultCallback(WebRequestResult(m_webService, m_curlHandle.Get(), std::move(m_responseBody)));
m_responseBody.clear();
return m_fetchHandle;
}
inline void WebRequest::TriggerCallback(std::string errorMessage)
inline Time WebRequest::GetRequestTime() const
{
m_resultCallback(WebRequestResult(m_webService, std::move(errorMessage)));
return m_clock.GetElapsedTime();
}
inline void WebRequest::StopClock()
{
m_clock.Pause();
}
#endif
inline void WebRequest::TriggerErrorCallback(std::string errorMessage)
{
#ifndef NAZARA_PLATFORM_WEB
m_resultCallback(WebRequestResult(m_webService, Nz::Err(std::move(errorMessage)), m_curlHandle.Get()));
#else
m_resultCallback(WebRequestResult(m_webService, Nz::Err(std::move(errorMessage)), m_fetchHandle.Get(), m_clock.GetElapsedTime()));
#endif
}
inline void WebRequest::TriggerSuccessCallback()
{
#ifndef NAZARA_PLATFORM_WEB
m_resultCallback(WebRequestResult(m_webService, Nz::Ok(std::move(m_responseBody)), m_curlHandle.Get()));
#else
m_resultCallback(WebRequestResult(m_webService, Nz::Ok(std::move(m_responseBody)), m_fetchHandle.Get(), m_clock.GetElapsedTime()));
#endif
m_responseBody.clear();
}
}
#include <Nazara/Network/DebugOff.hpp>
#include "WebRequest.hpp"

View File

@@ -8,12 +8,18 @@
#define NAZARA_NETWORK_WEBREQUESTRESULT_HPP
#include <NazaraUtils/Prerequisites.hpp>
#include <Nazara/Core/Time.hpp>
#include <Nazara/Network/Config.hpp>
#include <NazaraUtils/MovablePtr.hpp>
#include <NazaraUtils/Result.hpp>
#include <functional>
#include <string>
#ifndef NAZARA_PLATFORM_WEB
using CURL = void;
#else
struct emscripten_fetch_t;
#endif
namespace Nz
{
@@ -30,10 +36,10 @@ namespace Nz
inline std::string& GetBody();
inline const std::string& GetBody() const;
Nz::UInt64 GetDownloadedSize() const;
Nz::UInt64 GetDownloadSpeed() const;
UInt64 GetDownloadedSize() const;
UInt64 GetDownloadSpeed() const;
inline const std::string& GetErrorMessage() const;
long GetReponseCode() const;
UInt32 GetStatusCode() const;
inline bool HasSucceeded() const;
@@ -43,12 +49,23 @@ namespace Nz
WebRequestResult& operator=(WebRequestResult&&) = delete;
private:
inline WebRequestResult(WebService& webService, CURL* curl, std::string body);
inline WebRequestResult(WebService& webService, std::string errMessage);
#ifndef NAZARA_PLATFORM_WEB
inline WebRequestResult(WebService& webService, Result<std::string, std::string>&& bodyResult, CURL* curl);
#else
inline WebRequestResult(WebService& webService, Result<std::string, std::string>&& bodyResult, emscripten_fetch_t* fetchHandle, Time downloadTime);
#endif
#ifndef NAZARA_PLATFORM_WEB
CURL* m_curlHandle;
#else
emscripten_fetch_t* m_fetchHandle;
#endif
WebService& m_webService;
std::string m_bodyOrErr;
Result<std::string, std::string> m_bodyResult;
#ifdef NAZARA_PLATFORM_WEB
Time m_downloadTime;
#endif
};
}

View File

@@ -2,53 +2,55 @@
// This file is part of the "Nazara Engine - Network module"
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Network/Debug.hpp>
#include <cassert>
#include <Nazara/Network/Debug.hpp>
namespace Nz
{
inline WebRequestResult::WebRequestResult(WebService& webService, CURL* curl, std::string body) :
#ifndef NAZARA_PLATFORM_WEB
inline WebRequestResult::WebRequestResult(WebService& webService, Result<std::string, std::string>&& bodyResult, CURL* curl) :
m_curlHandle(curl),
m_webService(webService),
m_bodyOrErr(std::move(body))
m_bodyResult(std::move(bodyResult))
{
}
inline WebRequestResult::WebRequestResult(WebService& webService, std::string errMessage) :
m_curlHandle(nullptr),
#else
inline WebRequestResult::WebRequestResult(WebService& webService, Result<std::string, std::string>&& bodyResult, emscripten_fetch_t* fetchHandle, Time downloadTime) :
m_fetchHandle(fetchHandle),
m_webService(webService),
m_bodyOrErr(std::move(errMessage))
m_bodyResult(std::move(bodyResult)),
m_downloadTime(downloadTime)
{
}
#endif
inline std::string& WebRequestResult::GetBody()
{
assert(HasSucceeded());
return m_bodyOrErr;
return m_bodyResult.GetValue();
}
inline const std::string& WebRequestResult::GetBody() const
{
assert(HasSucceeded());
return m_bodyOrErr;
return m_bodyResult.GetValue();
}
inline const std::string& WebRequestResult::GetErrorMessage() const
{
assert(!HasSucceeded());
return m_bodyOrErr;
return m_bodyResult.GetError();
}
inline bool WebRequestResult::HasSucceeded() const
{
return m_curlHandle != nullptr;
return m_bodyResult.IsOk();
}
inline WebRequestResult::operator bool() const
{
return HasSucceeded();
}
}
#include <Nazara/Network/DebugOff.hpp>

View File

@@ -10,8 +10,12 @@
#include <Nazara/Network/Config.hpp>
#include <Nazara/Network/WebRequest.hpp>
#include <NazaraUtils/MovablePtr.hpp>
#include <unordered_map>
#include <vector>
#ifndef NAZARA_PLATFORM_WEB
using CURLM = void;
#endif
namespace Nz
{
@@ -24,7 +28,11 @@ namespace Nz
friend WebRequestResult;
public:
#ifndef NAZARA_PLATFORM_WEB
WebService(const CurlLibrary& library);
#else
WebService();
#endif
WebService(const WebService&) = delete;
WebService(WebService&&) = delete;
~WebService();
@@ -44,12 +52,25 @@ namespace Nz
WebService& operator=(WebService&&) = delete;
private:
#ifndef NAZARA_PLATFORM_WEB
inline const CurlLibrary& GetCurlLibrary() const;
#endif
std::string m_userAgent;
#ifndef NAZARA_PLATFORM_WEB
std::unordered_map<CURL*, std::unique_ptr<WebRequest>> m_activeRequests;
const CurlLibrary& m_curl;
MovablePtr<CURLM> m_curlMulti;
#else
struct FinishedRequest
{
std::unique_ptr<WebRequest> request;
bool succeeded;
};
std::unordered_map<emscripten_fetch_t*, std::unique_ptr<WebRequest>> m_activeRequests;
std::vector<FinishedRequest> m_finishedRequests;
#endif
};
}

View File

@@ -36,10 +36,12 @@ namespace Nz
return m_userAgent;
}
#ifndef NAZARA_PLATFORM_WEB
const CurlLibrary& WebService::GetCurlLibrary() const
{
return m_curl;
}
#endif
}
#include <Nazara/Network/DebugOff.hpp>