mirror of
https://github.com/Rain-kl/OpenFlare.git
synced 2026-09-29 14:06:36 +08:00
feat(openresty): render origin error page directives
Wire origin error page into OpenResty proxy route rendering: ConfigSnapshot fields, default HTML template SupportFile, proxy_intercept_errors + error_page with status-preserving internal Lua location, and Agent placeholder substitution for __OPENFLARE_ERROR_PAGE_TMPL__. Pages routes are excluded.
This commit is contained in:
@@ -522,6 +522,9 @@ func (m *Manager) CurrentChecksum() (string, error) {
|
||||
}
|
||||
normalizedRoute := string(data)
|
||||
if m.NginxCertDir != "" {
|
||||
// Longer error-page path must be restored before the cert-dir prefix rewrite.
|
||||
errorPagePath := filepath.ToSlash(filepath.Join(m.NginxCertDir, openrestyrender.OriginErrorPageSupportPath))
|
||||
normalizedRoute = strings.ReplaceAll(normalizedRoute, errorPagePath, openrestyrender.ErrorPageTmplPlaceholder)
|
||||
normalizedRoute = strings.ReplaceAll(normalizedRoute, m.NginxCertDir, openrestyrender.CertDirPlaceholder)
|
||||
}
|
||||
if luaDir := m.luaRuntimePath(); luaDir != "" {
|
||||
@@ -1375,6 +1378,8 @@ func (m *Manager) renderRouteConfig(content string) string {
|
||||
rendered := content
|
||||
if m.NginxCertDir != "" {
|
||||
rendered = strings.ReplaceAll(rendered, openrestyrender.CertDirPlaceholder, m.NginxCertDir)
|
||||
errorPagePath := filepath.ToSlash(filepath.Join(m.NginxCertDir, openrestyrender.OriginErrorPageSupportPath))
|
||||
rendered = strings.ReplaceAll(rendered, openrestyrender.ErrorPageTmplPlaceholder, errorPagePath)
|
||||
}
|
||||
if luaDir := m.luaRuntimePath(); luaDir != "" {
|
||||
rendered = strings.ReplaceAll(rendered, openrestyrender.LuaDirPlaceholder, luaDir)
|
||||
|
||||
@@ -15,6 +15,7 @@ import (
|
||||
|
||||
"github.com/Rain-kl/Wavelet/internal/apps/agent/protocol"
|
||||
sharedprotocol "github.com/Rain-kl/Wavelet/pkg/protocol"
|
||||
openrestyrender "github.com/Rain-kl/Wavelet/pkg/render/openresty"
|
||||
)
|
||||
|
||||
type runCall struct {
|
||||
@@ -299,13 +300,17 @@ func TestManagerApplyWritesSupportFilesAndReplacesPlaceholder(t *testing.T) {
|
||||
if !strings.Contains(string(routeData), "/etc/nginx/openflare-certs/1.crt") {
|
||||
t.Fatalf("expected placeholder replacement in route config, got %s", string(routeData))
|
||||
}
|
||||
renderedRoute := manager.renderRouteConfig("access_by_lua_file __OPENFLARE_LUA_DIR__/pow/check.lua;\nlocation /.within.website/x/cmd/anubis/static/ { alias __OPENFLARE_POW_STATIC_DIR__/; }\n")
|
||||
renderedRoute := manager.renderRouteConfig("access_by_lua_file __OPENFLARE_LUA_DIR__/pow/check.lua;\nlocation /.within.website/x/cmd/anubis/static/ { alias __OPENFLARE_POW_STATIC_DIR__/; }\nio.open(\"__OPENFLARE_ERROR_PAGE_TMPL__\", \"r\")\n")
|
||||
if !strings.Contains(renderedRoute, "access_by_lua_file /etc/nginx/openflare-lua/pow/check.lua;") {
|
||||
t.Fatalf("expected lua dir placeholder replacement in route config, got %s", renderedRoute)
|
||||
}
|
||||
if !strings.Contains(renderedRoute, "alias /etc/nginx/openflare-lua/pow/static/;") {
|
||||
t.Fatalf("expected pow static dir placeholder replacement in route config, got %s", renderedRoute)
|
||||
}
|
||||
wantErrorPagePath := filepath.ToSlash(filepath.Join(manager.NginxCertDir, openrestyrender.OriginErrorPageSupportPath))
|
||||
if !strings.Contains(renderedRoute, `io.open("`+wantErrorPagePath+`", "r")`) {
|
||||
t.Fatalf("expected error page template placeholder replacement, got %s", renderedRoute)
|
||||
}
|
||||
mainData, err := os.ReadFile(manager.MainConfigPath)
|
||||
if err != nil {
|
||||
t.Fatalf("failed to read main config: %v", err)
|
||||
|
||||
@@ -0,0 +1,172 @@
|
||||
package openresty
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const (
|
||||
// OriginErrorPageSupportPath is the SupportFile path for the origin error HTML template.
|
||||
OriginErrorPageSupportPath = "error_pages/origin_error.html.tmpl"
|
||||
|
||||
// OriginErrorPageInternalLocation is the internal nginx location that serves the error body.
|
||||
OriginErrorPageInternalLocation = "/__openflare_origin_error"
|
||||
|
||||
defaultOriginErrorPageStatusTag = "500-599"
|
||||
)
|
||||
|
||||
// DefaultOriginErrorPageHTML is the built-in Cloudflare-style origin error page.
|
||||
// Placeholders {{status}} and {{host}} are substituted at request time by Lua.
|
||||
const DefaultOriginErrorPageHTML = `<!DOCTYPE html>
|
||||
<html lang="zh-CN">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>{{status}} | 源站暂时无法提供服务</title>
|
||||
<style>
|
||||
:root { color-scheme: light dark; }
|
||||
* { box-sizing: border-box; }
|
||||
body {
|
||||
margin: 0;
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, "Noto Sans", sans-serif;
|
||||
background: #f6f7f9;
|
||||
color: #1f2937;
|
||||
}
|
||||
@media (prefers-color-scheme: dark) {
|
||||
body { background: #0f1419; color: #e5e7eb; }
|
||||
.card { background: #1a2332; border-color: #2d3a4d; box-shadow: none; }
|
||||
.status { color: #f3f4f6; }
|
||||
.muted { color: #9ca3af; }
|
||||
.host { background: #243044; color: #d1d5db; }
|
||||
}
|
||||
.card {
|
||||
width: min(32rem, calc(100% - 2rem));
|
||||
padding: 2.5rem 2rem;
|
||||
border-radius: 12px;
|
||||
background: #fff;
|
||||
border: 1px solid #e5e7eb;
|
||||
box-shadow: 0 10px 30px rgba(15, 23, 42, 0.06);
|
||||
text-align: center;
|
||||
}
|
||||
.status {
|
||||
margin: 0;
|
||||
font-size: clamp(3.5rem, 12vw, 5.5rem);
|
||||
font-weight: 700;
|
||||
letter-spacing: -0.04em;
|
||||
line-height: 1;
|
||||
color: #111827;
|
||||
}
|
||||
h1 {
|
||||
margin: 1rem 0 0.5rem;
|
||||
font-size: 1.25rem;
|
||||
font-weight: 600;
|
||||
}
|
||||
p { margin: 0.4rem 0; line-height: 1.6; }
|
||||
.muted { color: #6b7280; font-size: 0.95rem; }
|
||||
.host {
|
||||
display: inline-block;
|
||||
margin-top: 1.25rem;
|
||||
padding: 0.35rem 0.75rem;
|
||||
border-radius: 999px;
|
||||
background: #f3f4f6;
|
||||
color: #374151;
|
||||
font-size: 0.85rem;
|
||||
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
|
||||
word-break: break-all;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<main class="card" role="main">
|
||||
<p class="status" aria-label="HTTP status">{{status}}</p>
|
||||
<h1>源站暂时无法提供服务</h1>
|
||||
<p class="muted">网关已拦截源站错误响应。请稍后重试;若问题持续,请联系站点管理员。</p>
|
||||
<p class="host">{{host}}</p>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
`
|
||||
|
||||
// EffectiveOriginErrorPageHTML returns custom HTML when set, otherwise the built-in default.
|
||||
func EffectiveOriginErrorPageHTML(cfg ConfigSnapshot) string {
|
||||
if strings.TrimSpace(cfg.OriginErrorPageHTML) == "" {
|
||||
return DefaultOriginErrorPageHTML
|
||||
}
|
||||
return cfg.OriginErrorPageHTML
|
||||
}
|
||||
|
||||
func effectiveOriginErrorPageStatusTags(cfg ConfigSnapshot) []string {
|
||||
if len(cfg.OriginErrorPageStatusCodes) == 0 {
|
||||
return []string{defaultOriginErrorPageStatusTag}
|
||||
}
|
||||
return cfg.OriginErrorPageStatusCodes
|
||||
}
|
||||
|
||||
func originErrorPageSupportFile(cfg ConfigSnapshot) SupportFile {
|
||||
return SupportFile{
|
||||
Path: OriginErrorPageSupportPath,
|
||||
Content: EffectiveOriginErrorPageHTML(cfg),
|
||||
}
|
||||
}
|
||||
|
||||
func renderOriginErrorPageIntercept(cfg ConfigSnapshot) string {
|
||||
if !cfg.OriginErrorPageEnabled {
|
||||
return ""
|
||||
}
|
||||
if _, err := ExpandStatusCodeTags(effectiveOriginErrorPageStatusTags(cfg)); err != nil {
|
||||
return ""
|
||||
}
|
||||
return " proxy_intercept_errors on;\n"
|
||||
}
|
||||
|
||||
// renderOriginErrorPageServerBits emits server-level error_page + internal location.
|
||||
// Returns empty string when disabled, expand fails, or no codes remain.
|
||||
func renderOriginErrorPageServerBits(cfg ConfigSnapshot) string {
|
||||
if !cfg.OriginErrorPageEnabled {
|
||||
return ""
|
||||
}
|
||||
codes, err := ExpandStatusCodeTags(effectiveOriginErrorPageStatusTags(cfg))
|
||||
if err != nil || len(codes) == 0 {
|
||||
return ""
|
||||
}
|
||||
parts := make([]string, len(codes))
|
||||
for i, code := range codes {
|
||||
parts[i] = strconv.Itoa(code)
|
||||
}
|
||||
var builder strings.Builder
|
||||
fmt.Fprintf(&builder, " error_page %s = %s;\n", strings.Join(parts, " "), OriginErrorPageInternalLocation)
|
||||
builder.WriteString(renderOriginErrorPageInternalLocation())
|
||||
return builder.String()
|
||||
}
|
||||
|
||||
func renderOriginErrorPageInternalLocation() string {
|
||||
return fmt.Sprintf(` location = %s {
|
||||
internal;
|
||||
default_type text/html;
|
||||
charset utf-8;
|
||||
content_by_lua_block {
|
||||
local f = io.open("%s", "r")
|
||||
if not f then
|
||||
ngx.status = ngx.status
|
||||
ngx.say("Error ", ngx.status)
|
||||
return
|
||||
end
|
||||
local body = f:read("*a")
|
||||
f:close()
|
||||
local status = tostring(ngx.status)
|
||||
local host = ngx.var.host or ""
|
||||
body = body:gsub("{{status}}", status, 1)
|
||||
body = body:gsub("{{host}}", host, 1)
|
||||
body = body:gsub("{{status}}", status)
|
||||
body = body:gsub("{{host}}", host)
|
||||
ngx.header["Content-Type"] = "text/html; charset=utf-8"
|
||||
ngx.say(body)
|
||||
}
|
||||
}
|
||||
`, OriginErrorPageInternalLocation, ErrorPageTmplPlaceholder)
|
||||
}
|
||||
@@ -0,0 +1,185 @@
|
||||
package openresty
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestRenderOriginErrorPageEnabled(t *testing.T) {
|
||||
t.Parallel()
|
||||
doc := Document{
|
||||
Routes: []Route{{
|
||||
ID: 1, SiteName: "ex", Domains: []string{"ex.test"},
|
||||
OriginURL: "http://127.0.0.1:9", Enabled: true,
|
||||
}},
|
||||
OpenRestyConfig: ConfigSnapshot{
|
||||
OriginErrorPageEnabled: true,
|
||||
OriginErrorPageStatusCodes: []string{"500-599"},
|
||||
},
|
||||
}
|
||||
out, err := RenderRouteConfig(doc, nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !strings.Contains(out, "proxy_intercept_errors on") {
|
||||
t.Fatal("missing intercept")
|
||||
}
|
||||
if !strings.Contains(out, "error_page") || !strings.Contains(out, "/__openflare_origin_error") {
|
||||
t.Fatal("missing error_page")
|
||||
}
|
||||
if !strings.Contains(out, "error_page 500") {
|
||||
t.Fatalf("expected expanded status codes in error_page, got:\n%s", out)
|
||||
}
|
||||
if !strings.Contains(out, "= /__openflare_origin_error") {
|
||||
t.Fatal("error_page must keep original status via = redirect form")
|
||||
}
|
||||
if !strings.Contains(out, ErrorPageTmplPlaceholder) {
|
||||
t.Fatal("missing error page template placeholder")
|
||||
}
|
||||
res, err := Render(doc, nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
found := false
|
||||
for _, f := range res.SupportFiles {
|
||||
if f.Path == OriginErrorPageSupportPath {
|
||||
found = true
|
||||
if !strings.Contains(f.Content, "{{status}}") {
|
||||
t.Fatal("template missing placeholder")
|
||||
}
|
||||
if !strings.Contains(f.Content, "{{host}}") {
|
||||
t.Fatal("template missing host placeholder")
|
||||
}
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
t.Fatal("missing support file")
|
||||
}
|
||||
}
|
||||
|
||||
func TestRenderOriginErrorPageDisabled(t *testing.T) {
|
||||
t.Parallel()
|
||||
doc := Document{
|
||||
Routes: []Route{{
|
||||
ID: 1, SiteName: "ex", Domains: []string{"ex.test"},
|
||||
OriginURL: "http://127.0.0.1:9", Enabled: true,
|
||||
}},
|
||||
OpenRestyConfig: ConfigSnapshot{OriginErrorPageEnabled: false},
|
||||
}
|
||||
out, err := RenderRouteConfig(doc, nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if strings.Contains(out, "proxy_intercept_errors") {
|
||||
t.Fatal("should not intercept when disabled")
|
||||
}
|
||||
if strings.Contains(out, "/__openflare_origin_error") {
|
||||
t.Fatal("should not emit internal error location when disabled")
|
||||
}
|
||||
res, err := Render(doc, nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
for _, f := range res.SupportFiles {
|
||||
if f.Path == OriginErrorPageSupportPath {
|
||||
t.Fatal("should not emit support file when disabled")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestRenderOriginErrorPageDefaultsEmptyHTMLAndStatusCodes(t *testing.T) {
|
||||
t.Parallel()
|
||||
doc := Document{
|
||||
Routes: []Route{{
|
||||
ID: 1, SiteName: "ex", Domains: []string{"ex.test"},
|
||||
OriginURL: "http://127.0.0.1:9", Enabled: true,
|
||||
}},
|
||||
OpenRestyConfig: ConfigSnapshot{
|
||||
OriginErrorPageEnabled: true,
|
||||
},
|
||||
}
|
||||
out, err := RenderRouteConfig(doc, nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !strings.Contains(out, "error_page 500") {
|
||||
t.Fatalf("empty status codes should default to 500-599, got:\n%s", out)
|
||||
}
|
||||
html := EffectiveOriginErrorPageHTML(doc.OpenRestyConfig)
|
||||
if html != DefaultOriginErrorPageHTML {
|
||||
t.Fatal("empty HTML should use default template")
|
||||
}
|
||||
if !strings.Contains(html, "{{status}}") || !strings.Contains(html, "{{host}}") {
|
||||
t.Fatal("default HTML must include placeholders")
|
||||
}
|
||||
if !strings.Contains(html, "源站暂时无法提供服务") {
|
||||
t.Fatal("default HTML missing neutral copy")
|
||||
}
|
||||
}
|
||||
|
||||
func TestRenderOriginErrorPageCustomHTMLInSupportFile(t *testing.T) {
|
||||
t.Parallel()
|
||||
custom := "<html><body>custom {{status}} @ {{host}}</body></html>"
|
||||
doc := Document{
|
||||
Routes: []Route{{
|
||||
ID: 1, SiteName: "ex", Domains: []string{"ex.test"},
|
||||
OriginURL: "http://127.0.0.1:9", Enabled: true,
|
||||
}},
|
||||
OpenRestyConfig: ConfigSnapshot{
|
||||
OriginErrorPageEnabled: true,
|
||||
OriginErrorPageStatusCodes: []string{"502"},
|
||||
OriginErrorPageHTML: custom,
|
||||
},
|
||||
}
|
||||
res, err := Render(doc, nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
found := false
|
||||
for _, f := range res.SupportFiles {
|
||||
if f.Path == OriginErrorPageSupportPath {
|
||||
found = true
|
||||
if f.Content != custom {
|
||||
t.Fatalf("support file content = %q, want custom HTML", f.Content)
|
||||
}
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
t.Fatal("missing support file")
|
||||
}
|
||||
out, err := RenderRouteConfig(doc, nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !strings.Contains(out, "error_page 502 = /__openflare_origin_error") {
|
||||
t.Fatalf("expected single 502 error_page, got:\n%s", out)
|
||||
}
|
||||
}
|
||||
|
||||
func TestRenderOriginErrorPageSkipsPagesRoutes(t *testing.T) {
|
||||
t.Parallel()
|
||||
doc := Document{
|
||||
Routes: []Route{{
|
||||
ID: 1, SiteName: "pages", Domains: []string{"pages.test"},
|
||||
UpstreamType: "pages", Enabled: true,
|
||||
PagesDeployment: &PagesDeployment{
|
||||
ProjectID: 1, LocalRoot: PagesDirPlaceholder + "/projects/1/current",
|
||||
EntryFile: "index.html",
|
||||
},
|
||||
}},
|
||||
OpenRestyConfig: ConfigSnapshot{
|
||||
OriginErrorPageEnabled: true,
|
||||
OriginErrorPageStatusCodes: []string{"500-599"},
|
||||
},
|
||||
}
|
||||
out, err := RenderRouteConfig(doc, nil)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if strings.Contains(out, "proxy_intercept_errors") {
|
||||
t.Fatal("pages routes must not get proxy_intercept_errors")
|
||||
}
|
||||
if strings.Contains(out, "/__openflare_origin_error") {
|
||||
t.Fatal("pages routes must not get origin error location")
|
||||
}
|
||||
}
|
||||
@@ -46,6 +46,9 @@ func Render(doc Document, certificateFiles []SupportFile) (*Result, error) {
|
||||
}
|
||||
files := append([]SupportFile(nil), certificateFiles...)
|
||||
files = append(files, SupportFile{Path: "waf_config.json", Content: wafConfig})
|
||||
if doc.OpenRestyConfig.OriginErrorPageEnabled {
|
||||
files = append(files, originErrorPageSupportFile(doc.OpenRestyConfig))
|
||||
}
|
||||
files = DedupeSupportFiles(files)
|
||||
return &Result{
|
||||
MainConfig: mainConfig,
|
||||
@@ -270,7 +273,7 @@ func renderOpenRestyObservabilityTemplateBlock() string {
|
||||
}
|
||||
|
||||
func renderHTTPProxyServer(serverNames string, siteName string, originURL string, originHost string, customHeaders []CustomHeader, cacheConfig routeCacheConfig, limitConfig routeLimitConfig, upstreamConfig routeUpstreamConfig, powEnabled bool, basicAuthEnabled bool, basicAuthUsername string, basicAuthPassword string, cfg ConfigSnapshot) string {
|
||||
return fmt.Sprintf("server {\n listen 80;\n server_name %s;\n%s%s location / {\n%s%s%s%s%s }\n%s}\n\n", serverNames, renderAccessBlock(siteName, powEnabled), renderPowLocationBlocks(powEnabled), renderBasicAuthBlock(basicAuthEnabled, basicAuthUsername, basicAuthPassword), renderProxyHeaderBlock(originURL, originHost, customHeaders, upstreamConfig, cfg), renderRouteLimitBlock(limitConfig), renderRouteCacheBlock(cacheConfig, cfg), renderProxyPassBlock(originURL, upstreamConfig), renderPowStaticLocationBlock(powEnabled))
|
||||
return fmt.Sprintf("server {\n listen 80;\n server_name %s;\n%s%s location / {\n%s%s%s%s%s%s }\n%s%s}\n\n", serverNames, renderAccessBlock(siteName, powEnabled), renderPowLocationBlocks(powEnabled), renderBasicAuthBlock(basicAuthEnabled, basicAuthUsername, basicAuthPassword), renderProxyHeaderBlock(originURL, originHost, customHeaders, upstreamConfig, cfg), renderRouteLimitBlock(limitConfig), renderRouteCacheBlock(cacheConfig, cfg), renderOriginErrorPageIntercept(cfg), renderProxyPassBlock(originURL, upstreamConfig), renderOriginErrorPageServerBits(cfg), renderPowStaticLocationBlock(powEnabled))
|
||||
}
|
||||
|
||||
func renderPagesAPIProxyLocationBlock(deployment *PagesDeployment) string {
|
||||
@@ -333,7 +336,7 @@ func renderHTTPSServer(serverNames string, siteName string, originURL string, or
|
||||
h3Listen = " listen 443 quic;\n"
|
||||
h3Header = " add_header Alt-Svc 'h3=\":443\"; ma=86400';\n"
|
||||
}
|
||||
return fmt.Sprintf("server {\n listen 443 ssl;\n%s http2 on;\n server_name %s;\n ssl_certificate %s;\n ssl_certificate_key %s;\n%s%s%s location / {\n%s%s%s%s%s }\n%s}\n\n", h3Listen, serverNames, certPath, keyPath, h3Header, renderAccessBlock(siteName, powEnabled), renderPowLocationBlocks(powEnabled), renderBasicAuthBlock(basicAuthEnabled, basicAuthUsername, basicAuthPassword), renderProxyHeaderBlock(originURL, originHost, customHeaders, upstreamConfig, cfg), renderRouteLimitBlock(limitConfig), renderRouteCacheBlock(cacheConfig, cfg), renderProxyPassBlock(originURL, upstreamConfig), renderPowStaticLocationBlock(powEnabled))
|
||||
return fmt.Sprintf("server {\n listen 443 ssl;\n%s http2 on;\n server_name %s;\n ssl_certificate %s;\n ssl_certificate_key %s;\n%s%s%s location / {\n%s%s%s%s%s%s }\n%s%s}\n\n", h3Listen, serverNames, certPath, keyPath, h3Header, renderAccessBlock(siteName, powEnabled), renderPowLocationBlocks(powEnabled), renderBasicAuthBlock(basicAuthEnabled, basicAuthUsername, basicAuthPassword), renderProxyHeaderBlock(originURL, originHost, customHeaders, upstreamConfig, cfg), renderRouteLimitBlock(limitConfig), renderRouteCacheBlock(cacheConfig, cfg), renderOriginErrorPageIntercept(cfg), renderProxyPassBlock(originURL, upstreamConfig), renderOriginErrorPageServerBits(cfg), renderPowStaticLocationBlock(powEnabled))
|
||||
}
|
||||
|
||||
func renderHTTPSPagesServer(serverNames string, siteName string, certificateID uint, deployment *PagesDeployment, limitConfig routeLimitConfig, powEnabled bool, basicAuthEnabled bool, basicAuthUsername string, basicAuthPassword string, cfg ConfigSnapshot) string {
|
||||
|
||||
@@ -20,6 +20,7 @@ const (
|
||||
ObservabilityPortPlaceholder = "__OPENFLARE_OBSERVABILITY_PORT__"
|
||||
PowStaticDirPlaceholder = "__OPENFLARE_POW_STATIC_DIR__"
|
||||
PagesDirPlaceholder = "__OPENFLARE_PAGES_DIR__"
|
||||
ErrorPageTmplPlaceholder = "__OPENFLARE_ERROR_PAGE_TMPL__"
|
||||
|
||||
SourceConfigFileName = "openresty_config.json"
|
||||
)
|
||||
@@ -273,47 +274,50 @@ type WAFDocument struct {
|
||||
// ConfigSnapshot holds the full set of OpenResty tuning parameters that are
|
||||
// rendered into the nginx main configuration template.
|
||||
type ConfigSnapshot struct {
|
||||
DefaultServerReturnStatus int `json:"default_server_return_status"`
|
||||
WorkerProcesses string `json:"worker_processes"`
|
||||
WorkerConnections int `json:"worker_connections"`
|
||||
WorkerRlimitNofile int `json:"worker_rlimit_nofile"`
|
||||
EventsUse string `json:"events_use,omitempty"`
|
||||
EventsMultiAcceptEnabled bool `json:"events_multi_accept_enabled"`
|
||||
KeepaliveTimeout int `json:"keepalive_timeout"`
|
||||
KeepaliveRequests int `json:"keepalive_requests"`
|
||||
ClientHeaderTimeout int `json:"client_header_timeout"`
|
||||
ClientBodyTimeout int `json:"client_body_timeout"`
|
||||
ClientMaxBodySize string `json:"client_max_body_size"`
|
||||
LargeClientHeaderBuffers string `json:"large_client_header_buffers"`
|
||||
SendTimeout int `json:"send_timeout"`
|
||||
ProxyConnectTimeout int `json:"proxy_connect_timeout"`
|
||||
ProxySendTimeout int `json:"proxy_send_timeout"`
|
||||
ProxyReadTimeout int `json:"proxy_read_timeout"`
|
||||
WebsocketEnabled bool `json:"websocket_enabled"`
|
||||
HTTP3Enabled bool `json:"http3_enabled"`
|
||||
ProxyRequestBuffering bool `json:"proxy_request_buffering"`
|
||||
ProxyBufferingEnabled bool `json:"proxy_buffering_enabled"`
|
||||
ProxyBuffers string `json:"proxy_buffers"`
|
||||
ProxyBufferSize string `json:"proxy_buffer_size"`
|
||||
ProxyBusyBuffersSize string `json:"proxy_busy_buffers_size"`
|
||||
GzipEnabled bool `json:"gzip_enabled"`
|
||||
GzipMinLength int `json:"gzip_min_length"`
|
||||
GzipCompLevel int `json:"gzip_comp_level"`
|
||||
Resolvers string `json:"resolvers,omitempty"`
|
||||
CacheEnabled bool `json:"cache_enabled"`
|
||||
CachePath string `json:"cache_path,omitempty"`
|
||||
CacheLevels string `json:"cache_levels"`
|
||||
CacheInactive string `json:"cache_inactive"`
|
||||
CacheMaxSize string `json:"cache_max_size"`
|
||||
CacheKeyTemplate string `json:"cache_key_template"`
|
||||
CacheLockEnabled bool `json:"cache_lock_enabled"`
|
||||
CacheLockTimeout string `json:"cache_lock_timeout"`
|
||||
CacheUseStale string `json:"cache_use_stale"`
|
||||
MainConfigTemplate string `json:"main_config_template,omitempty"`
|
||||
DefaultLimitConnPerServer int `json:"default_limit_conn_per_server,omitempty"`
|
||||
DefaultLimitConnPerIP int `json:"default_limit_conn_per_ip,omitempty"`
|
||||
DefaultLimitRate string `json:"default_limit_rate,omitempty"`
|
||||
DefaultLimitReqPerIP string `json:"default_limit_req_per_ip,omitempty"`
|
||||
DefaultServerReturnStatus int `json:"default_server_return_status"`
|
||||
WorkerProcesses string `json:"worker_processes"`
|
||||
WorkerConnections int `json:"worker_connections"`
|
||||
WorkerRlimitNofile int `json:"worker_rlimit_nofile"`
|
||||
EventsUse string `json:"events_use,omitempty"`
|
||||
EventsMultiAcceptEnabled bool `json:"events_multi_accept_enabled"`
|
||||
KeepaliveTimeout int `json:"keepalive_timeout"`
|
||||
KeepaliveRequests int `json:"keepalive_requests"`
|
||||
ClientHeaderTimeout int `json:"client_header_timeout"`
|
||||
ClientBodyTimeout int `json:"client_body_timeout"`
|
||||
ClientMaxBodySize string `json:"client_max_body_size"`
|
||||
LargeClientHeaderBuffers string `json:"large_client_header_buffers"`
|
||||
SendTimeout int `json:"send_timeout"`
|
||||
ProxyConnectTimeout int `json:"proxy_connect_timeout"`
|
||||
ProxySendTimeout int `json:"proxy_send_timeout"`
|
||||
ProxyReadTimeout int `json:"proxy_read_timeout"`
|
||||
WebsocketEnabled bool `json:"websocket_enabled"`
|
||||
HTTP3Enabled bool `json:"http3_enabled"`
|
||||
ProxyRequestBuffering bool `json:"proxy_request_buffering"`
|
||||
ProxyBufferingEnabled bool `json:"proxy_buffering_enabled"`
|
||||
ProxyBuffers string `json:"proxy_buffers"`
|
||||
ProxyBufferSize string `json:"proxy_buffer_size"`
|
||||
ProxyBusyBuffersSize string `json:"proxy_busy_buffers_size"`
|
||||
GzipEnabled bool `json:"gzip_enabled"`
|
||||
GzipMinLength int `json:"gzip_min_length"`
|
||||
GzipCompLevel int `json:"gzip_comp_level"`
|
||||
Resolvers string `json:"resolvers,omitempty"`
|
||||
CacheEnabled bool `json:"cache_enabled"`
|
||||
CachePath string `json:"cache_path,omitempty"`
|
||||
CacheLevels string `json:"cache_levels"`
|
||||
CacheInactive string `json:"cache_inactive"`
|
||||
CacheMaxSize string `json:"cache_max_size"`
|
||||
CacheKeyTemplate string `json:"cache_key_template"`
|
||||
CacheLockEnabled bool `json:"cache_lock_enabled"`
|
||||
CacheLockTimeout string `json:"cache_lock_timeout"`
|
||||
CacheUseStale string `json:"cache_use_stale"`
|
||||
MainConfigTemplate string `json:"main_config_template,omitempty"`
|
||||
DefaultLimitConnPerServer int `json:"default_limit_conn_per_server,omitempty"`
|
||||
DefaultLimitConnPerIP int `json:"default_limit_conn_per_ip,omitempty"`
|
||||
DefaultLimitRate string `json:"default_limit_rate,omitempty"`
|
||||
DefaultLimitReqPerIP string `json:"default_limit_req_per_ip,omitempty"`
|
||||
OriginErrorPageEnabled bool `json:"origin_error_page_enabled"`
|
||||
OriginErrorPageStatusCodes []string `json:"origin_error_page_status_codes,omitempty"`
|
||||
OriginErrorPageHTML string `json:"origin_error_page_html,omitempty"`
|
||||
}
|
||||
|
||||
// Document is the top-level input structure for the OpenResty renderer,
|
||||
|
||||
Reference in New Issue
Block a user