Fixed nil pointer exception in new setups

This commit is contained in:
Toby Chui 2024-12-29 16:11:00 +08:00
parent b3ad97743c
commit 1d4c275db3
6 changed files with 123 additions and 47 deletions

View File

@ -48,7 +48,7 @@ func LoadReverseProxyConfig(configFilepath string) error {
} }
//Parse it into dynamic proxy endpoint //Parse it into dynamic proxy endpoint
thisConfigEndpoint := dynamicproxy.ProxyEndpoint{} thisConfigEndpoint := dynamicproxy.GetDefaultProxyEndpoint()
err = json.Unmarshal(endpointConfig, &thisConfigEndpoint) err = json.Unmarshal(endpointConfig, &thisConfigEndpoint)
if err != nil { if err != nil {
return err return err
@ -129,31 +129,23 @@ func RemoveReverseProxyConfig(endpoint string) error {
// Get the default root config that point to the internal static web server // Get the default root config that point to the internal static web server
// this will be used if root config is not found (new deployment / missing root.config file) // this will be used if root config is not found (new deployment / missing root.config file)
func GetDefaultRootConfig() (*dynamicproxy.ProxyEndpoint, error) { func GetDefaultRootConfig() (*dynamicproxy.ProxyEndpoint, error) {
//Default Authentication Provider //Get the default proxy endpoint
defaultAuth := &dynamicproxy.AuthenticationProvider{ rootProxyEndpointConfig := dynamicproxy.GetDefaultProxyEndpoint()
AuthMethod: dynamicproxy.AuthMethodNone, rootProxyEndpointConfig.ProxyType = dynamicproxy.ProxyTypeRoot
BasicAuthCredentials: []*dynamicproxy.BasicAuthCredentials{}, rootProxyEndpointConfig.RootOrMatchingDomain = "/"
BasicAuthExceptionRules: []*dynamicproxy.BasicAuthExceptionRule{}, rootProxyEndpointConfig.ActiveOrigins = []*loadbalance.Upstream{
} {
//Default settings OriginIpOrDomain: "127.0.0.1:" + staticWebServer.GetListeningPort(),
rootProxyEndpoint, err := dynamicProxyRouter.PrepareProxyRoute(&dynamicproxy.ProxyEndpoint{ RequireTLS: false,
ProxyType: dynamicproxy.ProxyTypeRoot, SkipCertValidations: false,
RootOrMatchingDomain: "/", Weight: 0,
ActiveOrigins: []*loadbalance.Upstream{
{
OriginIpOrDomain: "127.0.0.1:" + staticWebServer.GetListeningPort(),
RequireTLS: false,
SkipCertValidations: false,
Weight: 0,
},
}, },
InactiveOrigins: []*loadbalance.Upstream{}, }
BypassGlobalTLS: false, rootProxyEndpointConfig.DefaultSiteOption = dynamicproxy.DefaultSite_InternalStaticWebServer
VirtualDirectories: []*dynamicproxy.VirtualDirectoryEndpoint{}, rootProxyEndpointConfig.DefaultSiteValue = ""
AuthenticationProvider: defaultAuth,
DefaultSiteOption: dynamicproxy.DefaultSite_InternalStaticWebServer, //Default settings
DefaultSiteValue: "", rootProxyEndpoint, err := dynamicProxyRouter.PrepareProxyRoute(&rootProxyEndpointConfig)
})
if err != nil { if err != nil {
return nil, err return nil, err
} }

View File

@ -0,0 +1,64 @@
package dynamicproxy
import (
"github.com/google/uuid"
"imuslab.com/zoraxy/mod/dynamicproxy/loadbalance"
"imuslab.com/zoraxy/mod/dynamicproxy/rewrite"
)
/*
Default Provider
This script provide the default options for all datatype
provided by dynamicproxy module
*/
// GetDefaultAuthenticationProvider return a default authentication provider
func GetDefaultAuthenticationProvider() *AuthenticationProvider {
return &AuthenticationProvider{
AuthMethod: AuthMethodNone,
BasicAuthCredentials: []*BasicAuthCredentials{},
BasicAuthExceptionRules: []*BasicAuthExceptionRule{},
BasicAuthGroupIDs: []string{},
AutheliaURL: "",
UseHTTPS: false,
}
}
// GetDefaultHeaderRewriteRules return a default header rewrite rules
func GetDefaultHeaderRewriteRules() *HeaderRewriteRules {
return &HeaderRewriteRules{
UserDefinedHeaders: []*rewrite.UserDefinedHeader{},
RequestHostOverwrite: "",
HSTSMaxAge: 0,
EnablePermissionPolicyHeader: false,
PermissionPolicy: nil,
DisableHopByHopHeaderRemoval: false,
}
}
// GetDefaultProxyEndpoint return a default proxy endpoint
func GetDefaultProxyEndpoint() ProxyEndpoint {
randomPrefix := uuid.New().String()
return ProxyEndpoint{
ProxyType: ProxyTypeHost,
RootOrMatchingDomain: randomPrefix + ".internal",
MatchingDomainAlias: []string{},
ActiveOrigins: []*loadbalance.Upstream{},
InactiveOrigins: []*loadbalance.Upstream{},
UseStickySession: false,
UseActiveLoadBalance: false,
Disabled: false,
BypassGlobalTLS: false,
VirtualDirectories: []*VirtualDirectoryEndpoint{},
HeaderRewriteRules: GetDefaultHeaderRewriteRules(),
AuthenticationProvider: GetDefaultAuthenticationProvider(),
RequireRateLimit: false,
RateLimit: 0,
DisableUptimeMonitor: false,
AccessFilterUUID: "default",
DefaultSiteOption: DefaultSite_InternalStaticWebServer,
DefaultSiteValue: "",
}
}

View File

@ -157,12 +157,18 @@ func (router *Router) StartProxyService() error {
router.Option.Logger.PrintAndLog("dprouter", "failed to get upstream for hostname", err) router.Option.Logger.PrintAndLog("dprouter", "failed to get upstream for hostname", err)
router.logRequest(r, false, 404, "vdir-http", r.Host) router.logRequest(r, false, 404, "vdir-http", r.Host)
} }
endpointProxyRewriteRules := GetDefaultHeaderRewriteRules()
if sep.HeaderRewriteRules != nil {
endpointProxyRewriteRules = sep.HeaderRewriteRules
}
selectedUpstream.ServeHTTP(w, r, &dpcore.ResponseRewriteRuleSet{ selectedUpstream.ServeHTTP(w, r, &dpcore.ResponseRewriteRuleSet{
ProxyDomain: selectedUpstream.OriginIpOrDomain, ProxyDomain: selectedUpstream.OriginIpOrDomain,
OriginalHost: originalHostHeader, OriginalHost: originalHostHeader,
UseTLS: selectedUpstream.RequireTLS, UseTLS: selectedUpstream.RequireTLS,
HostHeaderOverwrite: sep.HeaderRewriteRules.RequestHostOverwrite, HostHeaderOverwrite: endpointProxyRewriteRules.RequestHostOverwrite,
NoRemoveHopByHop: sep.HeaderRewriteRules.DisableHopByHopHeaderRemoval, NoRemoveHopByHop: endpointProxyRewriteRules.DisableHopByHopHeaderRemoval,
PathPrefix: "", PathPrefix: "",
Version: sep.parent.Option.HostVersion, Version: sep.parent.Option.HostVersion,
}) })

View File

@ -27,7 +27,12 @@ import (
// Check if a user define header exists in this endpoint, ignore case // Check if a user define header exists in this endpoint, ignore case
func (ep *ProxyEndpoint) UserDefinedHeaderExists(key string) bool { func (ep *ProxyEndpoint) UserDefinedHeaderExists(key string) bool {
for _, header := range ep.HeaderRewriteRules.UserDefinedHeaders { endpointProxyRewriteRules := GetDefaultHeaderRewriteRules()
if ep.HeaderRewriteRules != nil {
endpointProxyRewriteRules = ep.HeaderRewriteRules
}
for _, header := range endpointProxyRewriteRules.UserDefinedHeaders {
if strings.EqualFold(header.Key, key) { if strings.EqualFold(header.Key, key) {
return true return true
} }
@ -38,6 +43,9 @@ func (ep *ProxyEndpoint) UserDefinedHeaderExists(key string) bool {
// Remvoe a user defined header from the list // Remvoe a user defined header from the list
func (ep *ProxyEndpoint) RemoveUserDefinedHeader(key string) error { func (ep *ProxyEndpoint) RemoveUserDefinedHeader(key string) error {
newHeaderList := []*rewrite.UserDefinedHeader{} newHeaderList := []*rewrite.UserDefinedHeader{}
if ep.HeaderRewriteRules == nil {
ep.HeaderRewriteRules = GetDefaultHeaderRewriteRules()
}
for _, header := range ep.HeaderRewriteRules.UserDefinedHeaders { for _, header := range ep.HeaderRewriteRules.UserDefinedHeaders {
if !strings.EqualFold(header.Key, key) { if !strings.EqualFold(header.Key, key) {
newHeaderList = append(newHeaderList, header) newHeaderList = append(newHeaderList, header)
@ -55,6 +63,9 @@ func (ep *ProxyEndpoint) AddUserDefinedHeader(newHeaderRule *rewrite.UserDefined
ep.RemoveUserDefinedHeader(newHeaderRule.Key) ep.RemoveUserDefinedHeader(newHeaderRule.Key)
} }
if ep.HeaderRewriteRules == nil {
ep.HeaderRewriteRules = GetDefaultHeaderRewriteRules()
}
newHeaderRule.Key = cases.Title(language.Und, cases.NoLower).String(newHeaderRule.Key) newHeaderRule.Key = cases.Title(language.Und, cases.NoLower).String(newHeaderRule.Key)
ep.HeaderRewriteRules.UserDefinedHeaders = append(ep.HeaderRewriteRules.UserDefinedHeaders, newHeaderRule) ep.HeaderRewriteRules.UserDefinedHeaders = append(ep.HeaderRewriteRules.UserDefinedHeaders, newHeaderRule)
return nil return nil
@ -106,7 +117,7 @@ func (ep *ProxyEndpoint) RemoveVirtualDirectoryRuleByMatchingPath(matchingPath s
return errors.New("target virtual directory routing rule not found") return errors.New("target virtual directory routing rule not found")
} }
// Delete a vdir rule by its matching path // Add a vdir rule by its matching path
func (ep *ProxyEndpoint) AddVirtualDirectoryRule(vdir *VirtualDirectoryEndpoint) (*ProxyEndpoint, error) { func (ep *ProxyEndpoint) AddVirtualDirectoryRule(vdir *VirtualDirectoryEndpoint) (*ProxyEndpoint, error) {
//Check for matching path duplicate //Check for matching path duplicate
if ep.GetVirtualDirectoryRuleByMatchingPath(vdir.MatchingPath) != nil { if ep.GetVirtualDirectoryRuleByMatchingPath(vdir.MatchingPath) != nil {

View File

@ -145,6 +145,10 @@ func (h *ProxyHandler) hostRequest(w http.ResponseWriter, r *http.Request, targe
} }
h.Parent.logRequest(r, true, 101, "host-websocket", selectedUpstream.OriginIpOrDomain) h.Parent.logRequest(r, true, 101, "host-websocket", selectedUpstream.OriginIpOrDomain)
if target.HeaderRewriteRules == nil {
target.HeaderRewriteRules = GetDefaultHeaderRewriteRules()
}
wspHandler := websocketproxy.NewProxy(u, websocketproxy.Options{ wspHandler := websocketproxy.NewProxy(u, websocketproxy.Options{
SkipTLSValidation: selectedUpstream.SkipCertValidations, SkipTLSValidation: selectedUpstream.SkipCertValidations,
SkipOriginCheck: selectedUpstream.SkipWebSocketOriginCheck, SkipOriginCheck: selectedUpstream.SkipWebSocketOriginCheck,
@ -165,18 +169,19 @@ func (h *ProxyHandler) hostRequest(w http.ResponseWriter, r *http.Request, targe
} }
//Populate the user-defined headers with the values from the request //Populate the user-defined headers with the values from the request
rewrittenUserDefinedHeaders := []*rewrite.UserDefinedHeader{} headerRewriteOptions := GetDefaultHeaderRewriteRules()
if target.HeaderRewriteRules != nil { if target.HeaderRewriteRules != nil {
rewrittenUserDefinedHeaders = rewrite.PopulateRequestHeaderVariables(r, target.HeaderRewriteRules.UserDefinedHeaders) headerRewriteOptions = target.HeaderRewriteRules
} }
rewrittenUserDefinedHeaders := rewrite.PopulateRequestHeaderVariables(r, headerRewriteOptions.UserDefinedHeaders)
//Build downstream and upstream header rules //Build downstream and upstream header rules
upstreamHeaders, downstreamHeaders := rewrite.SplitUpDownStreamHeaders(&rewrite.HeaderRewriteOptions{ upstreamHeaders, downstreamHeaders := rewrite.SplitUpDownStreamHeaders(&rewrite.HeaderRewriteOptions{
UserDefinedHeaders: rewrittenUserDefinedHeaders, UserDefinedHeaders: rewrittenUserDefinedHeaders,
HSTSMaxAge: target.HeaderRewriteRules.HSTSMaxAge, HSTSMaxAge: headerRewriteOptions.HSTSMaxAge,
HSTSIncludeSubdomains: target.ContainsWildcardName(true), HSTSIncludeSubdomains: target.ContainsWildcardName(true),
EnablePermissionPolicyHeader: target.HeaderRewriteRules.EnablePermissionPolicyHeader, EnablePermissionPolicyHeader: headerRewriteOptions.EnablePermissionPolicyHeader,
PermissionPolicy: target.HeaderRewriteRules.PermissionPolicy, PermissionPolicy: headerRewriteOptions.PermissionPolicy,
}) })
//Handle the request reverse proxy //Handle the request reverse proxy
@ -188,8 +193,8 @@ func (h *ProxyHandler) hostRequest(w http.ResponseWriter, r *http.Request, targe
PathPrefix: "", PathPrefix: "",
UpstreamHeaders: upstreamHeaders, UpstreamHeaders: upstreamHeaders,
DownstreamHeaders: downstreamHeaders, DownstreamHeaders: downstreamHeaders,
HostHeaderOverwrite: target.HeaderRewriteRules.RequestHostOverwrite, HostHeaderOverwrite: headerRewriteOptions.RequestHostOverwrite,
NoRemoveHopByHop: target.HeaderRewriteRules.DisableHopByHopHeaderRemoval, NoRemoveHopByHop: headerRewriteOptions.DisableHopByHopHeaderRemoval,
Version: target.parent.Option.HostVersion, Version: target.parent.Option.HostVersion,
}) })
@ -248,18 +253,20 @@ func (h *ProxyHandler) vdirRequest(w http.ResponseWriter, r *http.Request, targe
} }
//Populate the user-defined headers with the values from the request //Populate the user-defined headers with the values from the request
rewrittenUserDefinedHeaders := []*rewrite.UserDefinedHeader{} headerRewriteOptions := GetDefaultHeaderRewriteRules()
if target.parent.HeaderRewriteRules != nil { if target.parent.HeaderRewriteRules != nil {
rewrittenUserDefinedHeaders = rewrite.PopulateRequestHeaderVariables(r, target.parent.HeaderRewriteRules.UserDefinedHeaders) headerRewriteOptions = target.parent.HeaderRewriteRules
} }
rewrittenUserDefinedHeaders := rewrite.PopulateRequestHeaderVariables(r, headerRewriteOptions.UserDefinedHeaders)
//Build downstream and upstream header rules, use the parent (subdomain) endpoint's headers //Build downstream and upstream header rules, use the parent (subdomain) endpoint's headers
upstreamHeaders, downstreamHeaders := rewrite.SplitUpDownStreamHeaders(&rewrite.HeaderRewriteOptions{ upstreamHeaders, downstreamHeaders := rewrite.SplitUpDownStreamHeaders(&rewrite.HeaderRewriteOptions{
UserDefinedHeaders: rewrittenUserDefinedHeaders, UserDefinedHeaders: rewrittenUserDefinedHeaders,
HSTSMaxAge: target.parent.HeaderRewriteRules.HSTSMaxAge, HSTSMaxAge: headerRewriteOptions.HSTSMaxAge,
HSTSIncludeSubdomains: target.parent.ContainsWildcardName(true), HSTSIncludeSubdomains: target.parent.ContainsWildcardName(true),
EnablePermissionPolicyHeader: target.parent.HeaderRewriteRules.EnablePermissionPolicyHeader, EnablePermissionPolicyHeader: headerRewriteOptions.EnablePermissionPolicyHeader,
PermissionPolicy: target.parent.HeaderRewriteRules.PermissionPolicy, PermissionPolicy: headerRewriteOptions.PermissionPolicy,
}) })
//Handle the virtual directory reverse proxy request //Handle the virtual directory reverse proxy request
@ -270,7 +277,7 @@ func (h *ProxyHandler) vdirRequest(w http.ResponseWriter, r *http.Request, targe
PathPrefix: target.MatchingPath, PathPrefix: target.MatchingPath,
UpstreamHeaders: upstreamHeaders, UpstreamHeaders: upstreamHeaders,
DownstreamHeaders: downstreamHeaders, DownstreamHeaders: downstreamHeaders,
HostHeaderOverwrite: target.parent.HeaderRewriteRules.RequestHostOverwrite, HostHeaderOverwrite: headerRewriteOptions.RequestHostOverwrite,
Version: target.parent.parent.Option.HostVersion, Version: target.parent.parent.Option.HostVersion,
}) })

View File

@ -320,10 +320,6 @@ func ReverseProxyHandleAddEndpoint(w http.ResponseWriter, r *http.Request) {
BasicAuthExceptionRules: []*dynamicproxy.BasicAuthExceptionRule{}, BasicAuthExceptionRules: []*dynamicproxy.BasicAuthExceptionRule{},
} }
thisCustomHeaderRules := dynamicproxy.HeaderRewriteRules{
UserDefinedHeaders: []*rewrite.UserDefinedHeader{},
}
//Generate a proxy endpoint object //Generate a proxy endpoint object
thisProxyEndpoint := dynamicproxy.ProxyEndpoint{ thisProxyEndpoint := dynamicproxy.ProxyEndpoint{
//I/O //I/O
@ -353,7 +349,7 @@ func ReverseProxyHandleAddEndpoint(w http.ResponseWriter, r *http.Request) {
AuthenticationProvider: &thisAuthenticationProvider, AuthenticationProvider: &thisAuthenticationProvider,
//Header Rewrite //Header Rewrite
HeaderRewriteRules: &thisCustomHeaderRules, HeaderRewriteRules: dynamicproxy.GetDefaultHeaderRewriteRules(),
//Default Site //Default Site
DefaultSiteOption: 0, DefaultSiteOption: 0,