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 | ||||