Browse Source

auto update script executed

Toby Chui 1 year ago
parent
commit
e26da3de7f
5 changed files with 99 additions and 6 deletions
  1. 2 1
      go.mod
  2. 47 0
      mod/dynamicproxy/endpoints.go
  3. 9 0
      mod/dynamicproxy/typedef.go
  4. 2 0
      reverseproxy.go
  5. 39 5
      web/components/httprp.html

+ 2 - 1
go.mod

@@ -10,10 +10,11 @@ require (
 	github.com/gorilla/sessions v1.2.1
 	github.com/gorilla/websocket v1.5.0
 	github.com/grandcat/zeroconf v1.0.0
-	github.com/grokify/html-strip-tags-go v0.1.0 // indirect
+	github.com/grokify/html-strip-tags-go v0.1.0
 	github.com/likexian/whois v1.15.1
 	github.com/microcosm-cc/bluemonday v1.0.25
 	golang.org/x/net v0.14.0
 	golang.org/x/sys v0.11.0
+	golang.org/x/text v0.12.0
 	golang.org/x/tools v0.12.0 // indirect
 )

+ 47 - 0
mod/dynamicproxy/endpoints.go

@@ -4,6 +4,9 @@ import (
 	"encoding/json"
 	"errors"
 	"strings"
+
+	"golang.org/x/text/cases"
+	"golang.org/x/text/language"
 )
 
 /*
@@ -16,6 +19,50 @@ import (
 	Most of the functions are implemented in dynamicproxy.go
 */
 
