Browse Source

auto update script executed

Toby Chui 1 year ago
parent
commit
a16faf63c1

+ 2 - 2
api.go

@@ -57,8 +57,8 @@ func initAPIs() {
 	authRouter.HandleFunc("/api/proxy/listenPort80", HandleUpdatePort80Listener)
 	authRouter.HandleFunc("/api/proxy/requestIsProxied", HandleManagementProxyCheck)
 	//Reverse proxy root related APIs
-	authRouter.HandleFunc("/api/proxy/root/listOptions", HandleRootRouteOptionList)
-	authRouter.HandleFunc("/api/proxy/root/updateOptions", HandleRootRouteOptionsUpdate)
+	//authRouter.HandleFunc("/api/proxy/root/listOptions", HandleRootRouteOptionList)
+	//authRouter.HandleFunc("/api/proxy/root/updateOptions", HandleRootRouteOptionsUpdate)
 	//Reverse proxy auth related APIs
 	authRouter.HandleFunc("/api/proxy/auth/exceptions/list", ListProxyBasicAuthExceptionPaths)
 	authRouter.HandleFunc("/api/proxy/auth/exceptions/add", AddProxyBasicAuthExceptionPaths)

+ 0 - 7
mod/dynamicproxy/dynamicproxy.go

@@ -84,13 +84,6 @@ func (router *Router) StartProxyService() error {
 		return errors.New("Reverse proxy router root not set")
 	}
 
-	//Load root options from file
-	loadedRootOption, err := loadRootRoutingOptionsFromFile()
-	if err != nil {
-		return err
-	}
-	router.RootRoutingOptions = loadedRootOption
-
 	minVersion := tls.VersionTLS10
 	if router.Option.ForceTLSLatest {
 		minVersion = tls.VersionTLS12

+ 0 - 51
mod/dynamicproxy/rootRoute.go

@@ -1,51 +0,0 @@
-package dynamicproxy
-
-import (
-	"encoding/json"
-	"errors"
-	"log"
-	"os"
-
-	"imuslab.com/zoraxy/mod/utils"
-)
-
-/*
-	rootRoute.go
-
-	This script handle special case in routing where the root proxy
-	entity is involved. This also include its setting object
-	RootRoutingOptions
-*/
-
-var rootConfigFilepath string = "conf/root_config.json"
-
-func loadRootRoutingOptionsFromFile() (*RootRoutingOptions, error) {
-	if !utils.FileExists(rootConfigFilepath) {
-		//Not found. Create a root option
-		js, _ := json.MarshalIndent(RootRoutingOptions{}, "", " ")
-		err := os.WriteFile(rootConfigFilepath, js, 0775)
-		if err != nil {
-			return nil, errors.New("Unable to write root config to file: " + err.Error())
-		}
-	}
-	newRootOption := RootRoutingOptions{}
-	rootOptionsBytes, err := os.ReadFile(rootConfigFilepath)
-	if err != nil {
-		log.Println("[Error] Unable to read root config file at " + rootConfigFilepath + ": " + err.Error())
-		return nil, err
-	}
-	err = json.Unmarshal(rootOptionsBytes, &newRootOption)
-	if err != nil {
-		log.Println("[Error] Unable to parse root config file: " + err.Error())
-		return nil, err
-	}
-
-	return &newRootOption, nil
-}
-
-// Save the new config to file. Note that this will not overwrite the runtime one
-func (opt *RootRoutingOptions) SaveToFile() error {
-	js, _ := json.MarshalIndent(opt, "", " ")
-	err := os.WriteFile(rootConfigFilepath, js, 0775)
-	return err
-}

+ 47 - 25
mod/dynamicproxy/typedef.go

@@ -37,16 +37,15 @@ type RouterOption struct {
 }
 
 type Router struct {
-	Option             *RouterOption
-	ProxyEndpoints     *sync.Map
-	SubdomainEndpoint  *sync.Map
-	Running            bool
-	Root               *ProxyEndpoint
-	RootRoutingOptions *RootRoutingOptions
-	mux                http.Handler
-	server             *http.Server
-	tlsListener        net.Listener
-	routingRules       []*RoutingRule
+	Option            *RouterOption
+	ProxyEndpoints    *sync.Map
+	SubdomainEndpoint *sync.Map
+	Running           bool
+	Root              *ProxyEndpoint
+	mux               http.Handler
+	server            *http.Server
+	tlsListener       net.Listener
+	routingRules      []*RoutingRule
 
 	tlsRedirectStop chan bool      //Stop channel for tls redirection server
 	tldMap          map[string]int //Top level domain map, see tld.json
@@ -69,23 +68,46 @@ type BasicAuthExceptionRule struct {
 	PathPrefix string
 }
 
-// A proxy endpoint record
+// A proxy endpoint record, a general interface for handling inbound routing
 type ProxyEndpoint struct {
-	ProxyType               int                       //The type of this proxy, see const def
-	RootOrMatchingDomain    string                    //Root for vdir or Matching domain for subd, also act as key
-	Domain                  string                    //Domain or IP to proxy to
-	RequireTLS              bool                      //Target domain require TLS
-	BypassGlobalTLS         bool                      //Bypass global TLS setting options if TLS Listener enabled (parent.tlsListener != nil)
-	SkipCertValidations     bool                      //Set to true to accept self signed certs
+	ProxyType            int    //The type of this proxy, see const def
+	RootOrMatchingDomain string //Root for vdir or Matching domain for subd, also act as key
+	Domain               string //Domain or IP to proxy to
+
+	//TLS/SSL Related
+	RequireTLS          bool //Target domain require TLS
+	BypassGlobalTLS     bool //Bypass global TLS setting options if TLS Listener enabled (parent.tlsListener != nil)
+	SkipCertValidations bool //Set to true to accept self signed certs
+
+	//Virtual Directories
+	VirtualDirectories []*ProxyEndpoint
+
+	//Authentication
 	RequireBasicAuth        bool                      //Set to true to request basic auth before proxy
 	BasicAuthCredentials    []*BasicAuthCredentials   `json:"-"` //Basic auth credentials
 	BasicAuthExceptionRules []*BasicAuthExceptionRule //Path to exclude in a basic auth enabled proxy target
-	Proxy                   *dpcore.ReverseProxy      `json:"-"`
 
-	parent *Router
+	//Internal Logic Elements
+	Proxy                *dpcore.ReverseProxy `json:"-"`
+	OriginalRouteOptions interface{}          //Route options from original structure, may carry additional information for edge cases
+	parent               *Router
 }
 
+/*
+	Routing type specific interface
+	These are options that only avaible for a specific interface
+	when running, these are converted into "ProxyEndpoint" objects
+	for more generic routing logic
+*/
+
 // Root options are those that are required for reverse proxy handler to work
+const (
+	DefaultSite_InternalStaticWebServer = 0
+	DefaultSite_ReverseProxy            = 1
+	DefaultSite_Redirect                = 2
+	DefaultSite_NotFoundPage            = 3
+)
+
 type RootOptions struct {
 	ProxyLocation       string //Proxy Root target, all unset traffic will be forward to here
 	RequireTLS          bool   //Proxy root target require TLS connection (not recommended)
@@ -96,15 +118,13 @@ type RootOptions struct {
 	RequireBasicAuth        bool //Require basic auth, CURRENTLY NOT USED
 	BasicAuthCredentials    []*BasicAuthCredentials
 	BasicAuthExceptionRules []*BasicAuthExceptionRule
-}
 
-// Additional options are here for letting router knows how to route exception cases for root
-type RootRoutingOptions struct {
-	//Root only configs
-	EnableRedirectForUnsetRules bool   //Force unset rules to redirect to custom domain
-	UnsetRuleRedirectTarget     string //Custom domain to redirect to for unset rules
+	//Default Site Related
+	UnknownHostOption int    //What to do when hit with unknown host. See DefaultSite_* Options
+	UnknownHostTarget string //Target if the action is redirect or proxy
 }
 
+// Virtual Directory routing options
 type VdirOptions struct {
 	RootName                string
 	Domain                  string
@@ -116,6 +136,7 @@ type VdirOptions struct {
 	BasicAuthExceptionRules []*BasicAuthExceptionRule
 }
 
+// Subdomain routing options
 type SubdOptions struct {
 	MatchingDomain          string
 	Domain                  string
@@ -123,6 +144,7 @@ type SubdOptions struct {
 	BypassGlobalTLS         bool
 	SkipCertValidations     bool
 	RequireBasicAuth        bool
+	VirtualDirectories      []*VdirOptions
 	BasicAuthCredentials    []*BasicAuthCredentials
 	BasicAuthExceptionRules []*BasicAuthExceptionRule
 }

+ 0 - 31
reverseproxy.go

@@ -891,34 +891,3 @@ func HandleIncomingPortSet(w http.ResponseWriter, r *http.Request) {
 
 	utils.SendOK(w)
 }
-
-// Handle list of root route options
-func HandleRootRouteOptionList(w http.ResponseWriter, r *http.Request) {
-	js, _ := json.Marshal(dynamicProxyRouter.RootRoutingOptions)
-	utils.SendJSONResponse(w, string(js))
-}
-
-// Handle update of the root route edge case options. See dynamicproxy/rootRoute.go
-func HandleRootRouteOptionsUpdate(w http.ResponseWriter, r *http.Request) {
-	enableUnsetSubdomainRedirect, err := utils.PostBool(r, "unsetRedirect")
-	if err != nil {
-		utils.SendErrorResponse(w, err.Error())
-		return
-	}
-
-	unsetRedirectTarget, _ := utils.PostPara(r, "unsetRedirectTarget")
-
-	newRootOption := dynamicproxy.RootRoutingOptions{
-		EnableRedirectForUnsetRules: enableUnsetSubdomainRedirect,
-		UnsetRuleRedirectTarget:     unsetRedirectTarget,
-	}
-
-	dynamicProxyRouter.RootRoutingOptions = &newRootOption
-	err = newRootOption.SaveToFile()
-	if err != nil {
-		utils.SendErrorResponse(w, err.Error())
-		return
-	}
-
-	utils.SendOK(w)
-}

+ 92 - 88
web/components/rproot.html

@@ -1,54 +1,65 @@
 <div class="standardContainer">
     <div class="ui basic segment">
         <h2>Default Site</h2>
-        <p>What to show when Zoraxy is hit with an unknown Host</p>
-
+        <p>Default routing options for inbound traffic (previously called Proxy Root)</p>
         <div class="ui form">
-            <div class="field">
-                <div class="ui checkbox">
-                    <input type="checkbox" id="useStaticWebServer" onchange="handleUseStaticWebServerAsRoot()">
-                    <label>Internal Static Web Server <br><small>Check this if you prefer a more Apache / Nginx like experience</small></label>
+            <div class="grouped fields">
+                <label>What to show when Zoraxy is hit with an unknown Host?</label>
+                <div class="field">
+                    <div class="ui radio defaultsite checkbox">
+                        <input type="radio" name="defaultsiteOption" checked="checked" value="webserver">
+                        <label>Internal Static Web Server<br>
+                            <small>Check this if you prefer a more Apache / Nginx like experience</small>
+                        </label>
+                    </div>
                 </div>
-            </div>
-            <div class="ui horizontal divider">OR</div>
-            <div class="field">
-                <label>Reverse Proxy Target</label>
-                <input type="text" id="proxyRoot" onchange="checkRootRequireTLS(this.value);">
-                <small>E.g. localhost:8080</small>
-            </div>
-            <div class="field">
-                <div class="ui checkbox">
-                    <input type="checkbox" id="rootReqTLS">
-                    <label>Reverse proxy target require TLS connection <br><small>Check this if your proxy root URL starts with https://</small></label>
+                <div class="field">
+                    <div class="ui radio defaultsite checkbox">
+                        <input type="radio" name="defaultsiteOption" value="proxy">
+                        <label>Reverse Proxy Target<br>
+                            <small>Proxy the request to a target IP / domain</small>
+                        </label>
+                    </div>
                 </div>
-            </div>
-
-            
-            <br>
-            <button class="ui basic button" onclick="setProxyRoot()"><i class="teal home icon" ></i> Update Proxy Root</button>
-            <div class="ui divider"></div>
-            <div class="field">
-                <h4>Root Routing Options</h4>
-            </div>
-            <div class="field">
-                <div class="ui checkbox">
-                    <input type="checkbox" id="unsetRedirect">
-                    <label>Enable redirect for unset subdomains <br><small>Redirect subdomain that is not found to custom domain</small></label>
+                <div class="field">
+                    <div class="ui radio defaultsite checkbox">
+                        <input type="radio" name="defaultsiteOption" value="redirect">
+                        <label>Redirect<br>
+                            <small>Redirect the user to a new location</small>
+                        </label>
+                    </div>
+                </div>
+                <div class="field">
+                    <div class="ui radio defaultsite checkbox">
+                        <input type="radio" name="defaultsiteOption" value="notfound">
+                        <label>Show 404 NOT FOUND<br>
+                            <small>Respond to request with a 404 page</small>
+                        </label>
+                    </div>
                 </div>
             </div>
-            <div class="ui basic segment" id="unsetRedirectDomainWrapper" style="background-color: #f7f7f7; border-radius: 1em; margin-left: 2em; padding-left: 2em; display:none;">
-                <div style="
-                    position: absolute;
-                    top:0;
-                    left: 1em;
-                    width: 0px;
-                    height: 0px;
-                    margin-top: -10px;
-                    border-left: 10px solid transparent;
-                    border-right: 10px solid transparent;
-                    border-bottom: 10px solid #f7f7f7;">
+        </div>
 
+        <!-- Reverse Proxy as Default Site Options -->
+        <div id="defaultSiteProxyOptions" class="ui basic segment advanceoptions defaultSiteOptionDetails" style="display:none; ">
+            <div class="ui form">
+                <div class="field">
+                        <label>Reverse Proxy Target</label>
+                        <input type="text" id="proxyRoot" onchange="checkRootRequireTLS(this.value);">
+                        <small>e.g. localhost:8080 / 192.168.0.100:80 / example.com</small>
+                </div>
+                <div class="field">
+                    <div class="ui checkbox">
+                        <input type="checkbox" id="rootReqTLS">
+                        <label>Reverse proxy target require TLS connection <br><small>Check this if your proxy target URL require connection with https://</small></label>
+                    </div>
                 </div>
+            </div>
+        </div>
+        
+        <!-- Redirect as default site Options-->
+        <div id="defaultSiteRedirectOptions" class="ui basic segment advanceoptions defaultSiteOptionDetails" style="display:none;"">
+            <div class="ui form">
                 <div class="field">
                     <label>Redirect target domain</label>
                     <div class="ui input">
@@ -58,40 +69,54 @@
                     Leave empty for redirecting to upper level domain (e.g. notfound.example.com <i class="right arrow icon"></i> example.com)</small>
                 </div>
             </div>
-            <br>
-            <button class="ui basic button" onclick="updateRootOptions()"><i class="blue save icon" ></i> Save Root Options</button>
         </div>
-        <br>
-        
+
+        <button class="ui basic button" onclick="setProxyRoot()"><i class="green save icon" ></i> Save Options</button>
     </div>
 </div>
 <script>
+    let currentDefaultSiteOption = "webserver";
     $("#advanceRootSettings").accordion();
 
-    function handleUseStaticWebServerAsRoot(){
-        let useStaticWebServer = $("#useStaticWebServer")[0].checked;
-        if (useStaticWebServer){
+    //Handle toggle events of option radio boxes
+    function updateAvaibleDefaultSiteOptions(){
+        let selectedDefaultSite = $('input[name="defaultsiteOption"]:checked').val();
+
+        $(".defaultSiteOptionDetails").hide();
+        if (selectedDefaultSite == "webserver"){
+            //Use build in web server as target
             let staticWebServerURL = "127.0.0.1:" + $("#webserv_listenPort").val();
             $("#proxyRoot").val(staticWebServerURL);
             $("#proxyRoot").parent().addClass("disabled");
             $("#rootReqTLS").parent().checkbox("set unchecked");
             $("#rootReqTLS").parent().addClass("disabled");
 
-            //Check if web server is enabled. If not, ask if the user want to enable it
-            /*if (!$("#webserv_enable").parent().checkbox("is checked")){
-                confirmBox("Enable static web server now?", function(choice){
-                    if (choice == true){
-                        $("#webserv_enable").parent().checkbox("set checked");
-                    }
-                });
-            }*/
-        }else{
+        }else if (selectedDefaultSite == "proxy"){
+            $("#defaultSiteProxyOptions").show();
             $("#rootReqTLS").parent().removeClass("disabled");
             $("#proxyRoot").parent().removeClass("disabled");
             initRootInfo();
+        }else if (selectedDefaultSite == "redirect"){
+            $("#defaultSiteRedirectOptions").show();
+        }else if (selectedDefaultSite == "notfound"){
+
+        }else{
+            //Unknown option
+            return;
         }
+
+        currentDefaultSiteOption = selectedDefaultSite;
+    }
+
+    //Bind events to the radio boxes
+    function bindDefaultSiteRadioCheckboxEvents(){
+        $('input[type=radio][name=defaultsiteOption]').change(function() {
+            updateAvaibleDefaultSiteOptions();
+        });
     }
     
+
+    
     function initRootInfo(callback=undefined){
         $.get("/api/proxy/list?type=root", function(data){
             if (data == null){
@@ -107,18 +132,22 @@
         });
     }
     initRootInfo(function(){
-        updateWebServerLinkSettings();
+        updateWebServerLinkSettings(function(){
+            bindDefaultSiteRadioCheckboxEvents();
+        });
     });
 
     //Update the current web server port settings
-    function updateWebServerLinkSettings(){
+    function updateWebServerLinkSettings(callback=undefined){
         isUsingStaticWebServerAsRoot(function(isUsingWebServ){
             if (isUsingWebServ){
-                $(".webservRootDisabled").addClass("disabled");
-                $("#useStaticWebServer").parent().checkbox("set checked");
+                //Select the 
             }else{
-                $(".webservRootDisabled").removeClass("disabled");
-                $("#useStaticWebServer").parent().checkbox("set unchecked");
+                
+            }
+
+            if (callback != undefined){
+                callback(isUsingWebServ);
             }
         })
     }
@@ -150,31 +179,6 @@
         updateRootSettingStates();
     }
 
-    //Toggle the display status of the input box for domain setting
-    function updateRedirectionDomainSettingInputBox(useRedirect){
-        if(useRedirect){
-            $("#unsetRedirectDomainWrapper").stop().finish().slideDown("fast");
-        }else{
-            $("#unsetRedirectDomainWrapper").stop().finish().slideUp("fast");
-        }
-    }
-
-    function checkCustomRedirectForUnsetSubd(){
-        $.get("/api/proxy/root/listOptions", function(data){
-            $("#unsetRedirect")[0].checked = data.EnableRedirectForUnsetRules || false;
-            $("#unsetRedirectDomain").val(data.UnsetRuleRedirectTarget);
-            updateRedirectionDomainSettingInputBox(data.EnableRedirectForUnsetRules);
-
-            //Bind event to the checkbox
-            $("#unsetRedirect").off("change").on("change", function(){
-                let useRedirect = $("#unsetRedirect")[0].checked;
-                updateRedirectionDomainSettingInputBox(useRedirect);
-            });
-        });
-       
-    }
-    checkCustomRedirectForUnsetSubd();
-
     //Check if the given domain will redirect to https
     function checkRootRequireTLS(targetDomain){
         //Trim off the http or https from the origin

+ 14 - 10
web/components/status.html

@@ -51,17 +51,23 @@
         </div>
     </div>
 </div>
-
-<div id="networkActWrapper" class="standardContainer" style="position: relative; margin-top: 1em;">
+<div class="standardContainer" style="padding-bottom: 0 !important;">
+    <!-- Power Buttons-->
+    <button id="startbtn" class="ui basic button" onclick="startService();"><i class="ui green arrow alternate circle up icon"></i> Start Service</button>
+    <button id="stopbtn" class="ui basic notloopbackOnly disabled button" onclick="stopService();"><i class="ui red minus circle icon"></i> Stop Service</button>
+    <div class="ui divider"></div>
+    <h4>Network Status</h4>
+    <p>Overall Network I/O in Current Host Server</p>
+</div>
+<div id="networkActWrapper" class="standardContainer" style="position: relative;">
     <canvas id="networkActivity"></canvas>
 </div>
 <div id="networkActivityPlaceHolder">
     <p style="opacity: 0.5;"> Graph Render Paused</p>
 </div>
-
-<br>
 <div class="standardContainer">
-    <h4>Basic Settings</h4>
+    <div class="ui divider"></div>
+    <h4>Global Settings</h4>
     <p>Inbound Port (Port to be proxied)</p>
     <div class="ui action fluid notloopbackOnly input">
         <input type="text" id="incomingPort" placeholder="Incoming Port" value="80">
@@ -100,9 +106,7 @@
             </div>
         </div>
     </div>
-    <br>
-    <button id="startbtn" class="ui basic button" onclick="startService();"><i class="ui green arrow alternate circle up icon"></i> Start Service</button>
-    <button id="stopbtn" class="ui basic notloopbackOnly disabled button" onclick="stopService();"><i class="ui red minus circle icon"></i> Stop Service</button>
+   
     <div id="rploopbackWarning" class="ui segment" style="display:none;">
         <b><i class="yellow warning icon"></i> Loopback Routing Warning</b><br>
         <small>This management interface is a loopback proxied service. <br>If you want to shutdown the reverse proxy server, please remove the proxy rule for the management interface and refresh.</small>
@@ -113,7 +117,7 @@
     <div class="ui two column stackable grid">
         <div class="column">
         <p>Visitor Counts</p>
-        <table class="ui unstackable inverted celled table">
+        <table class="ui unstackable very basic celled table">
             <thead>
             <tr>
                 <th>Country ISO Code</th>
@@ -129,7 +133,7 @@
         </div>
         <div class="column">
         <p>Proxy Request Types</p>
-        <table class="ui unstackable inverted celled table">
+        <table class="ui unstackable very basic celled table">
             <thead>
             <tr>
                 <th>Proxy Type</th>

+ 11 - 5
web/main.css

@@ -305,7 +305,7 @@ body{
 }
 
 .ui.secondary.vertical.menu .active.item{
-    background: linear-gradient(60deg, rgba(84,58,183,1) 0%, rgba(0,172,193,1) 100%);
+    background: var(--theme_background);
     font-weight: 600;
     color: white;
 }
@@ -314,12 +314,18 @@ body{
     animation: blinker 3s ease-in-out infinite;
 }
 
-.bluefont{
-    color: #417ac1 !important;
+.ui.important.basic.segment{
+    background: linear-gradient(217deg, rgba(234,238,175,1) 16%, rgba(254,255,242,1) 78%);
+    border-radius: 1em;
 }
 
-.ui.inverted.table{
-    background: var(--theme_background);
+.basic.segment.advanceoptions{
+    background-color: #f7f7f7; 
+    border-radius: 1em;
+}
+
+.bluefont{
+    color: #417ac1 !important;
 }
 
 @keyframes blinker {