Skip to content

Commit 62bed20

Browse files
authored
Merge pull request #691 from triuk/main
Improve directory redirects and strict entry-file handling for root folders and VFS
2 parents 6c3e8fd + ebaab97 commit 62bed20

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

47 files changed

+1735
-332
lines changed

CMakeLists.txt

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,13 +126,15 @@ if (WEBUI_BUILD_EXAMPLES)
126126
add_executable(call_cpp_from_js ${CMAKE_CURRENT_SOURCE_DIR}/examples/C++/call_cpp_from_js/main.cpp)
127127
add_executable(serve_a_folder_cpp ${CMAKE_CURRENT_SOURCE_DIR}/examples/C++/serve_a_folder/main.cpp)
128128
add_executable(virtual_file_system_cpp ${CMAKE_CURRENT_SOURCE_DIR}/examples/C++/virtual_file_system/main.cpp)
129+
add_executable(test_index_redirect_cpp ${CMAKE_CURRENT_SOURCE_DIR}/examples/C++/test_index_redirect/main.cpp)
129130

130131
# C examples
131132
add_executable(minimal_c ${CMAKE_CURRENT_SOURCE_DIR}/examples/C/minimal/main.c)
132133
add_executable(call_js_from_c ${CMAKE_CURRENT_SOURCE_DIR}/examples/C/call_js_from_c/main.c)
133134
add_executable(call_c_from_js ${CMAKE_CURRENT_SOURCE_DIR}/examples/C/call_c_from_js/main.c)
134135
add_executable(serve_a_folder_c ${CMAKE_CURRENT_SOURCE_DIR}/examples/C/serve_a_folder/main.c)
135136
add_executable(virtual_file_system_c ${CMAKE_CURRENT_SOURCE_DIR}/examples/C/virtual_file_system/main.c)
137+
add_executable(test_index_redirect_c ${CMAKE_CURRENT_SOURCE_DIR}/examples/C/test_index_redirect/main.c)
136138
add_executable(public_network_access ${CMAKE_CURRENT_SOURCE_DIR}/examples/C/public_network_access/main.c)
137139
add_executable(web_app_multi_client ${CMAKE_CURRENT_SOURCE_DIR}/examples/C/web_app_multi_client/main.c)
138140
add_executable(chatgpt_api ${CMAKE_CURRENT_SOURCE_DIR}/examples/C/chatgpt_api/main.c)
@@ -146,12 +148,14 @@ if (WEBUI_BUILD_EXAMPLES)
146148
target_link_libraries(call_cpp_from_js webui)
147149
target_link_libraries(serve_a_folder_cpp webui)
148150
target_link_libraries(virtual_file_system_cpp webui)
151+
target_link_libraries(test_index_redirect_cpp webui)
149152

150153
target_link_libraries(minimal_c webui)
151154
target_link_libraries(call_js_from_c webui)
152155
target_link_libraries(call_c_from_js webui)
153156
target_link_libraries(serve_a_folder_c webui)
154157
target_link_libraries(virtual_file_system_c webui)
158+
target_link_libraries(test_index_redirect_c webui)
155159
target_link_libraries(public_network_access webui)
156160
target_link_libraries(web_app_multi_client webui)
157161
target_link_libraries(chatgpt_api webui)
@@ -166,11 +170,13 @@ if (WEBUI_BUILD_EXAMPLES)
166170
set_target_properties(call_cpp_from_js PROPERTIES LINK_FLAGS "/SubSystem:\"Windows\"" VS_DPI_AWARE "ON")
167171
set_target_properties(serve_a_folder_cpp PROPERTIES LINK_FLAGS "/SubSystem:\"Windows\"" VS_DPI_AWARE "ON")
168172
set_target_properties(virtual_file_system_cpp PROPERTIES LINK_FLAGS "/SubSystem:\"Windows\"" VS_DPI_AWARE "ON")
173+
set_target_properties(test_index_redirect_cpp PROPERTIES LINK_FLAGS "/SubSystem:\"Windows\"" VS_DPI_AWARE "ON")
169174
set_target_properties(minimal_c PROPERTIES LINK_FLAGS "/SubSystem:\"Windows\"" VS_DPI_AWARE "ON")
170175
set_target_properties(call_js_from_c PROPERTIES LINK_FLAGS "/SubSystem:\"Windows\"" VS_DPI_AWARE "ON")
171176
set_target_properties(call_c_from_js PROPERTIES LINK_FLAGS "/SubSystem:\"Windows\"" VS_DPI_AWARE "ON")
172177
set_target_properties(serve_a_folder_c PROPERTIES LINK_FLAGS "/SubSystem:\"Windows\"" VS_DPI_AWARE "ON")
173178
set_target_properties(virtual_file_system_c PROPERTIES LINK_FLAGS "/SubSystem:\"Windows\"" VS_DPI_AWARE "ON")
179+
set_target_properties(test_index_redirect_c PROPERTIES LINK_FLAGS "/SubSystem:\"Windows\"" VS_DPI_AWARE "ON")
174180
set_target_properties(public_network_access PROPERTIES LINK_FLAGS "/SubSystem:\"Windows\"" VS_DPI_AWARE "ON")
175181
set_target_properties(web_app_multi_client PROPERTIES LINK_FLAGS "/SubSystem:\"Windows\"" VS_DPI_AWARE "ON")
176182
set_target_properties(chatgpt_api PROPERTIES LINK_FLAGS "/SubSystem:\"Windows\"" VS_DPI_AWARE "ON")

