Does not work very well because of CORS restrictions in browsers.legacy
@@ -66,6 +66,7 @@ build/visualstudio/ipch | |||||
build/visualstudio/*.log | build/visualstudio/*.log | ||||
build/visualstudio/*.XGD | build/visualstudio/*.XGD | ||||
# Emscripten cruft | # Emscripten cruft | ||||
a.out* | |||||
doc/samples/*.html | doc/samples/*.html | ||||
doc/samples/*.wasm | doc/samples/*.wasm | ||||
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 \ | 06_sprite 07_input 08_fbo 09_sound 11_fractal \ | ||||
12_voronoi 13_shader_builder 14_lua 15_gui | 12_voronoi 13_shader_builder 14_lua 15_gui | ||||
endif | endif | ||||
tutorials += 16_movie | |||||
tutorials += 16_movie 17_net | |||||
01_triangle_SOURCES = 01_triangle.cpp 01_triangle.lolfx | 01_triangle_SOURCES = 01_triangle.cpp 01_triangle.lolfx | ||||
01_triangle_CPPFLAGS = $(AM_CPPFLAGS) | 01_triangle_CPPFLAGS = $(AM_CPPFLAGS) | ||||
@@ -81,3 +81,7 @@ endif | |||||
16_movie_CPPFLAGS = $(AM_CPPFLAGS) | 16_movie_CPPFLAGS = $(AM_CPPFLAGS) | ||||
16_movie_DEPENDENCIES = @LOL_DEPS@ | 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 | EndProject | ||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "16_movie", "doc\tutorial\16_movie.vcxproj", "{5F5714D0-1C3D-4522-A409-214C5A2951AA}" | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "16_movie", "doc\tutorial\16_movie.vcxproj", "{5F5714D0-1C3D-4522-A409-214C5A2951AA}" | ||||
EndProject | 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}" | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "09_sound", "doc\tutorial\09_sound.vcxproj", "{51626A22-DD68-4450-9696-13B03BF7A2C5}" | ||||
EndProject | EndProject | ||||
Global | Global | ||||
@@ -418,6 +420,22 @@ Global | |||||
{5F5714D0-1C3D-4522-A409-214C5A2951AA}.Release|Win32.Build.0 = Release|Win32 | {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.ActiveCfg = Release|x64 | ||||
{5F5714D0-1C3D-4522-A409-214C5A2951AA}.Release|Win64.Build.0 = 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.ActiveCfg = Debug|NX64 | ||||
{51626A22-DD68-4450-9696-13B03BF7A2C5}.Debug|NX64.Build.0 = Debug|NX64 | {51626A22-DD68-4450-9696-13B03BF7A2C5}.Debug|NX64.Build.0 = Debug|NX64 | ||||
{51626A22-DD68-4450-9696-13B03BF7A2C5}.Debug|ORBIS.ActiveCfg = Debug|ORBIS | {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} | {81C83B42-D00A-4FA3-9A3D-80F9D46524BF} = {E74CF679-CA2A-47E9-B1F4-3779D6AC6B04} | ||||
{31B96262-1C41-43B9-BA38-27AA385B05DB} = {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} | {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} | {51626A22-DD68-4450-9696-13B03BF7A2C5} = {E74CF679-CA2A-47E9-B1F4-3779D6AC6B04} | ||||
EndGlobalSection | EndGlobalSection | ||||
GlobalSection(ExtensibilityGlobals) = postSolution | GlobalSection(ExtensibilityGlobals) = postSolution | ||||
@@ -25,15 +25,29 @@ namespace http | |||||
class client_impl; | class client_impl; | ||||
enum class status : uint8_t | |||||
{ | |||||
ready = 0, | |||||
pending = 1, | |||||
success = 2, | |||||
error = 3, | |||||
}; | |||||
class client | class client | ||||
{ | { | ||||
public: | public: | ||||
client(); | client(); | ||||
~client(); | ~client(); | ||||
// Enqueue a query | |||||
void get(std::string const &url); | 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: | private: | ||||
std::unique_ptr<client_impl> impl; | std::unique_ptr<client_impl> impl; | ||||
@@ -10,10 +10,14 @@ | |||||
// See http://www.wtfpl.net/ for more details. | // See http://www.wtfpl.net/ for more details. | ||||
// | // | ||||
#pragma once | |||||
#include <lol/engine-internal.h> | #include <lol/engine-internal.h> | ||||
#if __EMSCRIPTEN__ | |||||
# include <emscripten/fetch.h> | |||||
#else | |||||
# include <httplib.h> | |||||
#endif | |||||
namespace lol | namespace lol | ||||
{ | { | ||||
@@ -23,22 +27,41 @@ namespace net | |||||
namespace http | namespace http | ||||
{ | { | ||||
#if __EMSCRIPTEN__ | |||||
class client_impl | |||||
{ | |||||
// FIXME | |||||
}; | |||||
#else | |||||
class client_impl | class client_impl | ||||
{ | { | ||||
public: | 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) | void get(std::string const& url) | ||||
{ | { | ||||
} | } | ||||
}; | |||||
//httplib::Client &client; | |||||
#endif | #endif | ||||
status m_status; | |||||
std::string m_result; | |||||
}; | |||||
client::client() | client::client() | ||||
: impl(std::make_unique<client_impl>()) | : impl(std::make_unique<client_impl>()) | ||||
{ | { | ||||
@@ -46,20 +69,41 @@ client::client() | |||||
client::~client() | client::~client() | ||||
{ | { | ||||
#if __EMSCRIPTEN__ | |||||
emscripten_fetch_close(impl->m_fetch); | |||||
#endif | |||||
} | } | ||||
void client::get(std::string const &url) | 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 | } // namespace http | ||||