mirror of
https://github.com/Rain-kl/OpenFlare.git
synced 2026-10-09 00:56:37 +08:00
feat(openresty): merge global default limits at route render
This commit is contained in:
@@ -94,7 +94,7 @@ func RenderRouteConfig(doc Document, certificateFiles []SupportFile) (string, er
|
|||||||
serverNames := renderServerNames(domains)
|
serverNames := renderServerNames(domains)
|
||||||
displayName := resolveRouteSiteName(route)
|
displayName := resolveRouteSiteName(route)
|
||||||
cacheConfig := routeCacheConfig{Enabled: route.CacheEnabled, Policy: route.CachePolicy, Rules: route.CacheRules}
|
cacheConfig := routeCacheConfig{Enabled: route.CacheEnabled, Policy: route.CachePolicy, Rules: route.CacheRules}
|
||||||
limitConfig := routeLimitConfig{LimitConnPerServer: route.LimitConnPerServer, LimitConnPerIP: route.LimitConnPerIP, LimitRate: route.LimitRate}
|
limitConfig := mergeRouteLimitConfig(route, doc.OpenRestyConfig)
|
||||||
powEnabled, _ := getPoWConfigForRoute(route.ID, doc.WAF)
|
powEnabled, _ := getPoWConfigForRoute(route.ID, doc.WAF)
|
||||||
if normalizeRouteUpstreamType(route.UpstreamType) == routeUpstreamTypePages {
|
if normalizeRouteUpstreamType(route.UpstreamType) == routeUpstreamTypePages {
|
||||||
if err := renderPagesRoute(&builder, route, displayName, serverNames, certificates, limitConfig, powEnabled, doc.OpenRestyConfig); err != nil {
|
if err := renderPagesRoute(&builder, route, displayName, serverNames, certificates, limitConfig, powEnabled, doc.OpenRestyConfig); err != nil {
|
||||||
@@ -478,6 +478,42 @@ func renderRouteLimitBlock(limitConfig routeLimitConfig) string {
|
|||||||
return builder.String()
|
return builder.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func mergeRouteLimitConfig(route Route, cfg ConfigSnapshot) routeLimitConfig {
|
||||||
|
return routeLimitConfig{
|
||||||
|
LimitConnPerServer: mergeLimitConn(route.LimitConnPerServer, cfg.DefaultLimitConnPerServer),
|
||||||
|
LimitConnPerIP: mergeLimitConn(route.LimitConnPerIP, cfg.DefaultLimitConnPerIP),
|
||||||
|
LimitRate: mergeLimitRate(route.LimitRate, cfg.DefaultLimitRate),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func mergeLimitConn(route, def int) int {
|
||||||
|
if route == -1 {
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
if route > 0 {
|
||||||
|
return route
|
||||||
|
}
|
||||||
|
if def > 0 {
|
||||||
|
return def
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func mergeLimitRate(route, def string) string {
|
||||||
|
r := strings.ToLower(strings.TrimSpace(route))
|
||||||
|
if r == "-1" {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
if r != "" && r != "0" {
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
d := strings.ToLower(strings.TrimSpace(def))
|
||||||
|
if d != "" && d != "0" {
|
||||||
|
return d
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
func renderRouteCachePolicyCondition(cacheConfig routeCacheConfig) string {
|
func renderRouteCachePolicyCondition(cacheConfig routeCacheConfig) string {
|
||||||
policy := normalizeRenderCachePolicy(cacheConfig.Policy)
|
policy := normalizeRenderCachePolicy(cacheConfig.Policy)
|
||||||
switch policy {
|
switch policy {
|
||||||
|
|||||||
@@ -442,3 +442,126 @@ func TestRenderRouteCacheBlockIncludesStaticWhenEnabled(t *testing.T) {
|
|||||||
t.Fatalf("expected security bypass for non-GET, got:\n%s", block)
|
t.Fatalf("expected security bypass for non-GET, got:\n%s", block)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestMergeRouteLimitConfig(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
cases := []struct {
|
||||||
|
name string
|
||||||
|
route Route
|
||||||
|
cfg ConfigSnapshot
|
||||||
|
want routeLimitConfig
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "both zero off",
|
||||||
|
route: Route{},
|
||||||
|
cfg: ConfigSnapshot{},
|
||||||
|
want: routeLimitConfig{},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "inherit all defaults",
|
||||||
|
route: Route{},
|
||||||
|
cfg: ConfigSnapshot{
|
||||||
|
DefaultLimitConnPerServer: 100,
|
||||||
|
DefaultLimitConnPerIP: 10,
|
||||||
|
DefaultLimitRate: "512k",
|
||||||
|
},
|
||||||
|
want: routeLimitConfig{LimitConnPerServer: 100, LimitConnPerIP: 10, LimitRate: "512k"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "explicit off ignores default",
|
||||||
|
route: Route{LimitConnPerServer: -1, LimitConnPerIP: -1, LimitRate: "-1"},
|
||||||
|
cfg: ConfigSnapshot{
|
||||||
|
DefaultLimitConnPerServer: 100,
|
||||||
|
DefaultLimitConnPerIP: 10,
|
||||||
|
DefaultLimitRate: "512k",
|
||||||
|
},
|
||||||
|
want: routeLimitConfig{},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "route overrides default",
|
||||||
|
route: Route{LimitConnPerServer: 50, LimitConnPerIP: 5, LimitRate: "1m"},
|
||||||
|
cfg: ConfigSnapshot{
|
||||||
|
DefaultLimitConnPerServer: 100,
|
||||||
|
DefaultLimitConnPerIP: 10,
|
||||||
|
DefaultLimitRate: "512k",
|
||||||
|
},
|
||||||
|
want: routeLimitConfig{LimitConnPerServer: 50, LimitConnPerIP: 5, LimitRate: "1m"},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "partial inherit",
|
||||||
|
route: Route{LimitConnPerServer: 0, LimitConnPerIP: -1, LimitRate: ""},
|
||||||
|
cfg: ConfigSnapshot{
|
||||||
|
DefaultLimitConnPerServer: 100,
|
||||||
|
DefaultLimitConnPerIP: 10,
|
||||||
|
DefaultLimitRate: "256k",
|
||||||
|
},
|
||||||
|
want: routeLimitConfig{LimitConnPerServer: 100, LimitConnPerIP: 0, LimitRate: "256k"},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
for _, tc := range cases {
|
||||||
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
got := mergeRouteLimitConfig(tc.route, tc.cfg)
|
||||||
|
if got != tc.want {
|
||||||
|
t.Fatalf("mergeRouteLimitConfig() = %#v, want %#v", got, tc.want)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRenderRouteConfigAppliesDefaultLimits(t *testing.T) {
|
||||||
|
doc := Document{
|
||||||
|
Routes: []Route{{
|
||||||
|
SiteName: "example.com",
|
||||||
|
Domains: []string{"example.com"},
|
||||||
|
Enabled: true,
|
||||||
|
OriginURL: "http://127.0.0.1:8080",
|
||||||
|
Upstreams: []string{"http://127.0.0.1:8080"},
|
||||||
|
}},
|
||||||
|
OpenRestyConfig: ConfigSnapshot{
|
||||||
|
DefaultLimitConnPerServer: 120,
|
||||||
|
DefaultLimitConnPerIP: 12,
|
||||||
|
DefaultLimitRate: "512k",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
rendered, err := RenderRouteConfig(doc, nil)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("RenderRouteConfig() error = %v", err)
|
||||||
|
}
|
||||||
|
for _, want := range []string{
|
||||||
|
"limit_conn openflare_conn_per_server 120;",
|
||||||
|
"limit_conn openflare_conn_per_ip 12;",
|
||||||
|
"limit_rate 512k;",
|
||||||
|
} {
|
||||||
|
if !strings.Contains(rendered, want) {
|
||||||
|
t.Fatalf("expected %q in route config, got:\n%s", want, rendered)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRenderRouteConfigExplicitOffSkipsDefaultLimits(t *testing.T) {
|
||||||
|
doc := Document{
|
||||||
|
Routes: []Route{{
|
||||||
|
SiteName: "example.com",
|
||||||
|
Domains: []string{"example.com"},
|
||||||
|
Enabled: true,
|
||||||
|
OriginURL: "http://127.0.0.1:8080",
|
||||||
|
Upstreams: []string{"http://127.0.0.1:8080"},
|
||||||
|
LimitConnPerServer: -1,
|
||||||
|
LimitConnPerIP: -1,
|
||||||
|
LimitRate: "-1",
|
||||||
|
}},
|
||||||
|
OpenRestyConfig: ConfigSnapshot{
|
||||||
|
DefaultLimitConnPerServer: 120,
|
||||||
|
DefaultLimitConnPerIP: 12,
|
||||||
|
DefaultLimitRate: "512k",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
rendered, err := RenderRouteConfig(doc, nil)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("RenderRouteConfig() error = %v", err)
|
||||||
|
}
|
||||||
|
if strings.Contains(rendered, "limit_conn") || strings.Contains(rendered, "limit_rate") {
|
||||||
|
t.Fatalf("expected no limit directives, got:\n%s", rendered)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -309,6 +309,9 @@ type ConfigSnapshot struct {
|
|||||||
CacheLockTimeout string `json:"cache_lock_timeout"`
|
CacheLockTimeout string `json:"cache_lock_timeout"`
|
||||||
CacheUseStale string `json:"cache_use_stale"`
|
CacheUseStale string `json:"cache_use_stale"`
|
||||||
MainConfigTemplate string `json:"main_config_template,omitempty"`
|
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"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Document is the top-level input structure for the OpenResty renderer,
|
// Document is the top-level input structure for the OpenResty renderer,
|
||||||
|
|||||||
Reference in New Issue
Block a user