examples/C++/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ The only requirement to build the examples is a a C++11 compiler.
99
- `call_js_from_cpp`: Calls JavaScript from C++ using class methods and member-function bind.
1010
- `serve_a_folder`: Uses WebUI to serve a folder with multiple files (class-based example using member-function bind).
1111
- `virtual_file_system`: Embeds files using a virtual file system.
12+
- `test_index_redirect`: Tests index fallback and custom entry behavior for `/`, `/sub`, and `/sub/foo`.
1213

1314
To build an example, cd into its directory and run the make command.
1415

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
# WebUI C++ Example
2+
3+
# == 1. VARIABLES =============================================================
4+
5+
MAKEFILE_PATH := $(abspath $(lastword $(MAKEFILE_LIST)))
6+
PROJECT_DIR := $(dir $(MAKEFILE_PATH))/../../../
7+
TARGET := $(firstword $(MAKECMDGOALS))
8+
LIB_DIR := $(PROJECT_DIR)/dist
9+
ifeq ($(TARGET), debug)
10+
LIB_DIR := $(LIB_DIR)/debug
11+
endif
12+
INCLUDE_DIR := $(PROJECT_DIR)/include
13+
WEBUI_LIB_NAME = webui-2
14+
ifeq ($(WEBUI_USE_TLS), 1)
15+
WEBUI_LIB_NAME = webui-2-secure
16+
endif
17+
18+
# ARGS
19+
# Set a compiler when running on Linux via `make CC=g++` / `make CC=clang`
20+
CC = g++
21+
# Build the WebUI library if running via `make BUILD_LIB=true`
22+
BUILD_LIB ?=
23+
24+
# BUILD FLAGS
25+
STATIC_BUILD_FLAGS = main.cpp -I"$(INCLUDE_DIR)" -L"$(LIB_DIR)"
26+
DYN_BUILD_FLAGS = main.cpp -I"$(INCLUDE_DIR)" -L"$(LIB_DIR)"
27+
28+
# Platform conditions
29+
ifeq ($(OS),Windows_NT)
30+
# Windows
31+
PLATFORM := windows
32+
SHELL := CMD
33+
STATIC_BUILD_FLAGS += -l$(WEBUI_LIB_NAME)-static -lws2_32 -Wall -luser32 -lstdc++ -luuid -static
34+
COPY_LIB_CMD := @copy "$(LIB_DIR)\$(WEBUI_LIB_NAME).dll" "$(WEBUI_LIB_NAME).dll"
35+
DYN_BUILD_FLAGS += "$(WEBUI_LIB_NAME).dll" -lws2_32 -Wall -luser32 -lstdc++ -luuid
36+
STATIC_OUT := main.exe
37+
DYN_OUT := main-dyn.exe
38+
LWS2_OPT := -lws2_32 -lole32
39+
STRIP_OPT := --strip-all
40+
CONSOLE_APP := -Wl,-subsystem=console
41+
GUI_APP := -Wl,-subsystem=windows
42+
else
43+
STATIC_BUILD_FLAGS += -l$(WEBUI_LIB_NAME)-static -lpthread -lm -ldl
44+
DYN_BUILD_FLAGS += -l$(WEBUI_LIB_NAME) -lpthread -lm -ldl
45+
STATIC_OUT := main
46+
DYN_OUT := main-dyn
47+
ifeq ($(shell uname),Darwin)
48+
# MacOS
49+
PLATFORM := macos
50+
CC = clang
51+
COPY_LIB_CMD := @cp "$(LIB_DIR)/lib$(WEBUI_LIB_NAME).dylib" "lib$(WEBUI_LIB_NAME).dylib"
52+
WKWEBKIT_LINK_FLAGS := -framework Cocoa -framework WebKit
53+
else
54+
# Linux
55+
PLATFORM := linux
56+
COPY_LIB_CMD := @cp "$(LIB_DIR)/lib$(WEBUI_LIB_NAME).so" "lib$(WEBUI_LIB_NAME).so"
57+
STRIP_OPT := --strip-all
58+
ifeq ($(CC),clang)
59+
LLVM_OPT := llvm-
60+
endif
61+
endif
62+
endif
63+
64+
# == 2.TARGETS ================================================================
65+
66+
all: release
67+
68+
debug: --validate-args
69+
ifeq ($(BUILD_LIB),true)
70+
@cd "$(PROJECT_DIR)" && $(MAKE) debug
71+
endif
72+
# Static with Debug info
73+
ifneq ($(WEBUI_USE_TLS), 1)
74+
@echo "Build C++ Example ($(CC) debug static)..."
75+
@$(CC) -g $(CONSOLE_APP) $(STATIC_BUILD_FLAGS) $(LWS2_OPT) $(WKWEBKIT_LINK_FLAGS) -o $(STATIC_OUT)
76+
endif
77+
# Dynamic with Debug info
78+
@echo "Build C++ Example ($(CC) debug dynamic)..."
79+
$(COPY_LIB_CMD)
80+
@$(CC) -g $(CONSOLE_APP) $(DYN_BUILD_FLAGS) $(LWS2_OPT) $(WKWEBKIT_LINK_FLAGS) -o $(DYN_OUT)
81+
# Clean
82+
ifeq ($(PLATFORM),windows)
83+
@- del *.o >nul 2>&1
84+
else
85+
@- rm -f *.o
86+
@- rm -rf *.dSYM # macOS
87+
endif
88+
@echo "Done."
89+
90+
release: --validate-args
91+
ifeq ($(BUILD_LIB),true)
92+
@cd "$(PROJECT_DIR)" && $(MAKE)
93+
endif
94+
# Static Release
95+
ifneq ($(WEBUI_USE_TLS), 1)
96+
@echo "Build C++ Example ($(CC) release static)..."
97+
@$(CC) -Os $(GUI_APP) $(STATIC_BUILD_FLAGS) $(LWS2_OPT) $(WKWEBKIT_LINK_FLAGS) -o $(STATIC_OUT)
98+
@$(LLVM_OPT)strip $(STRIP_OPT) $(STATIC_OUT)
99+
endif
100+
# Dynamic Release
101+
@echo "Build C++ Example ($(CC) release dynamic)..."
102+
$(COPY_LIB_CMD)
103+
@$(CC) $(GUI_APP) $(DYN_BUILD_FLAGS) $(LWS2_OPT) $(WKWEBKIT_LINK_FLAGS) -o $(DYN_OUT)
104+
@$(LLVM_OPT)strip $(STRIP_OPT) $(DYN_OUT)
105+
# Clean
106+
ifeq ($(PLATFORM),windows)
107+
@- del *.o >nul 2>&1
108+
else
109+
@- rm -f *.o
110+
@- rm -rf *.dSYM # macOS
111+
endif
112+
@echo "Done."
113+
114+
clean: --clean-$(PLATFORM)
115+
116+
# INTERNAL TARGETS
117+
118+
--validate-args:
119+
ifneq ($(filter $(CC),g++ clang aarch64-linux-gnu-g++ arm-linux-gnueabihf-g++ musl-g++),$(CC))
120+
$(error Invalid compiler specified: `$(CC)`)
121+
endif
122+
123+
--clean-linux: --clean-unix
124+
125+
--clean-macos: --clean-unix
126+
127+
--clean-unix:
128+
- rm -f *.o
129+
- rm -f *.a
130+
- rm -f *.so
131+
- rm -f *.dylib
132+
- rm -rf *.dSYM
133+
134+
--clean-windows:
135+
- del *.o >nul 2>&1
136+
- del *.dll >nul 2>&1
137+
- del *.a >nul 2>&1
138+
- del *.exe >nul 2>&1
Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
# WebUI C++ Example
2+
# Windows - Microsoft Visual C++
3+
4+
SHELL = CMD
5+
LIB_DIR = ../../../dist
6+
INCLUDE_DIR = ../../../include
7+
WEBUI_LIB_NAME = webui-2
8+
!IF "$(WEBUI_USE_TLS)" == "1"
9+
WEBUI_LIB_NAME = webui-2-secure
10+
!ENDIF
11+
12+
# Build the WebUI library if running `nmake BUILD_LIB=true`
13+
BUILD_LIB =
14+
15+
all: release
16+
17+
debug:
18+
!IF "$(BUILD_LIB)" == "true"
19+
@cd "$(LIB_DIR)" && cd .. && $(MAKE) debug
20+
!ENDIF
21+
# Static with Debug info
22+
!IF "$(WEBUI_USE_TLS)" != "1"
23+
@echo Build C++ Example (Debug Static)...
24+
@cl /Zi /EHsc /std:c++17 main.cpp /I"$(INCLUDE_DIR)" /link /LIBPATH:"$(LIB_DIR)/debug" /SUBSYSTEM:CONSOLE $(WEBUI_LIB_NAME)-static.lib user32.lib Advapi32.lib Shell32.lib Ole32.lib /OUT:main.exe 1>NUL 2>&1
25+
!ENDIF
26+
# Dynamic with Debug info
27+
@echo Build C++ Example (Debug Dynamic)...
28+
@copy "$(LIB_DIR)\debug\$(WEBUI_LIB_NAME).dll" "$(WEBUI_LIB_NAME).dll"
29+
@cl /Zi /EHsc /std:c++17 main.cpp /I"$(INCLUDE_DIR)" /link /LIBPATH:"$(LIB_DIR)/debug" /SUBSYSTEM:CONSOLE $(WEBUI_LIB_NAME).lib user32.lib Advapi32.lib Shell32.lib Ole32.lib /OUT:main-dyn.exe 1>NUL 2>&1
30+
# Clean
31+
@- del *.exp >nul 2>&1
32+
@- del *.ilk >nul 2>&1
33+
@- del *.lib >nul 2>&1
34+
@- del *.obj >nul 2>&1
35+
@- del *.pdb >nul 2>&1
36+
@echo Done.
37+
38+
release:
39+
!IF "$(BUILD_LIB)" == "true"
40+
@cd "$(LIB_DIR)" && cd .. && $(MAKE)
41+
!ENDIF
42+
# Static Release
43+
!IF "$(WEBUI_USE_TLS)" != "1"
44+
@echo Build C++ Example (Release Static)...
45+
@cl /EHsc /std:c++17 main.cpp /I"$(INCLUDE_DIR)" /link /LIBPATH:"$(LIB_DIR)" /SUBSYSTEM:WINDOWS $(WEBUI_LIB_NAME)-static.lib user32.lib Advapi32.lib Shell32.lib Ole32.lib /OUT:main.exe 1>NUL 2>&1
46+
!ENDIF
47+
# Dynamic Release
48+
@echo Build C++ Example (Release Dynamic)...
49+
@copy "$(LIB_DIR)\$(WEBUI_LIB_NAME).dll" "$(WEBUI_LIB_NAME).dll"
50+
@cl /EHsc /std:c++17 main.cpp /I"$(INCLUDE_DIR)" /link /LIBPATH:"$(LIB_DIR)" /SUBSYSTEM:WINDOWS $(WEBUI_LIB_NAME).lib user32.lib Advapi32.lib Shell32.lib Ole32.lib /OUT:main-dyn.exe 1>NUL 2>&1
51+
# Clean
52+
@- del *.exp >nul 2>&1
53+
@- del *.ilk >nul 2>&1
54+
@- del *.lib >nul 2>&1
55+
@- del *.obj >nul 2>&1
56+
@- del *.pdb >nul 2>&1
57+
@echo Done.
58+
59+
clean:
60+
- del *.obj >nul 2>&1
61+
- del *.ilk >nul 2>&1
62+
- del *.pdb >nul 2>&1
63+
- del *.exp >nul 2>&1
64+
- del *.exe >nul 2>&1
65+
- del *.lib >nul 2>&1
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
#include "webui.hpp"
2+
#include "vfs.h"
3+
4+
// This example is used to verify redirect and fallback behavior for:
5+
// /, /sub, /sub/foo
6+
// in both storage modes:
7+
// 1) set_root_folder(...)
8+
// 2) set_file_handler(vfs)
9+
//
10+
// Server mode is the primary redirect test path because it exposes the raw
11+
// HTTP behavior (302 Location targets) without mixing in window lifecycle.
12+
//
13+
// The expected server behavior is:
14+
// - start_server("custom.html") prefers custom.html in every directory
15+
// - an explicit filename is strict; if it does not exist, the request fails
16+
// - start_server() or start_server("") means "fallback mode", which probes
17+
// index.html, index.htm, index.ts, then index.js
18+
//
19+
// Note: index.ts and index.js can still be valid fallback targets for
20+
// runtime/script-first scenarios, but they are not equivalent to an HTML GUI
21+
// entry page. For normal GUI testing, HTML/HTM are the page-like entries.
22+
int main(int argc, char *argv[])
23+
{
24+
bool serverMode = false;
25+
bool vfsEnabled = false;
26+
for (int i = 1; i < argc; ++i)
27+
{
28+
if (std::string(argv[i]) == "--server")
29+
{
30+
serverMode = true;
31+
}
32+
else if (std::string(argv[i]) == "--vfs")
33+
{
34+
vfsEnabled = true;
35+
}
36+
}
37+
38+
webui::window window_;
39+
webui::set_config(use_cookies, false);
40+
41+
if (vfsEnabled)
42+
{
43+
window_.set_file_handler(vfs);
44+
}
45+
else
46+
{
47+
window_.set_root_folder("/home/gordon/Dokumenty/PlatformIO/Projects/webui/examples/C++/test_index_redirect/ui/");
48+
49+
// Absolute paths:
50+
// window_.set_root_folder("/path/to/ui/");
51+
// window_.set_root_folder("/path/to/ui");
52+
53+
// Relative if ui folder is next to executable:
54+
// window_.set_root_folder("ui/");
55+
// window_.set_root_folder("ui");
56+
}
57+
58+
if (serverMode)
59+
{
60+
window_.set_port(8080);
61+
62+
// Explicit custom entry file:
63+
window_.start_server("custom.html");
64+
65+
// Redirect to the hardcoded index.* fallback list:
66+
// window_.start_server();
67+
68+
}
69+
else
70+
{
71+
// Explicit custom entry file:
72+
window_.show("custom.html");
73+
// window_.show_browser("custom.html"); // AnyBrowser is the default second argument in C++.
74+
75+
// Redirect to the hardcoded index.* fallback list:
76+
// window_.show();
77+
// window_.show_browser();
78+
}
79+
80+
webui::wait();
81+
82+
return 0;
83+
}
84+
85+
#if defined(_MSC_VER)
86+
int APIENTRY WinMain(HINSTANCE hInst, HINSTANCE hInstPrev, PSTR cmdline, int cmdshow) { return main(__argc, __argv); }
87+
#endif
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<!doctype html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="utf-8" />
5+
<meta name="viewport" content="width=device-width, initial-scale=1" />
6+
<title>ui/custom.html</title>
7+
</head>
8+
<body>
9+
<h1>ui/custom.html</h1>
10+
<p>IDENTIFIER: ui/custom.html</p>
11+
<p>Directory routes: <a href="/">/</a> | <a href="/sub">/sub</a> | <a href="/sub/foo">/sub/foo</a></p>
12+
<h2>All test files</h2>
13+
<ul>
14+
<li><a href="/custom.html">/custom.html</a></li>
15+
<li><a href="/index.html">/index.html</a></li>
16+
<li><a href="/index.css">/index.css</a></li>
17+
<li><a href="/index.js">/index.js</a></li>
18+
<li><a href="/sub/custom.html">/sub/custom.html</a></li>
19+
<li><a href="/sub/index.html">/sub/index.html</a></li>
20+
<li><a href="/sub/index.css">/sub/index.css</a></li>
21+
<li><a href="/sub/index.js">/sub/index.js</a></li>
22+
<li><a href="/sub/foo/custom.html">/sub/foo/custom.html</a></li>
23+
<li><a href="/sub/foo/index.html">/sub/foo/index.html</a></li>
24+
<li><a href="/sub/foo/index.css">/sub/foo/index.css</a></li>
25+
<li><a href="/sub/foo/index.js">/sub/foo/index.js</a></li>
26+
</ul>
27+
<script src="/webui.js"></script>
28+
</body>
29+
</html>
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
/* IDENTIFIER: ui/index.css */
2+
/* Directory routes: / | /sub | /sub/foo */
3+
/* All files: /custom.html /index.html /index.css /index.js /sub/custom.html /sub/index.html /sub/index.css /sub/index.js /sub/foo/custom.html /sub/foo/index.html /sub/foo/index.css /sub/foo/index.js */
4+
body { font-family: monospace; }

0 commit comments

Comments
 (0)