From b00e302f6dd748b5b9fb8740c3415aa979e47e55 Mon Sep 17 00:00:00 2001 From: Toby Chui Date: Sun, 9 Jun 2024 22:49:35 +0800 Subject: [PATCH] Added new custom header structure + Moved custom header rewrite to dpcore + Restructure dpcore header rewrite sequence + Added advance custom header settings (zoraxy to upstream and zoraxy to downstream mode) + Added header remove feature + Removed password requirement for SMTP #80 + Completed stream proxy module (TCP and UDP) + Optimized UX for reminding user to click Apply after port change + Added version number to footer #160 --- src/mod/dynamicproxy/Server.go | 3 - src/mod/dynamicproxy/customHeader.go | 46 ++++++++ src/mod/dynamicproxy/dpcore/dpcore.go | 106 ++++------------- src/mod/dynamicproxy/dpcore/header.go | 121 ++++++++++++++++++++ src/mod/dynamicproxy/dynamicproxy.go | 1 + src/mod/dynamicproxy/endpoints.go | 14 +-- src/mod/dynamicproxy/proxyRequestHandler.go | 44 ++++--- src/mod/dynamicproxy/typedef.go | 1 - src/mod/email/email.go | 13 ++- src/reverseproxy.go | 81 +++++++------ src/web/components/status.html | 24 +++- src/web/components/streamprox.html | 4 +- src/web/components/utils.html | 10 +- src/web/index.html | 2 +- src/web/main.css | 10 ++ src/web/snippet/customHeaders.html | 93 ++++++++++++--- 16 files changed, 385 insertions(+), 188 deletions(-) create mode 100644 src/mod/dynamicproxy/customHeader.go create mode 100644 src/mod/dynamicproxy/dpcore/header.go diff --git a/src/mod/dynamicproxy/Server.go b/src/mod/dynamicproxy/Server.go index e67ea0c..2771059 100644 --- a/src/mod/dynamicproxy/Server.go +++ b/src/mod/dynamicproxy/Server.go @@ -39,9 +39,6 @@ func (h *ProxyHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { return } - //Inject headers - w.Header().Set("x-proxy-by", "zoraxy/"+h.Parent.Option.HostVersion) - /* Redirection Routing */ diff --git a/src/mod/dynamicproxy/customHeader.go b/src/mod/dynamicproxy/customHeader.go new file mode 100644 index 0000000..00177f2 --- /dev/null +++ b/src/mod/dynamicproxy/customHeader.go @@ -0,0 +1,46 @@ +package dynamicproxy + +/* + CustomHeader.go + + This script handle parsing and injecting custom headers + into the dpcore routing logic +*/ + +//SplitInboundOutboundHeaders split user defined headers into upstream and downstream headers +//return upstream header and downstream header key-value pairs +//if the header is expected to be deleted, the value will be set to empty string +func (ept *ProxyEndpoint) SplitInboundOutboundHeaders() ([][]string, [][]string) { + if len(ept.UserDefinedHeaders) == 0 { + //Early return if there are no defined headers + return [][]string{}, [][]string{} + } + + //Use pre-allocation for faster performance + upstreamHeaders := make([][]string, len(ept.UserDefinedHeaders)) + downstreamHeaders := make([][]string, len(ept.UserDefinedHeaders)) + upstreamHeaderCounter := 0 + downstreamHeaderCounter := 0 + + //Sort the headers into upstream or downstream + for _, customHeader := range ept.UserDefinedHeaders { + thisHeaderSet := make([]string, 2) + thisHeaderSet[0] = customHeader.Key + thisHeaderSet[1] = customHeader.Value + if customHeader.IsRemove { + //Prevent invalid config + thisHeaderSet[1] = "" + } + + //Assign to slice + if customHeader.Direction == HeaderDirection_ZoraxyToUpstream { + upstreamHeaders[upstreamHeaderCounter] = thisHeaderSet + upstreamHeaderCounter++ + } else if customHeader.Direction == HeaderDirection_ZoraxyToDownstream { + downstreamHeaders[downstreamHeaderCounter] = thisHeaderSet + downstreamHeaderCounter++ + } + } + + return upstreamHeaders, downstreamHeaders +} diff --git a/src/mod/dynamicproxy/dpcore/dpcore.go b/src/mod/dynamicproxy/dpcore/dpcore.go index a14a732..c5ff3c7 100644 --- a/src/mod/dynamicproxy/dpcore/dpcore.go +++ b/src/mod/dynamicproxy/dpcore/dpcore.go @@ -57,11 +57,14 @@ type ReverseProxy struct { } type ResponseRewriteRuleSet struct { - ProxyDomain string - OriginalHost string - UseTLS bool - NoCache bool - PathPrefix string //Vdir prefix for root, / will be rewrite to this + ProxyDomain string + OriginalHost string + UseTLS bool + NoCache bool + PathPrefix string //Vdir prefix for root, / will be rewrite to this + UpstreamHeaders [][]string + DownstreamHeaders [][]string + Version string //Version number of Zoraxy, use for X-Proxy-By } type requestCanceler interface { @@ -248,82 +251,6 @@ func (p *ReverseProxy) logf(format string, args ...interface{}) { } } -func removeHeaders(header http.Header, noCache bool) { - // Remove hop-by-hop headers listed in the "Connection" header. - if c := header.Get("Connection"); c != "" { - for _, f := range strings.Split(c, ",") { - if f = strings.TrimSpace(f); f != "" { - header.Del(f) - } - } - } - - // Remove hop-by-hop headers - for _, h := range hopHeaders { - if header.Get(h) != "" { - header.Del(h) - } - } - - //Restore the Upgrade header if any - if header.Get("Zr-Origin-Upgrade") != "" { - header.Set("Upgrade", header.Get("Zr-Origin-Upgrade")) - header.Del("Zr-Origin-Upgrade") - } - - //Disable cache if nocache is set - if noCache { - header.Del("Cache-Control") - header.Set("Cache-Control", "no-store") - } - - //Hide Go-HTTP-Client UA if the client didnt sent us one - if _, ok := header["User-Agent"]; !ok { - // If the outbound request doesn't have a User-Agent header set, - // don't send the default Go HTTP client User-Agent. - header.Set("User-Agent", "") - } - -} - -func addXForwardedForHeader(req *http.Request) { - if clientIP, _, err := net.SplitHostPort(req.RemoteAddr); err == nil { - // If we aren't the first proxy retain prior - // X-Forwarded-For information as a comma+space - // separated list and fold multiple headers into one. - if prior, ok := req.Header["X-Forwarded-For"]; ok { - clientIP = strings.Join(prior, ", ") + ", " + clientIP - } - req.Header.Set("X-Forwarded-For", clientIP) - if req.TLS != nil { - req.Header.Set("X-Forwarded-Proto", "https") - } else { - req.Header.Set("X-Forwarded-Proto", "http") - } - - if req.Header.Get("X-Real-Ip") == "" { - //Check if CF-Connecting-IP header exists - CF_Connecting_IP := req.Header.Get("CF-Connecting-IP") - Fastly_Client_IP := req.Header.Get("Fastly-Client-IP") - if CF_Connecting_IP != "" { - //Use CF Connecting IP - req.Header.Set("X-Real-Ip", CF_Connecting_IP) - } else if Fastly_Client_IP != "" { - //Use Fastly Client IP - req.Header.Set("X-Real-Ip", Fastly_Client_IP) - } else { - // Not exists. Fill it in with first entry in X-Forwarded-For - ips := strings.Split(clientIP, ",") - if len(ips) > 0 { - req.Header.Set("X-Real-Ip", strings.TrimSpace(ips[0])) - } - } - - } - - } -} - func (p *ReverseProxy) ProxyHTTP(rw http.ResponseWriter, req *http.Request, rrr *ResponseRewriteRuleSet) error { transport := p.Transport @@ -362,12 +289,18 @@ func (p *ReverseProxy) ProxyHTTP(rw http.ResponseWriter, req *http.Request, rrr outreq.Header = make(http.Header) copyHeader(outreq.Header, req.Header) - // Remove hop-by-hop headers listed in the "Connection" header, Remove hop-by-hop headers. + // Remove hop-by-hop headers. removeHeaders(outreq.Header, rrr.NoCache) // Add X-Forwarded-For Header. addXForwardedForHeader(outreq) + // Add user defined headers (to upstream) + injectUserDefinedHeaders(outreq.Header, rrr.UpstreamHeaders) + + // Rewrite outbound UA, must be after user headers + rewriteUserAgent(outreq.Header, "Zoraxy/"+rrr.Version) + res, err := transport.RoundTrip(outreq) if err != nil { if p.Verbal { @@ -398,13 +331,17 @@ func (p *ReverseProxy) ProxyHTTP(rw http.ResponseWriter, req *http.Request, rrr } } + //TODO: Figure out a way to proxy for proxmox //if res.StatusCode == 501 || res.StatusCode == 500 { // fmt.Println(outreq.Proto, outreq.RemoteAddr, outreq.RequestURI) // fmt.Println(">>>", outreq.Method, res.Header, res.ContentLength, res.StatusCode) // fmt.Println(outreq.Header, req.Host) //} - //Custom header rewriter functions + //Add debug X-Proxy-By tracker + res.Header.Set("x-proxy-by", "zoraxy/"+rrr.Version) + + //Custom Location header rewriter functions if res.Header.Get("Location") != "" { locationRewrite := res.Header.Get("Location") originLocation := res.Header.Get("Location") @@ -430,6 +367,9 @@ func (p *ReverseProxy) ProxyHTTP(rw http.ResponseWriter, req *http.Request, rrr res.Header.Set("Location", locationRewrite) } + // Add user defined headers (to downstream) + injectUserDefinedHeaders(res.Header, rrr.DownstreamHeaders) + // Copy header from response to client. copyHeader(rw.Header(), res.Header) diff --git a/src/mod/dynamicproxy/dpcore/header.go b/src/mod/dynamicproxy/dpcore/header.go new file mode 100644 index 0000000..40c029e --- /dev/null +++ b/src/mod/dynamicproxy/dpcore/header.go @@ -0,0 +1,121 @@ +package dpcore + +import ( + "net" + "net/http" + "strings" +) + +/* + Header.go + + This script handles headers rewrite and remove + in dpcore. + + Added in Zoraxy v3.0.6 by tobychui +*/ + +// removeHeaders Remove hop-by-hop headers listed in the "Connection" header, Remove hop-by-hop headers. +func removeHeaders(header http.Header, noCache bool) { + // Remove hop-by-hop headers listed in the "Connection" header. + if c := header.Get("Connection"); c != "" { + for _, f := range strings.Split(c, ",") { + if f = strings.TrimSpace(f); f != "" { + header.Del(f) + } + } + } + + // Remove hop-by-hop headers + for _, h := range hopHeaders { + if header.Get(h) != "" { + header.Del(h) + } + } + + //Restore the Upgrade header if any + if header.Get("Zr-Origin-Upgrade") != "" { + header.Set("Upgrade", header.Get("Zr-Origin-Upgrade")) + header.Del("Zr-Origin-Upgrade") + } + + //Disable cache if nocache is set + if noCache { + header.Del("Cache-Control") + header.Set("Cache-Control", "no-store") + } + +} + +// rewriteUserAgent rewrite the user agent based on incoming request +func rewriteUserAgent(header http.Header, UA string) { + //Hide Go-HTTP-Client UA if the client didnt sent us one + if header.Get("User-Agent") == "" { + // If the outbound request doesn't have a User-Agent header set, + // don't send the default Go HTTP client User-Agent + header.Del("User-Agent") + header.Set("User-Agent", UA) + } +} + +// Add X-Forwarded-For Header and rewrite X-Real-Ip according to sniffing logics +func addXForwardedForHeader(req *http.Request) { + if clientIP, _, err := net.SplitHostPort(req.RemoteAddr); err == nil { + // If we aren't the first proxy retain prior + // X-Forwarded-For information as a comma+space + // separated list and fold multiple headers into one. + if prior, ok := req.Header["X-Forwarded-For"]; ok { + clientIP = strings.Join(prior, ", ") + ", " + clientIP + } + req.Header.Set("X-Forwarded-For", clientIP) + if req.TLS != nil { + req.Header.Set("X-Forwarded-Proto", "https") + } else { + req.Header.Set("X-Forwarded-Proto", "http") + } + + if req.Header.Get("X-Real-Ip") == "" { + //Check if CF-Connecting-IP header exists + CF_Connecting_IP := req.Header.Get("CF-Connecting-IP") + Fastly_Client_IP := req.Header.Get("Fastly-Client-IP") + if CF_Connecting_IP != "" { + //Use CF Connecting IP + req.Header.Set("X-Real-Ip", CF_Connecting_IP) + } else if Fastly_Client_IP != "" { + //Use Fastly Client IP + req.Header.Set("X-Real-Ip", Fastly_Client_IP) + } else { + // Not exists. Fill it in with first entry in X-Forwarded-For + ips := strings.Split(clientIP, ",") + if len(ips) > 0 { + req.Header.Set("X-Real-Ip", strings.TrimSpace(ips[0])) + } + } + + } + + } +} + +// injectUserDefinedHeaders inject the user headers from slice +// if a value is empty string, the key will be removed from header. +// if a key is empty string, the function will return immediately +func injectUserDefinedHeaders(header http.Header, userHeaders [][]string) { + for _, userHeader := range userHeaders { + if len(userHeader) == 0 { + //End of header slice + return + } + headerKey := userHeader[0] + headerValue := userHeader[1] + if headerValue == "" { + //Remove header from head + header.Del(headerKey) + continue + } + + //Default: Set header value + header.Del(headerKey) //Remove header if it already exists + header.Set(headerKey, headerValue) + } +} diff --git a/src/mod/dynamicproxy/dynamicproxy.go b/src/mod/dynamicproxy/dynamicproxy.go index 3413033..7532d09 100644 --- a/src/mod/dynamicproxy/dynamicproxy.go +++ b/src/mod/dynamicproxy/dynamicproxy.go @@ -142,6 +142,7 @@ func (router *Router) StartProxyService() error { OriginalHost: originalHostHeader, UseTLS: sep.RequireTLS, PathPrefix: "", + Version: sep.parent.Option.HostVersion, }) return } diff --git a/src/mod/dynamicproxy/endpoints.go b/src/mod/dynamicproxy/endpoints.go index d403110..0cc7b70 100644 --- a/src/mod/dynamicproxy/endpoints.go +++ b/src/mod/dynamicproxy/endpoints.go @@ -30,7 +30,6 @@ func (ep *ProxyEndpoint) UserDefinedHeaderExists(key string) bool { return true } } - return false } @@ -49,16 +48,13 @@ func (ep *ProxyEndpoint) RemoveUserDefinedHeader(key string) error { } // Add a user defined header to the list, duplicates will be automatically removed -func (ep *ProxyEndpoint) AddUserDefinedHeader(key string, value string) error { - if ep.UserDefinedHeaderExists(key) { - ep.RemoveUserDefinedHeader(key) +func (ep *ProxyEndpoint) AddUserDefinedHeader(newHeaderRule *UserDefinedHeader) error { + if ep.UserDefinedHeaderExists(newHeaderRule.Key) { + ep.RemoveUserDefinedHeader(newHeaderRule.Key) } - ep.UserDefinedHeaders = append(ep.UserDefinedHeaders, &UserDefinedHeader{ - Key: cases.Title(language.Und, cases.NoLower).String(key), //e.g. x-proxy-by -> X-Proxy-By - Value: value, - }) - + newHeaderRule.Key = cases.Title(language.Und, cases.NoLower).String(newHeaderRule.Key) + ep.UserDefinedHeaders = append(ep.UserDefinedHeaders, newHeaderRule) return nil } diff --git a/src/mod/dynamicproxy/proxyRequestHandler.go b/src/mod/dynamicproxy/proxyRequestHandler.go index d268e6e..6cc727d 100644 --- a/src/mod/dynamicproxy/proxyRequestHandler.go +++ b/src/mod/dynamicproxy/proxyRequestHandler.go @@ -111,13 +111,6 @@ func (h *ProxyHandler) hostRequest(w http.ResponseWriter, r *http.Request, targe r.Header.Set("X-Forwarded-Host", r.Host) r.Header.Set("X-Forwarded-Server", "zoraxy-"+h.Parent.Option.HostUUID) - //Inject custom headers - if len(target.UserDefinedHeaders) > 0 { - for _, customHeader := range target.UserDefinedHeaders { - r.Header.Set(customHeader.Key, customHeader.Value) - } - } - requestURL := r.URL.String() if r.Header["Upgrade"] != nil && strings.ToLower(r.Header["Upgrade"][0]) == "websocket" { //Handle WebSocket request. Forward the custom Upgrade header and rewrite origin @@ -152,12 +145,18 @@ func (h *ProxyHandler) hostRequest(w http.ResponseWriter, r *http.Request, targe r.URL, _ = url.Parse(originalHostHeader) } + //Build downstream and upstream header rules + upstreamHeaders, downstreamHeaders := target.SplitInboundOutboundHeaders() + err := target.proxy.ServeHTTP(w, r, &dpcore.ResponseRewriteRuleSet{ - ProxyDomain: target.Domain, - OriginalHost: originalHostHeader, - UseTLS: target.RequireTLS, - NoCache: h.Parent.Option.NoCache, - PathPrefix: "", + ProxyDomain: target.Domain, + OriginalHost: originalHostHeader, + UseTLS: target.RequireTLS, + NoCache: h.Parent.Option.NoCache, + PathPrefix: "", + UpstreamHeaders: upstreamHeaders, + DownstreamHeaders: downstreamHeaders, + Version: target.parent.Option.HostVersion, }) var dnsError *net.DNSError @@ -184,13 +183,6 @@ func (h *ProxyHandler) vdirRequest(w http.ResponseWriter, r *http.Request, targe r.Header.Set("X-Forwarded-Host", r.Host) r.Header.Set("X-Forwarded-Server", "zoraxy-"+h.Parent.Option.HostUUID) - //Inject custom headers - if len(target.parent.UserDefinedHeaders) > 0 { - for _, customHeader := range target.parent.UserDefinedHeaders { - r.Header.Set(customHeader.Key, customHeader.Value) - } - } - if r.Header["Upgrade"] != nil && strings.ToLower(r.Header["Upgrade"][0]) == "websocket" { //Handle WebSocket request. Forward the custom Upgrade header and rewrite origin r.Header.Set("Zr-Origin-Upgrade", "websocket") @@ -219,11 +211,17 @@ func (h *ProxyHandler) vdirRequest(w http.ResponseWriter, r *http.Request, targe r.URL, _ = url.Parse(originalHostHeader) } + //Build downstream and upstream header rules + upstreamHeaders, downstreamHeaders := target.parent.SplitInboundOutboundHeaders() + err := target.proxy.ServeHTTP(w, r, &dpcore.ResponseRewriteRuleSet{ - ProxyDomain: target.Domain, - OriginalHost: originalHostHeader, - UseTLS: target.RequireTLS, - PathPrefix: target.MatchingPath, + ProxyDomain: target.Domain, + OriginalHost: originalHostHeader, + UseTLS: target.RequireTLS, + PathPrefix: target.MatchingPath, + UpstreamHeaders: upstreamHeaders, + DownstreamHeaders: downstreamHeaders, + Version: target.parent.parent.Option.HostVersion, }) var dnsError *net.DNSError diff --git a/src/mod/dynamicproxy/typedef.go b/src/mod/dynamicproxy/typedef.go index 04ded0c..3386aa6 100644 --- a/src/mod/dynamicproxy/typedef.go +++ b/src/mod/dynamicproxy/typedef.go @@ -86,7 +86,6 @@ type UserDefinedHeader struct { Key string Value string IsRemove bool //Instead of set, remove this key instead - IsAppend bool //Instead of set, append to the current one with "," as seperator } // A Virtual Directory endpoint, provide a subset of ProxyEndpoint for better diff --git a/src/mod/email/email.go b/src/mod/email/email.go index 36946fc..978af60 100644 --- a/src/mod/email/email.go +++ b/src/mod/email/email.go @@ -42,17 +42,22 @@ SendEmail( ) */ func (s *Sender) SendEmail(to string, subject string, content string) error { - //Parse the email content + // Parse the email content msg := []byte("To: " + to + "\n" + "From: Zoraxy <" + s.SenderAddr + ">\n" + "Subject: " + subject + "\n" + "MIME-version: 1.0;\nContent-Type: text/html; charset=\"UTF-8\";\n\n" + content + "\n\n") - //Login to the SMTP server - //Username can be username (e.g. admin) or email (e.g. admin@example.com), depending on SMTP service provider - auth := smtp.PlainAuth("", s.Username, s.Password, s.Hostname) + // Initialize the auth variable + var auth smtp.Auth + if s.Password != "" { + // Login to the SMTP server + // Username can be username (e.g. admin) or email (e.g. admin@example.com), depending on SMTP service provider + auth = smtp.PlainAuth("", s.Username, s.Password, s.Hostname) + } + // Send the email err := smtp.SendMail(s.Hostname+":"+strconv.Itoa(s.Port), auth, s.SenderAddr, []string{to}, msg) if err != nil { return err diff --git a/src/reverseproxy.go b/src/reverseproxy.go index eb084f1..e2113da 100644 --- a/src/reverseproxy.go +++ b/src/reverseproxy.go @@ -1076,9 +1076,9 @@ func HandleCustomHeaderList(w http.ResponseWriter, r *http.Request) { // Add a new header to the target endpoint func HandleCustomHeaderAdd(w http.ResponseWriter, r *http.Request) { - epType, err := utils.PostPara(r, "type") + rewriteType, err := utils.PostPara(r, "type") if err != nil { - utils.SendErrorResponse(w, "endpoint type not defined") + utils.SendErrorResponse(w, "rewriteType not defined") return } @@ -1088,6 +1088,12 @@ func HandleCustomHeaderAdd(w http.ResponseWriter, r *http.Request) { return } + direction, err := utils.PostPara(r, "direction") + if err != nil { + utils.SendErrorResponse(w, "HTTP modifiy direction not set") + return + } + name, err := utils.PostPara(r, "name") if err != nil { utils.SendErrorResponse(w, "HTTP header name not set") @@ -1095,26 +1101,46 @@ func HandleCustomHeaderAdd(w http.ResponseWriter, r *http.Request) { } value, err := utils.PostPara(r, "value") - if err != nil { + if err != nil && rewriteType == "add" { utils.SendErrorResponse(w, "HTTP header value not set") return } - var targetProxyEndpoint *dynamicproxy.ProxyEndpoint - if epType == "root" { - targetProxyEndpoint = dynamicProxyRouter.Root - } else { - ep, err := dynamicProxyRouter.LoadProxy(domain) - if err != nil { - utils.SendErrorResponse(w, "target endpoint not exists") - return - } + targetProxyEndpoint, err := dynamicProxyRouter.LoadProxy(domain) + if err != nil { + utils.SendErrorResponse(w, "target endpoint not exists") + return + } - targetProxyEndpoint = ep + //Create a Custom Header Defination type + var rewriteDirection dynamicproxy.HeaderDirection + if direction == "toOrigin" { + rewriteDirection = dynamicproxy.HeaderDirection_ZoraxyToUpstream + } else if direction == "toClient" { + rewriteDirection = dynamicproxy.HeaderDirection_ZoraxyToDownstream + } else { + //Unknown direction + utils.SendErrorResponse(w, "header rewrite direction not supported") + return + } + + isRemove := false + if rewriteType == "remove" { + isRemove = true + } + headerRewriteDefination := dynamicproxy.UserDefinedHeader{ + Key: name, + Value: value, + Direction: rewriteDirection, + IsRemove: isRemove, } //Create a new custom header object - targetProxyEndpoint.AddUserDefinedHeader(name, value) + err = targetProxyEndpoint.AddUserDefinedHeader(&headerRewriteDefination) + if err != nil { + utils.SendErrorResponse(w, "unable to add header rewrite rule: "+err.Error()) + return + } //Save it (no need reload as header are not handled by dpcore) err = SaveReverseProxyConfig(targetProxyEndpoint) @@ -1128,12 +1154,6 @@ func HandleCustomHeaderAdd(w http.ResponseWriter, r *http.Request) { // Remove a header from the target endpoint func HandleCustomHeaderRemove(w http.ResponseWriter, r *http.Request) { - epType, err := utils.PostPara(r, "type") - if err != nil { - utils.SendErrorResponse(w, "endpoint type not defined") - return - } - domain, err := utils.PostPara(r, "domain") if err != nil { utils.SendErrorResponse(w, "domain or matching rule not defined") @@ -1146,20 +1166,17 @@ func HandleCustomHeaderRemove(w http.ResponseWriter, r *http.Request) { return } - var targetProxyEndpoint *dynamicproxy.ProxyEndpoint - if epType == "root" { - targetProxyEndpoint = dynamicProxyRouter.Root - } else { - ep, err := dynamicProxyRouter.LoadProxy(domain) - if err != nil { - utils.SendErrorResponse(w, "target endpoint not exists") - return - } - - targetProxyEndpoint = ep + targetProxyEndpoint, err := dynamicProxyRouter.LoadProxy(domain) + if err != nil { + utils.SendErrorResponse(w, "target endpoint not exists") + return } - targetProxyEndpoint.RemoveUserDefinedHeader(name) + err = targetProxyEndpoint.RemoveUserDefinedHeader(name) + if err != nil { + utils.SendErrorResponse(w, "unable to remove header rewrite rule: "+err.Error()) + return + } err = SaveReverseProxyConfig(targetProxyEndpoint) if err != nil { diff --git a/src/web/components/status.html b/src/web/components/status.html index 69f705b..9bfd908 100644 --- a/src/web/components/status.html +++ b/src/web/components/status.html @@ -68,12 +68,13 @@

Global Settings

-

Inbound Port (Port to be proxied)

+

Inbound Port (Reverse Proxy Listening Port)

+ Click "Apply" button to confirm listening port changes - +
-
+

@@ -160,6 +161,7 @@