+/*
+	User Defined Header Functions
+*/
+
+// Check if a user define header exists in this endpoint, ignore case
+func (ep *ProxyEndpoint) UserDefinedHeaderExists(key string) bool {
+	for _, header := range ep.UserDefinedHeaders {
+		if strings.ToLower(header.Key) == strings.ToLower(key) {
+			return true
+		}
+	}
+
+	return false
+}
+
+// Remvoe a user defined header from the list
+func (ep *ProxyEndpoint) RemoveUserDefinedHeader(key string) error {
+	newHeaderList := []*UserDefinedHeader{}
+	for _, header := range ep.UserDefinedHeaders {
+		if strings.ToLower(header.Key) != strings.ToLower(key) {
+			newHeaderList = append(newHeaderList, header)
+		}
+	}
+
+	return nil
+}
+
+func (ep *ProxyEndpoint) AddUserDefinedHeader(key string, value string) error {
+	if ep.UserDefinedHeaderExists(key) {
+		ep.RemoveUserDefinedHeader(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,
+	})
+
+	return nil
+}
+
+/*
+	Virtual Directory Functions
+*/
+
 // Get virtual directory handler from given URI
 func (ep *ProxyEndpoint) GetVirtualDirectoryHandlerFromRequestURI(requestURI string) *VirtualDirectoryEndpoint {
 	for _, vdir := range ep.VirtualDirectories {

+ 9 - 0
mod/dynamicproxy/typedef.go

@@ -70,6 +70,12 @@ type BasicAuthExceptionRule struct {
 	PathPrefix string
 }
 
+// User defined headers to add into a proxy endpoint
+type UserDefinedHeader struct {
+	Key   string
+	Value string
+}
+
 // A Virtual Directory endpoint, provide a subset of ProxyEndpoint for better
 // program structure than directly using ProxyEndpoint
 type VirtualDirectoryEndpoint struct {
@@ -95,6 +101,9 @@ type ProxyEndpoint struct {
 	//Virtual Directories
 	VirtualDirectories []*VirtualDirectoryEndpoint
 
+	//Custom Headers
+	UserDefinedHeaders []*UserDefinedHeader //Custom headers to append when proxying requests from this endpoint
+
 	//Authentication
 	RequireBasicAuth        bool                      //Set to true to request basic auth before proxy
 	BasicAuthCredentials    []*BasicAuthCredentials   //Basic auth credentials

+ 2 - 0
reverseproxy.go

@@ -261,6 +261,8 @@ func ReverseProxyHandleAddEndpoint(w http.ResponseWriter, r *http.Request) {
 			SkipCertValidations: skipTlsValidation,
 			//VDir
 			VirtualDirectories: []*dynamicproxy.VirtualDirectoryEndpoint{},
+			//Custom headers
+			UserDefinedHeaders: []*dynamicproxy.UserDefinedHeader{},
 			//Auth
 			RequireBasicAuth:        requireBasicAuth,
 			BasicAuthCredentials:    basicAuthCredentials,

+ 39 - 5
web/components/httprp.html

@@ -9,7 +9,7 @@
                 <tr>
                     <th>Host</th>
                     <th>Destination</th>
-                    <!-- <th>Virtual Directory</th> -->
+                    <th>Virtual Directory</th>
                     <th>Basic Auth</th>
                     <th class="no-sort" style="min-width:100px;">Actions</th>
                 </tr>
@@ -30,11 +30,11 @@
             $("#httpProxyList").html(``);
             if (data.error !== undefined){
                     $("#httpProxyList").append(`<tr>
-                    <td data-label="" colspan="4"><i class="remove icon"></i> ${data.error}</td>
+                    <td data-label="" colspan="5"><i class="remove icon"></i> ${data.error}</td>
                 </tr>`);
             }else if (data.length == 0){
                 $("#httpProxyList").append(`<tr>
-                    <td data-label="" colspan="4"><i class="green check circle icon"></i> No HTTP Proxy Record</td>
+                    <td data-label="" colspan="5"><i class="green check circle icon"></i> No HTTP Proxy Record</td>
                 </tr>`);
             }else{
                 data.forEach(subd => {
@@ -65,12 +65,13 @@
                     vdList += `</div>`;
 
                     if (subd.VirtualDirectories.length == 0){
-                        vdList = `<i class="ui green circle check icon"></i> No Virtual Directory Rule`;
+                        vdList = `<small style="opacity: 0.3; pointer-events: none; user-select: none;"><i class="check icon"></i> No Virtual Directory</small>`;
                     }
 
                     $("#httpProxyList").append(`<tr eptuuid="${subd.RootOrMatchingDomain}" payload="${subdData}" class="subdEntry">
                         <td data-label="" editable="true" datatype="inbound"><a href="//${subd.RootOrMatchingDomain}" target="_blank">${subd.RootOrMatchingDomain}</a> ${inboundTlsIcon}</td>
                         <td data-label="" editable="true" datatype="domain">${subd.Domain} ${tlsIcon}</td>
+                        <td data-label="" editable="true" datatype="vdir">${vdList}</td>
                         <td data-label="" editable="true" datatype="basicauth">${subd.RequireBasicAuth?`<i class="ui green check icon"></i>`:`<i class="ui grey remove icon"></i>`}</td>
                         <td class="center aligned" editable="true" datatype="action" data-label="">
                             <button class="ui circular mini basic icon button editBtn inlineEditActionBtn" onclick='editEndpoint("${(subd.RootOrMatchingDomain).hexEncode()}")'><i class="edit icon"></i></button>
@@ -140,6 +141,12 @@
                     </div>
                 `;
                 column.empty().append(input);
+            }else if (datatype == "vdir"){
+                //Append a quick access button for vdir page
+                column.append(`<button class="ui basic tiny button" style="margin-left: 0.4em; margin-top: 0.4em;" onclick="quickEditVdir('${uuid}');">
+                    <i class="ui yellow folder icon"></i> Edit Virtual Directories
+                </button>`);
+
             }else if (datatype == "basicauth"){
                 let requireBasicAuth = payload.RequireBasicAuth;
                 let checkstate = "";
@@ -150,7 +157,20 @@
                     <input type="checkbox" class="RequireBasicAuth" ${checkstate}>
                     <label>Require Basic Auth</label>
                     </div>
-                    <button class="ui basic tiny button" style="margin-left: 0.4em; margin-top: 0.4em;" onclick="editBasicAuthCredentials('${uuid}');">Edit Credentials</button>`);
+                    <button class="ui basic tiny button" style="margin-left: 0.4em; margin-top: 0.4em;" onclick="editBasicAuthCredentials('${uuid}');"><i class="ui blue user circle icon"></i> Edit Credentials</button>
+                    <div class="ui basic advance segment" style="padding: 0.4em !important; border-radius: 0.4em;">
+                        <div class="ui endpointAdvanceConfig accordion" style="padding-right: 0.6em;">
+                            <div class="title">
+                                <i class="dropdown icon"></i>
+                                Advance Configs
+                            </div>
+                            <div class="content">
+                                <button class="ui basic compact fluid tiny button" style="margin-left: 0.4em; margin-top: 0.4em;" onclick="editCustomHeaders('${uuid}');"><i class="heading icon"></i> User Defined Headers</button>
+                                <button class="ui basic compact fluid tiny button" style="margin-left: 0.4em; margin-top: 0.4em;" onclick="editLoadBalanceOptions('${uuid}');"><i class="blue server icon"></i> Load Balance</button>
+                            </div>
+                        </div>
+                    <div>
+                `);
 
             }else if (datatype == 'action'){
                 column.empty().append(`
@@ -173,6 +193,7 @@
             }
         });
 
+        $(".endpointAdvanceConfig").accordion();
         $("#httpProxyList").find(".editBtn").addClass("disabled");
     }
 
@@ -220,6 +241,7 @@
         })
     }
     
+    /* button events */
     function editBasicAuthCredentials(uuid){
         let payload = encodeURIComponent(JSON.stringify({
             ept: "host",
@@ -227,6 +249,18 @@
         }));
         showSideWrapper("snippet/basicAuthEditor.html?t=" + Date.now() + "#" + payload);
     }
+
+    function quickEditVdir(uuid){
+        alert(uuid);
+    }
+
+    function editCustomHeaders(uuid){
+        alert(uuid);
+    }
+
+    function editLoadBalanceOptions(uuid){
+        alert(uuid);
+    }
     
 
     //Bind on tab switch events