Does not work very well because of CORS restrictions in browsers.legacy
@@ -66,6 +66,7 @@ build/visualstudio/ipch | |||
build/visualstudio/*.log | |||
build/visualstudio/*.XGD | |||
# Emscripten cruft | |||
a.out* | |||
doc/samples/*.html | |||
doc/samples/*.wasm | |||
doc/samples/*.wasm.* | |||
@@ -0,0 +1,55 @@ | |||
// | |||
// Lol Engine — HTTP client sample | |||
// | |||
// Copyright © 2016—2020 Sam Hocevar <sam@hocevar.net> | |||
// | |||
// Lol Engine is free software. It comes without any warranty, to | |||
// the extent permitted by applicable law. You can redistribute it | |||
// and/or modify it under the terms of the Do What the Fuck You Want | |||
// to Public License, Version 2, as published by the WTFPL Task Force. | |||
// See http://www.wtfpl.net/ for more details. | |||
// | |||
#if HAVE_CONFIG_H | |||
# include "config.h" | |||
#endif | |||
#include <lol/engine.h> | |||
class demo : public lol::entity | |||
{ | |||
public: | |||
virtual bool init_game() override | |||
{ | |||
// Choose URL that works with CORS (cross-origin resource sharing) | |||
client.get("https://api.github.com/"); | |||
return true; | |||
} | |||
virtual void tick_game(float seconds) override | |||
{ | |||
entity::tick_game(seconds); | |||
if (client.get_status() == lol::net::http::status::success) | |||
{ | |||
lol::msg::info("Downloaded %d bytes: %s\n", | |||
(int)client.get_result().size(), | |||
client.get_result().c_str()); | |||
client.reset(); | |||
} | |||
} | |||
lol::net::http::client client; | |||
}; | |||
int main(int argc, char **argv) | |||
{ | |||
lol::sys::init(argc, argv); | |||
lol::Application app("Tutorial 17: HTTP", lol::ivec2(800, 600), 60.0f); | |||
auto p = new demo(); | |||
app.Run(); | |||
return 0; | |||
} | |||
@@ -0,0 +1,66 @@ | |||
<?xml version="1.0" encoding="utf-8"?> | |||
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> | |||
<PropertyGroup Label="LolMacros"> | |||
<LolDir Condition="Exists('$(SolutionDir)\lol')">$(SolutionDir)\lol</LolDir> | |||
<LolDir Condition="!Exists('$(SolutionDir)\lol')">$(SolutionDir)</LolDir> | |||
</PropertyGroup> | |||
<ItemGroup Label="ProjectConfigurations"> | |||
<ProjectConfiguration Include="Debug|NX64"> | |||
<Configuration>Debug</Configuration> | |||
<Platform>NX64</Platform> | |||
</ProjectConfiguration> | |||
<ProjectConfiguration Include="Debug|ORBIS"> | |||
<Configuration>Debug</Configuration> | |||
<Platform>ORBIS</Platform> | |||
</ProjectConfiguration> | |||
<ProjectConfiguration Include="Debug|Win32"> | |||
<Configuration>Debug</Configuration> | |||
<Platform>Win32</Platform> | |||
</ProjectConfiguration> | |||
<ProjectConfiguration Include="Debug|x64"> | |||
<Configuration>Debug</Configuration> | |||
<Platform>x64</Platform> | |||
</ProjectConfiguration> | |||
<ProjectConfiguration Include="Release|NX64"> | |||
<Configuration>Release</Configuration> | |||
<Platform>NX64</Platform> | |||
</ProjectConfiguration> | |||
<ProjectConfiguration Include="Release|ORBIS"> | |||
<Configuration>Release</Configuration> | |||
<Platform>ORBIS</Platform> | |||
</ProjectConfiguration> | |||
<ProjectConfiguration Include="Release|Win32"> | |||
<Configuration>Release</Configuration> | |||
<Platform>Win32</Platform> | |||
</ProjectConfiguration> | |||
<ProjectConfiguration Include="Release|x64"> | |||
<Configuration>Release</Configuration> | |||
<Platform>x64</Platform> | |||
</ProjectConfiguration> | |||
</ItemGroup> | |||
<ItemGroup> | |||
<ClCompile Include="17_net.cpp" /> | |||
</ItemGroup> | |||
<Import Project="$(LolDir)\build\msbuild\lol-core.props" /> | |||
<Import Project="$(LolDir)\build\msbuild\lol-bullet.props" /> | |||
<PropertyGroup Label="Globals"> | |||
<ProjectGuid>{46910277-18E3-4151-9AD9-DC5B551772A9}</ProjectGuid> | |||
<ConfigurationType>Application</ConfigurationType> | |||
<Keyword>Win32Proj</Keyword> | |||
</PropertyGroup> | |||
<Import Project="$(LolDir)\build\msbuild\lol.config.props" /> | |||
<ImportGroup Label="ExtensionSettings"> | |||
<Import Project="$(LolDir)\build\msbuild\lolfx.props" /> | |||
</ImportGroup> | |||
<ImportGroup Label="PropertySheets"> | |||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> | |||
<Import Project="$(LolDir)\build\msbuild\lol.vars.props" /> | |||
</ImportGroup> | |||
<PropertyGroup Label="UserMacros" /> | |||
<Import Project="$(LolDir)\build\msbuild\lol.rules.props" /> | |||
<ItemDefinitionGroup /> | |||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> | |||
<ImportGroup Label="ExtensionTargets"> | |||
<Import Project="$(LolDir)\build\msbuild\lolfx.targets" /> | |||
</ImportGroup> | |||
</Project> |
@@ -11,7 +11,7 @@ tutorials += 01_triangle 02_cube 03_noise 04_texture 05_easymesh \ | |||
06_sprite 07_input 08_fbo 09_sound 11_fractal \ | |||
12_voronoi 13_shader_builder 14_lua 15_gui | |||
endif | |||
tutorials += 16_movie | |||
tutorials += 16_movie 17_net | |||
01_triangle_SOURCES = 01_triangle.cpp 01_triangle.lolfx | |||
01_triangle_CPPFLAGS = $(AM_CPPFLAGS) | |||
@@ -81,3 +81,7 @@ endif | |||
16_movie_CPPFLAGS = $(AM_CPPFLAGS) | |||
16_movie_DEPENDENCIES = @LOL_DEPS@ | |||
17_net_SOURCES = 17_net.cpp | |||
17_net_CPPFLAGS = $(AM_CPPFLAGS) | |||
17_net_DEPENDENCIES = @LOL_DEPS@ | |||
@@ -62,6 +62,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "14_lua", "doc\tutorial\14_l | |||
EndProject | |||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "16_movie", "doc\tutorial\16_movie.vcxproj", "{5F5714D0-1C3D-4522-A409-214C5A2951AA}" | |||
EndProject | |||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "17_net", "doc\tutorial\17_net.vcxproj", "{46910277-18E3-4151-9AD9-DC5B551772A9}" | |||
EndProject | |||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "09_sound", "doc\tutorial\09_sound.vcxproj", "{51626A22-DD68-4450-9696-13B03BF7A2C5}" | |||
EndProject | |||
Global | |||
@@ -418,6 +420,22 @@ Global | |||
{5F5714D0-1C3D-4522-A409-214C5A2951AA}.Release|Win32.Build.0 = Release|Win32 | |||
{5F5714D0-1C3D-4522-A409-214C5A2951AA}.Release|Win64.ActiveCfg = Release|x64 | |||
{5F5714D0-1C3D-4522-A409-214C5A2951AA}.Release|Win64.Build.0 = Release|x64 | |||
{46910277-18E3-4151-9AD9-DC5B551772A9}.Debug|NX64.ActiveCfg = Debug|NX64 | |||
{46910277-18E3-4151-9AD9-DC5B551772A9}.Debug|NX64.Build.0 = Debug|NX64 | |||
{46910277-18E3-4151-9AD9-DC5B551772A9}.Debug|ORBIS.ActiveCfg = Debug|ORBIS | |||
{46910277-18E3-4151-9AD9-DC5B551772A9}.Debug|ORBIS.Build.0 = Debug|ORBIS | |||
{46910277-18E3-4151-9AD9-DC5B551772A9}.Debug|Win32.ActiveCfg = Debug|Win32 | |||
{46910277-18E3-4151-9AD9-DC5B551772A9}.Debug|Win32.Build.0 = Debug|Win32 | |||
{46910277-18E3-4151-9AD9-DC5B551772A9}.Debug|Win64.ActiveCfg = Debug|x64 | |||
{46910277-18E3-4151-9AD9-DC5B551772A9}.Debug|Win64.Build.0 = Debug|x64 | |||
{46910277-18E3-4151-9AD9-DC5B551772A9}.Release|NX64.ActiveCfg = Release|NX64 | |||
{46910277-18E3-4151-9AD9-DC5B551772A9}.Release|NX64.Build.0 = Release|NX64 | |||
{46910277-18E3-4151-9AD9-DC5B551772A9}.Release|ORBIS.ActiveCfg = Release|ORBIS | |||
{46910277-18E3-4151-9AD9-DC5B551772A9}.Release|ORBIS.Build.0 = Release|ORBIS | |||
{46910277-18E3-4151-9AD9-DC5B551772A9}.Release|Win32.ActiveCfg = Release|Win32 | |||
{46910277-18E3-4151-9AD9-DC5B551772A9}.Release|Win32.Build.0 = Release|Win32 | |||
{46910277-18E3-4151-9AD9-DC5B551772A9}.Release|Win64.ActiveCfg = Release|x64 | |||
{46910277-18E3-4151-9AD9-DC5B551772A9}.Release|Win64.Build.0 = Release|x64 | |||
{51626A22-DD68-4450-9696-13B03BF7A2C5}.Debug|NX64.ActiveCfg = Debug|NX64 | |||
{51626A22-DD68-4450-9696-13B03BF7A2C5}.Debug|NX64.Build.0 = Debug|NX64 | |||
{51626A22-DD68-4450-9696-13B03BF7A2C5}.Debug|ORBIS.ActiveCfg = Debug|ORBIS | |||
@@ -463,6 +481,7 @@ Global | |||
{81C83B42-D00A-4FA3-9A3D-80F9D46524BF} = {E74CF679-CA2A-47E9-B1F4-3779D6AC6B04} | |||
{31B96262-1C41-43B9-BA38-27AA385B05DB} = {E74CF679-CA2A-47E9-B1F4-3779D6AC6B04} | |||
{5F5714D0-1C3D-4522-A409-214C5A2951AA} = {E74CF679-CA2A-47E9-B1F4-3779D6AC6B04} | |||
{46910277-18E3-4151-9AD9-DC5B551772A9} = {E74CF679-CA2A-47E9-B1F4-3779D6AC6B04} | |||
{51626A22-DD68-4450-9696-13B03BF7A2C5} = {E74CF679-CA2A-47E9-B1F4-3779D6AC6B04} | |||
EndGlobalSection | |||
GlobalSection(ExtensibilityGlobals) = postSolution | |||
@@ -25,15 +25,29 @@ namespace http | |||
class client_impl; | |||
enum class status : uint8_t | |||
{ | |||
ready = 0, | |||
pending = 1, | |||
success = 2, | |||
error = 3, | |||
}; | |||
class client | |||
{ | |||
public: | |||
client(); | |||
~client(); | |||
// Enqueue a query | |||
void get(std::string const &url); | |||
bool is_ready() const; | |||
std::tuple<int, std::string> result(); | |||
// Reset state | |||
void reset(); | |||
// Get status (may be pending) and result | |||
status get_status() const; | |||
std::string const & get_result() const; | |||
private: | |||
std::unique_ptr<client_impl> impl; | |||
@@ -10,10 +10,14 @@ | |||
// See http://www.wtfpl.net/ for more details. | |||
// | |||
#pragma once | |||
#include <lol/engine-internal.h> | |||
#if __EMSCRIPTEN__ | |||
# include <emscripten/fetch.h> | |||
#else | |||
# include <httplib.h> | |||
#endif | |||
namespace lol | |||
{ | |||
@@ -23,22 +27,41 @@ namespace net | |||
namespace http | |||
{ | |||
#if __EMSCRIPTEN__ | |||
class client_impl | |||
{ | |||
// FIXME | |||
}; | |||
#else | |||
class client_impl | |||
{ | |||
public: | |||
#if __EMSCRIPTEN__ | |||
static void on_success(emscripten_fetch_t *fetch) | |||
{ | |||
auto *that = (client_impl *)fetch->userData; | |||
msg::info("finished downloading %llu bytes from URL %s.\n", | |||
fetch->numBytes, fetch->url); | |||
that->m_result.assign(fetch->data, fetch->numBytes); | |||
that->m_status = status::success; | |||
} | |||
static void on_failure(emscripten_fetch_t *fetch) | |||
{ | |||
auto *that = (client_impl *)fetch->userData; | |||
msg::error("downloading %s failed, HTTP failure status code: %d.\n", | |||
fetch->url, fetch->status); | |||
that->m_status = status::error; | |||
} | |||
emscripten_fetch_t *m_fetch = nullptr; | |||
#else | |||
void get(std::string const& url) | |||
{ | |||
} | |||
}; | |||
//httplib::Client &client; | |||
#endif | |||
status m_status; | |||
std::string m_result; | |||
}; | |||
client::client() | |||
: impl(std::make_unique<client_impl>()) | |||
{ | |||
@@ -46,20 +69,41 @@ client::client() | |||
client::~client() | |||
{ | |||
#if __EMSCRIPTEN__ | |||
emscripten_fetch_close(impl->m_fetch); | |||
#endif | |||
} | |||
void client::get(std::string const &url) | |||
{ | |||
impl->m_status = status::pending; | |||
#if __EMSCRIPTEN__ | |||
emscripten_fetch_attr_t attr; | |||
emscripten_fetch_attr_init(&attr); | |||
strcpy(attr.requestMethod, "GET"); | |||
attr.userData = impl.get(); | |||
attr.attributes = EMSCRIPTEN_FETCH_LOAD_TO_MEMORY; | |||
attr.onsuccess = client_impl::on_success; | |||
attr.onerror = client_impl::on_failure; | |||
impl->m_fetch = emscripten_fetch(&attr, url.c_str()); | |||
#else | |||
#endif | |||
} | |||
void client::reset() | |||
{ | |||
impl->m_status = status::ready; | |||
impl->m_result.assign(""); | |||
} | |||
bool client::is_ready() const | |||
status client::get_status() const | |||
{ | |||
return false; | |||
return impl->m_status; | |||
} | |||
std::tuple<int, std::string> client::result() | |||
std::string const & client::get_result() const | |||
{ | |||
return std::make_tuple(404, std::string()); | |||
return impl->m_result; | |||
} | |||
} // namespace http | |||