mirror of
https://github.com/Rain-kl/OpenFlare.git
synced 2026-10-06 23:56:37 +08:00
feat(option): add sw offline
fix(openresty): scope sw injection per cert partition fix(lint): satisfy revive and biome format for sw offline feature docs: sw offline scope changelog fix(frontend): use scoped query key for sw scope zones fix(frontend): hide preview link in sw contact page editor feat(frontend): add sw scope domain picker and contact page fields refactor(frontend): generalize html editor workspace for reuse feat(openresty): scope sw offline injection by route domains feat(openresty): add sw offline domains snapshot field feat(option): add sw offline domains scope option docs: fill html editor workspace generalization detail docs: sw offline scope implementation plan docs: sw offline scope design test(openresty): assert single merged access block in sw enabled servers fix(openresty): restrict sw intercept to https server blocks fix(openresty): version sw offline cache by html content fix(agent): escape redir in sw challenge page to prevent xss fix(agent): return sw.runtime module table and add lua spec docs: sw offline fallback changelog fix(frontend): memoize option map to preserve unsaved contact page edits feat(frontend): add response pages module with contact page tab feat(agent): ship sw offline lua assets and placeholder substitution feat(config): wire sw offline options into config snapshot feat(openresty): render sw offline assets and challenge intercept feat(openresty): add sw offline ConfigSnapshot fields and placeholder feat(db): seed sw offline options feat(option): add sw offline config keys and validation docs: add service worker offline fallback implementation plan docs: adopt global-option pattern for SW offline fallback (matches origin error page) docs: unify offline contact page with error pages as response pages docs: service worker offline fallback design (issue #23)
This commit is contained in:
@@ -337,6 +337,85 @@ func TestManagerApplyWritesSupportFilesAndReplacesPlaceholder(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestManagerApplyShipsSWAssetsAndReplacesSWDirPlaceholder(t *testing.T) {
|
||||
tempDir := t.TempDir()
|
||||
manager := &Manager{
|
||||
MainConfigPath: filepath.Join(tempDir, "nginx.conf"),
|
||||
RouteConfigPath: filepath.Join(tempDir, "routes.conf"),
|
||||
CertDir: filepath.Join(tempDir, "certs"),
|
||||
NginxCertDir: "/etc/nginx/openflare-certs",
|
||||
LuaDir: filepath.Join(tempDir, "lua"),
|
||||
NginxLuaDir: "/etc/nginx/openflare-lua",
|
||||
Executor: &fakeExecutor{},
|
||||
}
|
||||
|
||||
outcome := manager.Apply(
|
||||
context.Background(),
|
||||
"include __OPENFLARE_ROUTE_CONFIG__;",
|
||||
"alias __OPENFLARE_SW_DIR__/sw.js;\nalias __OPENFLARE_SW_DIR__/offline.html;\ncontent_by_lua_file __OPENFLARE_SW_DIR__/challenge.lua;\nrequire(\"__OPENFLARE_LUA_DIR__\")",
|
||||
[]protocol.SupportFile{
|
||||
{Path: "sw/sw.js", Content: "js"},
|
||||
{Path: "sw/offline.html", Content: "html"},
|
||||
},
|
||||
)
|
||||
if outcome.Status != ApplyStatusSuccess {
|
||||
t.Fatalf("Apply failed: %#v", outcome)
|
||||
}
|
||||
|
||||
routeData, err := os.ReadFile(manager.RouteConfigPath)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to read route config: %v", err)
|
||||
}
|
||||
rendered := string(routeData)
|
||||
for _, want := range []string{
|
||||
"/etc/nginx/openflare-certs/sw/sw.js",
|
||||
"/etc/nginx/openflare-certs/sw/offline.html",
|
||||
"/etc/nginx/openflare-certs/sw/challenge.lua",
|
||||
} {
|
||||
if !strings.Contains(rendered, want) {
|
||||
t.Fatalf("route config missing %q, got %s", want, rendered)
|
||||
}
|
||||
}
|
||||
if strings.Contains(rendered, openrestyrender.SWDirPlaceholder) {
|
||||
t.Fatalf("route config still contains SW dir placeholder: %s", rendered)
|
||||
}
|
||||
|
||||
for _, path := range []string{
|
||||
filepath.Join(manager.CertDir, "sw", "sw.js"),
|
||||
filepath.Join(manager.CertDir, "sw", "offline.html"),
|
||||
filepath.Join(manager.CertDir, "sw", "challenge.lua"),
|
||||
filepath.Join(manager.CertDir, "sw", "runtime.lua"),
|
||||
} {
|
||||
if _, err := os.Stat(path); err != nil {
|
||||
t.Fatalf("expected SW asset %s to exist: %v", path, err)
|
||||
}
|
||||
}
|
||||
for _, path := range []string{
|
||||
filepath.Join(manager.LuaDir, "sw", "challenge.lua"),
|
||||
filepath.Join(manager.LuaDir, "sw", "runtime.lua"),
|
||||
} {
|
||||
if _, err := os.Stat(path); err != nil {
|
||||
t.Fatalf("expected SW lua asset %s to exist: %v", path, err)
|
||||
}
|
||||
}
|
||||
|
||||
checksum, err := manager.CurrentChecksum()
|
||||
if err != nil {
|
||||
t.Fatalf("CurrentChecksum failed: %v", err)
|
||||
}
|
||||
expected := bundleChecksum(
|
||||
"include __OPENFLARE_ROUTE_CONFIG__;",
|
||||
"alias __OPENFLARE_SW_DIR__/sw.js;\nalias __OPENFLARE_SW_DIR__/offline.html;\ncontent_by_lua_file __OPENFLARE_SW_DIR__/challenge.lua;\nrequire(\"__OPENFLARE_LUA_DIR__\")",
|
||||
[]protocol.SupportFile{
|
||||
{Path: "sw/sw.js", Content: "js"},
|
||||
{Path: "sw/offline.html", Content: "html"},
|
||||
},
|
||||
)
|
||||
if checksum != expected {
|
||||
t.Fatalf("unexpected checksum: got %s want %s", checksum, expected)
|
||||
}
|
||||
}
|
||||
|
||||
func TestManagerRenderMainConfigInitializesWAFRuntimeInWorker(t *testing.T) {
|
||||
manager := &Manager{NginxLuaDir: "/etc/nginx/openflare-lua"}
|
||||
rendered := manager.renderMainConfig("events {}\nhttp {\n lua_shared_dict openflare_waf_config 1m;\n server {}\n}\n")
|
||||
|
||||
Reference in New Issue
Block a user