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

@@ -3,12 +3,20 @@
// For conditions of distribution and use, see copyright notice in Config.hpp
#include <Nazara/Network/WebRequest.hpp>
#include <Nazara/Network/CurlLibrary.hpp> //< include last because of curl/curl.h
#include <Nazara/Network/WebService.hpp>
#include <cstring>
#ifndef NAZARA_PLATFORM_WEB
#include <Nazara/Network/CurlLibrary.hpp>
#else
#include <emscripten/fetch.h>
#endif
#include <Nazara/Network/Debug.hpp>
namespace Nz
{
#ifndef NAZARA_PLATFORM_WEB
WebRequest::WebRequest(WebService& webService) :
m_webService(webService),
m_isUserAgentSet(false)
@@ -17,17 +25,30 @@ namespace Nz
m_curlHandle = libcurl.easy_init();
}
#else
WebRequest::WebRequest(WebService& webService) :
m_webService(webService),
m_isUserAgentSet(false)
{
}
#endif
WebRequest::~WebRequest()
{
#ifndef NAZARA_PLATFORM_WEB
auto& libcurl = m_webService.GetCurlLibrary();
if (m_curlHandle)
libcurl.easy_cleanup(m_curlHandle);
if (m_headerList)
libcurl.slist_free_all(m_headerList);
#else
if (m_fetchHandle)
emscripten_fetch_close(m_fetchHandle);
#endif
}
#ifndef NAZARA_PLATFORM_WEB
void WebRequest::ForceProtocol(Nz::NetProtocol protocol)
{
assert(protocol != Nz::NetProtocol::Unknown);
@@ -51,28 +72,43 @@ namespace Nz
break;
}
}
void WebRequest::SetJSonContent(std::string_view encodedJSon)
#else
void WebRequest::ForceProtocol(Nz::NetProtocol /*protocol*/)
{
auto& libcurl = m_webService.GetCurlLibrary();
// Ignored
}
#endif
void WebRequest::SetJSonContent(std::string encodedJSon)
{
SetHeader("Content-Type", "application/json");
libcurl.easy_setopt(m_curlHandle, CURLOPT_POSTFIELDSIZE_LARGE, curl_off_t(encodedJSon.size()));
libcurl.easy_setopt(m_curlHandle, CURLOPT_COPYPOSTFIELDS, encodedJSon.data());
m_content = std::move(encodedJSon);
#ifndef NAZARA_PLATFORM_WEB
auto& libcurl = m_webService.GetCurlLibrary();
libcurl.easy_setopt(m_curlHandle, CURLOPT_POSTFIELDSIZE_LARGE, SafeCast<curl_off_t>(m_content.size()));
libcurl.easy_setopt(m_curlHandle, CURLOPT_POSTFIELDS, m_content.data());
#endif
}
void WebRequest::SetMaximumFileSize(Nz::UInt64 maxFileSize)
#ifndef NAZARA_PLATFORM_WEB
void WebRequest::SetMaximumFileSize(UInt64 maxFileSize)
{
auto& libcurl = m_webService.GetCurlLibrary();
curl_off_t maxSize = maxFileSize;
curl_off_t maxSize = SafeCast<curl_off_t>(maxFileSize);
libcurl.easy_setopt(m_curlHandle, CURLOPT_MAXFILESIZE_LARGE, maxSize);
}
void WebRequest::SetServiceName(const std::string_view& serviceName)
#else
void WebRequest::SetMaximumFileSize(UInt64 maxFileSize)
{
auto& libcurl = m_webService.GetCurlLibrary();
// TODO: Implement using EMSCRIPTEN_FETCH_STREAM_DATA
}
#endif
void WebRequest::SetServiceName(std::string serviceName)
{
if (!serviceName.empty())
{
//TODO Nz::StackString?
@@ -81,37 +117,50 @@ namespace Nz
userAgent.append(" - ");
userAgent.append(serviceName.data(), serviceName.size());
libcurl.easy_setopt(m_curlHandle, CURLOPT_USERAGENT, userAgent.data());
SetHeader("User-Agent", std::move(userAgent));
}
else
libcurl.easy_setopt(m_curlHandle, CURLOPT_USERAGENT, m_webService.GetUserAgent().c_str());
SetHeader("User-Agent", m_webService.GetUserAgent());
m_isUserAgentSet = true;
}
void WebRequest::SetURL(const std::string& url)
{
#ifndef NAZARA_PLATFORM_WEB
auto& libcurl = m_webService.GetCurlLibrary();
libcurl.easy_setopt(m_curlHandle, CURLOPT_URL, url.data());
#else
m_url = url;
#endif
}
void WebRequest::SetupGet()
{
#ifndef NAZARA_PLATFORM_WEB
auto& libcurl = m_webService.GetCurlLibrary();
libcurl.easy_setopt(m_curlHandle, CURLOPT_HTTPGET, long(1));
#else
m_httpMethod = "GET";
#endif
}
void WebRequest::SetupPost()
{
#ifndef NAZARA_PLATFORM_WEB
auto& libcurl = m_webService.GetCurlLibrary();
libcurl.easy_setopt(m_curlHandle, CURLOPT_POST, long(1));
#else
m_httpMethod = "POST";
#endif
}
#ifndef NAZARA_PLATFORM_WEB
CURL* WebRequest::Prepare()
{
if (!m_isUserAgentSet)
SetHeader("User-Agent", m_webService.GetUserAgent());
auto& libcurl = m_webService.GetCurlLibrary();
if (!m_headers.empty())
@@ -126,8 +175,41 @@ namespace Nz
}
if (!m_isUserAgentSet)
libcurl.easy_setopt(m_curlHandle, CURLOPT_USERAGENT, m_webService.GetUserAgent().c_str());
SetHeader("User-Agent", m_webService.GetUserAgent());
return m_curlHandle;
}
#else
emscripten_fetch_t* WebRequest::Prepare(emscripten_fetch_attr_t* fetchAttr)
{
if (!m_isUserAgentSet)
SetHeader("User-Agent", m_webService.GetUserAgent());
if (m_httpMethod.size() >= Nz::CountOf(fetchAttr->requestMethod))
throw std::runtime_error("request method is too big");
if (m_url.empty())
throw std::runtime_error("no url set");
std::strcpy(fetchAttr->requestMethod, m_httpMethod.c_str());
fetchAttr->requestData = m_content.data();
fetchAttr->requestDataSize = m_content.size();
if (!m_requestHeaders.empty())
{
for (auto&& [header, value] : m_headers)
{
m_requestHeaders.push_back(header.c_str());
m_requestHeaders.push_back(value.c_str());
}
m_requestHeaders.push_back(nullptr);
fetchAttr->requestHeaders = m_requestHeaders.data();
}
m_fetchHandle = emscripten_fetch(fetchAttr, m_url.c_str());
return m_fetchHandle;
}
#endif
}