Restructured proxy routing logic

- Moved virtual directory into host routing object
- Generalized root and hosts routing struct
- Optimized UI
This commit is contained in:
Toby Chui
2024-02-13 21:46:43 +08:00
parent 36e461795a
commit 3228789375
26 changed files with 1125 additions and 1156 deletions

View File

@@ -1,92 +1,119 @@
<div class="standardContainer">
<div class="ui basic segment">
<h2>Set Proxy Root</h2>
<p>The default routing point for all incoming traffics. For all routing not found in the proxy rules, request will be redirected to the proxy root server.</p>
<h2>Default Site</h2>
<p>Default routing options for inbound traffic (previously called Proxy Root)</p>
<div class="ui form">
<div class="field">
<label>Proxy Root</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>Root require TLS connection <br><small>Check this if your proxy root URL starts with https://</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 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 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 horizontal divider">OR</div>
<div class="field">
<div class="ui checkbox">
<input type="checkbox" id="useStaticWebServer" onchange="handleUseStaticWebServerAsRoot()">
<label>Use Static Web Server as Root <br><small>Check this if you prefer a more Apache Web Server like experience</small></label>
</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>
</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">
<input id="unsetRedirectDomain" type="text" placeholder="http://example.com">
<input id="redirectDomain" type="text" placeholder="http://example.com">
</div>
<small>Unset subdomain will be redirected to the link above. Remember to include the protocol (e.g. http:// or https://)<br>
Leave empty for redirecting to upper level domain (e.g. notfound.example.com <i class="right arrow icon"></i> example.com)</small>
<small>Unset subdomain will be redirected to the link above. Remember to include the protocol (e.g. http:// or https://)</small>
</div>
</div>
<br>
<button class="ui basic button" onclick="updateRootOptions()"><i class="blue save icon" ></i> Save Root Options</button>
</div>
<button class="ui basic button" onclick="setProxyRoot(this)"><i class="green checkmark icon" ></i> Apply Changes</button>
<button class="ui basic button" onclick="initRootInfo()"><i class="refresh icon" ></i> Reset</button>
<br>
</div>
</div>
<script>
var currentDefaultSiteOption = 0; //For enum see typedef.go
$("#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{
currentDefaultSiteOption = 0;
}else if (selectedDefaultSite == "proxy"){
$("#defaultSiteProxyOptions").show();
$("#rootReqTLS").parent().removeClass("disabled");
$("#proxyRoot").parent().removeClass("disabled");
initRootInfo();
currentDefaultSiteOption = 1;
}else if (selectedDefaultSite == "redirect"){
$("#defaultSiteRedirectOptions").show();
currentDefaultSiteOption = 2;
}else if (selectedDefaultSite == "notfound"){
currentDefaultSiteOption = 3;
}else{
//Unknown option
return;
}
}
//Bind events to the radio boxes
function bindDefaultSiteRadioCheckboxEvents(){
$('input[type=radio][name=defaultsiteOption]').off("change").on("change", function() {
updateAvaibleDefaultSiteOptions();
});
}
function initRootInfo(callback=undefined){
@@ -94,6 +121,22 @@
if (data == null){
}else{
var $radios = $('input:radio[name=defaultsiteOption]');
let proxyType = data.DefaultSiteOption;
//See typedef.go for enum conversion
if (proxyType == 0){
$radios.filter('[value=webserver]').prop('checked', true);
}else if (proxyType == 1){
$radios.filter('[value=proxy]').prop('checked', true);
$("#proxyRoot").val(data.DefaultSiteValue);
}else if (proxyType == 2){
$radios.filter('[value=redirect]').prop('checked', true);
$("#redirectDomain").val(data.DefaultSiteValue);
}else if (proxyType == 3){
$radios.filter('[value=notfound]').prop('checked', true);
}
updateAvaibleDefaultSiteOptions();
$("#proxyRoot").val(data.Domain);
checkRootRequireTLS(data.Domain);
}
@@ -104,21 +147,9 @@
});
}
initRootInfo(function(){
updateWebServerLinkSettings();
bindDefaultSiteRadioCheckboxEvents();
});
//Update the current web server port settings
function updateWebServerLinkSettings(){
isUsingStaticWebServerAsRoot(function(isUsingWebServ){
if (isUsingWebServ){
$(".webservRootDisabled").addClass("disabled");
$("#useStaticWebServer").parent().checkbox("set checked");
}else{
$(".webservRootDisabled").removeClass("disabled");
$("#useStaticWebServer").parent().checkbox("set unchecked");
}
})
}
function isUsingStaticWebServerAsRoot(callback){
let currentProxyRoot = $("#proxyRoot").val().trim();
@@ -131,47 +162,12 @@
}
function updateRootSettingStates(){
$.get("/api/cert/tls", function(data){
if (data == true){
$("#disableRootTLS").parent().removeClass('disabled').attr("title", "");
}else{
$("#disableRootTLS").parent().addClass('disabled').attr("title", "TLS listener is not enabled");
}
});
}
//Bind event to tab switch
tabSwitchEventBind["setroot"] = function(){
//On switch over to this page, update root info
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
@@ -193,14 +189,15 @@
}else if (data == "http"){
$("#rootReqTLS").parent().checkbox("set unchecked");
}
}
})
}
//Set the new proxy root option
function setProxyRoot(){
function setProxyRoot(btn=undefined){
if (btn != undefined){
$(btn).addClass("disabled");
}
var newpr = $("#proxyRoot").val();
if (newpr.trim() == ""){
$("#proxyRoot").parent().addClass('error');
@@ -211,10 +208,36 @@
var rootReqTls = $("#rootReqTLS")[0].checked;
//proxy mode or redirect mode, check for input values
var defaultSiteValue = "";
if (currentDefaultSiteOption == 1){
if ($("#proxyRoot").val().trim() == ""){
$("#proxyRoot").parent().addClass("error");
return;
}
defaultSiteValue = $("#proxyRoot").val().trim();
$("#proxyRoot").parent().removeClass("error");
}else if (currentDefaultSiteOption == 2){
if ($("#redirectDomain").val().trim() == ""){
$("#redirectDomain").parent().addClass("error");
return;
}
defaultSiteValue = $("#redirectDomain").val().trim();
$("#redirectDomain").parent().removeClass("error");
}
//Create the endpoint by calling add
$.ajax({
url: "/api/proxy/add",
data: {"type": "root", tls: rootReqTls, ep: newpr},
data: {
"type": "root",
"tls": rootReqTls,
"ep": newpr,
"defaultSiteOpt": currentDefaultSiteOption,
"defaultSiteVal":defaultSiteValue,
},
method: "POST",
success: function(data){
if (data.error != undefined){
msgbox(data.error, false, 5000);
@@ -231,37 +254,20 @@
setTimeout(function(){
//Update the checkbox
updateWebServerLinkSettings();
msgbox("Proxy Root Updated");
}, 1000);
}, 100);
})
});
}
if (btn != undefined){
$(btn).removeClass("disabled");
}
}
});
}
function updateRootOptions(){
$.ajax({
type: "POST",
url: "/api/proxy/root/updateOptions",
data: {
unsetRedirect: $("#unsetRedirect")[0].checked,
unsetRedirectTarget: $("#unsetRedirectDomain").val().trim(),
},
success: function(data) {
if (data.error != undefined){
msgbox(data.error, false);
}else{
msgbox("Root Routing Options updated");
}
},
error: function(error) {
console.log("Error:", error);
}
});
}
</script>

View File

@@ -1,119 +1,114 @@
<div class="ui stackable grid">
<!-- Proxy Create Form-->
<style>
.rulesInstructions{
background: var(--theme_background) !important;
color: var(--theme_lgrey);
border-radius: 1em !important;
}
</style>
<div class="standardContainer">
<div class="ui stackable grid">
<div class="ten wide column">
<div class="standardContainer">
<div class="ui basic segment" style="margin-top: 1em;">
<h2>New Proxy Rule</h2>
<p>You can create a proxy endpoing by subdomain or virtual directories</p>
<div class="ui form">
<div class="field">
<label>Proxy Type</label>
<div class="ui selection dropdown">
<input type="hidden" id="ptype" value="subd" onchange="handleProxyTypeOptionChange(this.value)">
<i class="dropdown icon"></i>
<div class="default text">Proxy Type</div>
<div class="menu">
<div class="item" data-value="subd">Sub-domain</div>
<div class="item" data-value="vdir">Virtual Directory</div>
</div>
</div>
</div>
<div class="field">
<label>Subdomain Matching Keyword / Virtual Directory Name</label>
<input type="text" id="rootname" placeholder="s1.mydomain.com">
</div>
<div class="field">
<label>Target IP Address or Domain Name with port</label>
<input type="text" id="proxyDomain" onchange="autoCheckTls(this.value);">
<small>E.g. 192.168.0.101:8000 or example.com</small>
</div>
<div class="field">
<div class="ui checkbox">
<input type="checkbox" id="reqTls">
<label>Proxy Target require TLS Connection <br><small>(i.e. Your proxy target starts with https://)</small></label>
</div>
</div>
<!-- Advance configs -->
<div class="ui basic segment" style="background-color: #f7f7f7; border-radius: 1em;">
<div id="advanceProxyRules" class="ui fluid accordion">
<div class="title">
<i class="dropdown icon"></i>
Advance Settings
</div>
<div class="content">
<p></p>
<div class="field">
<div class="ui checkbox">
<input type="checkbox" id="skipTLSValidation">
<label>Ignore TLS/SSL Verification Error<br><small>For targets that is using self-signed, expired certificate (Not Recommended)</small></label>
</div>
</div>
<div class="field">
<div class="ui checkbox">
<input type="checkbox" id="bypassGlobalTLS">
<label>Allow plain HTTP access<br><small>Allow this subdomain to be connected without TLS (Require HTTP server enabled on port 80)</small></label>
</div>
</div>
<div class="field">
<div class="ui checkbox">
<input type="checkbox" id="requireBasicAuth">
<label>Require Basic Auth<br><small>Require client to login in order to view the page</small></label>
</div>
</div>
<div id="basicAuthCredentials" class="field">
<p>Enter the username and password for allowing them to access this proxy endpoint</p>
<table class="ui very basic celled table">
<thead>
<tr>
<th>Username</th>
<th>Password</th>
<th>Remove</th>
</tr></thead>
<tbody id="basicAuthCredentialTable">
<tr>
<td colspan="3"><i class="ui green circle check icon"></i> No Entered Credential</td>
</tr>
</tbody>
</table>
<div class="three small fields credentialEntry">
<div class="field">
<input id="basicAuthCredUsername" type="text" placeholder="Username" autocomplete="off">
</div>
<div class="field">
<input id="basicAuthCredPassword" type="password" placeholder="Password" autocomplete="off">
</div>
<div class="field">
<button class="ui basic button" onclick="addCredentials();"><i class="blue add icon"></i> Add Credential</button>
</div>
</div>
</div>
</div>
</div>
</div>
<br>
<button class="ui basic button" onclick="newProxyEndpoint();"><i class="blue add icon"></i> Create Endpoint</button>
<br><br>
<div class="ui basic segment" style="border-radius: 1em; padding: 1em !important;">
<h2>New Proxy Rule</h2>
<p>You can add more proxy rules to support more site via domain / subdomains</p>
<div class="ui form">
<div class="field">
<label>Matching Keyword / Domain</label>
<input type="text" id="rootname" placeholder="mydomain.com">
<small>Support subdomain and wildcard, e.g. s1.mydomain.com or *.test.mydomain.com</small>
</div>
<div class="field">
<label>Target IP Address or Domain Name with port</label>
<input type="text" id="proxyDomain" onchange="autoCheckTls(this.value);">
<small>E.g. 192.168.0.101:8000 or example.com</small>
</div>
<div class="field">
<div class="ui checkbox">
<input type="checkbox" id="reqTls">
<label>Proxy Target require TLS Connection <br><small>(i.e. Your proxy target starts with https://)</small></label>
</div>
</div>
<!-- Advance configs -->
<div class="ui basic segment" style="background-color: #f7f7f7; border-radius: 1em;">
<div id="advanceProxyRules" class="ui fluid accordion">
<div class="title">
<i class="dropdown icon"></i>
Advance Settings
</div>
<div class="content">
<p></p>
<div class="field">
<div class="ui checkbox">
<input type="checkbox" id="skipTLSValidation">
<label>Ignore TLS/SSL Verification Error<br><small>For targets that is using self-signed, expired certificate (Not Recommended)</small></label>
</div>
</div>
<div class="field">
<div class="ui checkbox">
<input type="checkbox" id="bypassGlobalTLS">
<label>Allow plain HTTP access<br><small>Allow this subdomain to be connected without TLS (Require HTTP server enabled on port 80)</small></label>
</div>
</div>
<div class="field">
<div class="ui checkbox">
<input type="checkbox" id="requireBasicAuth">
<label>Require Basic Auth<br><small>Require client to login in order to view the page</small></label>
</div>
</div>
<div id="basicAuthCredentials" class="field">
<p>Enter the username and password for allowing them to access this proxy endpoint</p>
<table class="ui very basic celled table">
<thead>
<tr>
<th>Username</th>
<th>Password</th>
<th>Remove</th>
</tr></thead>
<tbody id="basicAuthCredentialTable">
<tr>
<td colspan="3"><i class="ui green circle check icon"></i> No Entered Credential</td>
</tr>
</tbody>
</table>
<div class="three small fields credentialEntry">
<div class="field">
<input id="basicAuthCredUsername" type="text" placeholder="Username" autocomplete="off">
</div>
<div class="field">
<input id="basicAuthCredPassword" type="password" placeholder="Password" autocomplete="off">
</div>
<div class="field">
<button class="ui basic button" onclick="addCredentials();"><i class="blue add icon"></i> Add Credential</button>
</div>
</div>
</div>
</div>
</div>
</div>
<br>
<button class="ui basic button" onclick="newProxyEndpoint();"><i class="blue add icon"></i> Create Endpoint</button>
<br><br>
</div>
</div>
</div>
<div class="six wide column">
<div class="ui basic segment" style="height: 100%; background-color: var(--theme_grey); color: var(--theme_lgrey);">
<br>
<span style="font-size: 1.2em; font-weight: 300;">Subdomain</span><br>
Example of subdomain matching keyword:<br>
<code>s1.arozos.com</code> <br>(Any access starting with s1.arozos.com will be proxy to the IP address below)<br>
<div class="ui basic segment rulesInstructions">
<span style="font-size: 1.2em; font-weight: 300;"><i class="ui yellow star icon"></i> Domain</span><br>
Example of domain matching keyword:<br>
<code>arozos.com</code> <br>Any acess requesting arozos.com will be proxy to the IP address below<br>
<div class="ui divider"></div>
<span style="font-size: 1.2em; font-weight: 300;">Virtual Directory</span><br>
Example of virtual directory name: <br>
<code>/s1/home/</code> <br>(Any access to {this_server}/s1/home/ will be proxy to the IP address below)<br>
You can also ignore the tailing slash for wildcard like usage.<br>
<code>/s1/room-</code> <br>Any access to {this_server}/s1/classroom_* will be proxied, for example: <br>
<span style="font-size: 1.2em; font-weight: 300;"><i class="ui yellow star icon"></i> Subdomain</span><br>
Example of subdomain matching keyword:<br>
<code>s1.arozos.com</code> <br>Any request starting with s1.arozos.com will be proxy to the IP address below<br>
<div class="ui divider"></div>
<span style="font-size: 1.2em; font-weight: 300;"><i class="ui yellow star icon"></i> Wildcard</span><br>
Example of wildcard matching keyword:<br>
<code>*.arozos.com</code> <br>Any request with a host name matching *.arozos.com will be proxy to the IP address below. Here are some examples.<br>
<div class="ui list">
<div class="item"><code>/s1/room-101</code></div>
<div class="item"><code>/s1/room-102/</code></div>
<div class="item"><code>/s1/room-103/map.txt</code></div>
</div><br>
<div class="item"><code>www.arozos.com</code></div>
<div class="item"><code>foo.bar.arozos.com</code></div>
</div>
<br>
</div>
</div>
@@ -124,7 +119,6 @@
//New Proxy Endpoint
function newProxyEndpoint(){
var type = $("#ptype").val();
var rootname = $("#rootname").val();
var proxyDomain = $("#proxyDomain").val();
var useTLS = $("#reqTls")[0].checked;
@@ -132,20 +126,6 @@
var bypassGlobalTLS = $("#bypassGlobalTLS")[0].checked;
var requireBasicAuth = $("#requireBasicAuth")[0].checked;
if (type === "vdir") {
if (!rootname.startsWith("/")) {
rootname = "/" + rootname
$("#rootname").val(rootname);
}
}else{
if (!isSubdomainDomain(rootname)){
//This doesn't seems like a subdomain
if (!confirm(rootname + " does not looks like a subdomain. Continue anyway?")){
return;
}
}
}
if (rootname.trim() == ""){
$("#rootname").parent().addClass("error");
return
@@ -164,7 +144,7 @@
$.ajax({
url: "/api/proxy/add",
data: {
type: type,
type: "host",
rootname: rootname,
tls: useTLS,
ep: proxyDomain,
@@ -178,8 +158,6 @@
msgbox(data.error, false, 5000);
}else{
//OK
listVdirs();
listSubd();
//Clear old data
@@ -189,7 +167,7 @@
updateTable();
//Check if it is a new subdomain and TLS enabled
if (type == "subd" && $("#tls").checkbox("is checked")){
if ($("#tls").checkbox("is checked")){
confirmBox("Request new SSL Cert for this subdomain?", function(choice){
if (choice == true){
//Load the prefer CA from TLS page
@@ -214,23 +192,14 @@
}
function handleProxyTypeOptionChange(newType){
if (newType == "subd"){
$("#bypassGlobalTLS").parent().removeClass("disabled");
}else if (newType == "vdir"){
$("#bypassGlobalTLS").parent().addClass("disabled");
}
}
//Generic functions for delete rp endpoints
function deleteEndpoint(ptype, epoint){
if (confirm("Confirm remove proxy for :" + epoint + " (type: " + ptype + ")?")){
if (confirm("Confirm remove proxy for :" + epoint + "?")){
$.ajax({
url: "/api/proxy/del",
data: {ep: epoint, ptype: ptype},
data: {ep: epoint, },
success: function(){
listVdirs();
listSubd();
listProxyEndpoints();
}
})
}
@@ -330,14 +299,6 @@
updateTable();
}
//Check if a string is a valid subdomain
function isSubdomainDomain(str) {
const regex = /^(localhost|[a-z0-9]+([\-.]{1}[a-z0-9]+)*\.[a-z]{2,}|[a-z0-9]+([\-.]{1}[a-z0-9]+)*\.[a-z]{2,}\.)$/i;
return regex.test(str);
}
/*
Inline editor for subd.html and vdir.html
*/
@@ -411,7 +372,7 @@
<button title="Cancel" onclick="exitProxyInlineEdit('${endpointType}');" class="ui basic small circular icon button"><i class="ui remove icon"></i></button>
<button title="Save" onclick="saveProxyInlineEdit('${uuid}');" class="ui basic small circular icon button"><i class="ui green save icon"></i></button>
`);
}else if (datatype == "inbound" && payload.ProxyType == 0){
}else if (datatype == "inbound"){
let originalContent = $(column).html();
column.empty().append(`${originalContent}
<div class="ui divider"></div>
@@ -429,9 +390,8 @@
$("#" + endpointType).find(".editBtn").addClass("disabled");
}
function exitProxyInlineEdit(){
listSubd();
listVdirs();
function exitProxyInlineEdit(endpointType){
listProxyEndpoints();
$("#" + endpointType).find(".editBtn").removeClass("disabled");
}
@@ -440,14 +400,8 @@
if (row.length == 0){
return;
}
var epttype = $(row).attr("class");
if (epttype == "subdEntry"){
epttype = "subd";
}else if (epttype == "vdirEntry"){
epttype = "vdir";
}
var epttype = "host";
let newDomain = $(row).find(".Domain").val();
let requireTLS = $(row).find(".RequireTLS")[0].checked;
let skipCertValidations = $(row).find(".SkipCertValidations")[0].checked;
@@ -473,11 +427,7 @@
msgbox(data.error, false, 6000);
}else{
msgbox("Proxy endpoint updated");
if (epttype == "subd"){
listSubd();
}else if (epttype == "vdir"){
listVdirs();
}
listProxyEndpoints();
}
}
})

View File

@@ -17,7 +17,7 @@
</div>
</div>
<div class="six wide column statisticWrapper">
<div class="ui greybackground statustab segment">
<div class="ui statustab segment">
<h5 class="ui header">
<i class="exchange icon"></i>
<div class="content">
@@ -29,7 +29,7 @@
</div>
</h5>
<div class="ui divider"></div>
<h5 class="ui header">
<h5 class="ui header" style="margin-top: 0px;">
<i class="arrows alternate horizontal icon"></i>
<div class="content">
<span id="forwardtype"></span>
@@ -39,7 +39,7 @@
</div>
</h5>
<div class="ui divider"></div>
<h5 class="ui header">
<h5 class="ui header" style="margin-top: 0px;">
<i class="map marker alternate icon"></i>
<div class="content">
<span id="country"></span>
@@ -51,20 +51,27 @@
</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;"><i class="ui pause icon"></i> Graph Render Paused</p>
<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">
<button class="ui basic green notloopbackOnly button" onclick="handlePortChange();">Apply</button>
<button class="ui basic notloopbackOnly button" onclick="handlePortChange();"><i class="ui green checkmark icon"></i> Apply</button>
</div>
<br>
<div id="tls" class="ui toggle notloopbackOnly checkbox">
@@ -99,11 +106,7 @@
</div>
</div>
</div>
<br><br>
<button id="startbtn" class="ui teal button" onclick="startService();">Start Service</button>
<button id="stopbtn" class="ui red notloopbackOnly disabled button" onclick="stopService();">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>
@@ -114,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>
@@ -130,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>
@@ -175,13 +178,13 @@
}
$("#serverstatus").addClass("green");
$("#statusTitle").text("Online");
$("#rpStatusIcon").attr("class", "green circle check icon");
$("#rpStatusIcon").attr("class", "white circle check icon");
$("#statusText").text("Serving request on port: " + data.Option.Port);
}else{
$("#startbtn").removeClass("disabled");
$("#stopbtn").addClass("disabled");
$("#statusTitle").text("Offline");
$("#rpStatusIcon").attr("class", "black circle times icon")
$("#rpStatusIcon").attr("class", "yellow moon icon")
$("#statusText").text("Reverse proxy server is offline");
$("#serverstatus").removeClass("green");
}
@@ -565,6 +568,7 @@
options: {
animation: false,
maintainAspectRatio: false,
bezierCurve: true,
tooltips: {enabled: false},
hover: {mode: null},
//stepped: 'middle',
@@ -606,18 +610,18 @@
{
label: 'Inbound',
data: rxValues,
borderColor: "#4d9dd9",
borderWidth: 2,
backgroundColor: 'rgba(77, 157, 217, 0.2)',
borderColor: "#484bb8",
borderWidth: 1,
backgroundColor: 'rgba(72, 75, 184, 0.2)',
fill: true,
pointStyle: false,
},
{
label: 'Outbound',
data: txValues,
borderColor: '#ffe32b',
borderWidth: 2,
backgroundColor: 'rgba(255, 227, 43, 0.2)',
borderColor: '#02a9c1',
borderWidth: 1,
backgroundColor: 'rgba(2, 169, 193, 0.2)',
fill: true,
pointStyle: false,
}

View File

@@ -1,14 +1,15 @@
<div class="standardContainer">
<div class="ui basic segment">
<h2>Subdomain</h2>
<p>Subdomains are a way to organize and identify different sections of a website or domain. They are essentially a prefix to the main domain name, separated by a dot. <br>For example, in the domain "blog.example.com," "blog" is the subdomain.</p>
<h2>HTTP Proxy</h2>
<p>Proxy HTTP server with HTTP or HTTPS. Sometime subdomain contain a prefix to the main domain name, separated by a dot. <br>For example, in the domain "blog.example.com," "blog" is the subdomain.</p>
</div>
<div style="width: 100%; overflow-x: auto; margin-bottom: 1em;">
<table class="ui celled sortable unstackable compact table">
<thead>
<tr>
<th>Matching Domain</th>
<th>Proxy To</th>
<th>Host</th>
<th>Destination</th>
<th>Virtual Directory</th>
<th>Basic Auth</th>
<th class="no-sort" style="min-width: 7.2em;">Actions</th>
</tr>
@@ -18,13 +19,13 @@
</tbody>
</table>
</div>
<button class="ui icon right floated basic button" onclick="listSubd();"><i class="green refresh icon"></i> Refresh</button>
<button class="ui icon right floated basic button" onclick="listProxyEndpoints();"><i class="green refresh icon"></i> Refresh</button>
<br><br>
</div>
<script>
function listSubd(){
$.get("/api/proxy/list?type=subd", function(data){
function listProxyEndpoints(){
$.get("/api/proxy/list?type=host", function(data){
$("#subdList").html(``);
if (data.error !== undefined){
$("#subdList").append(`<tr>
@@ -32,7 +33,7 @@
</tr>`);
}else if (data.length == 0){
$("#subdList").append(`<tr>
<td data-label="" colspan="3"><i class="checkmark icon"></i> No Subdomain Proxy Record</td>
<td data-label="" colspan="3"><i class="green check circle icon"></i> No HTTP Proxy Record</td>
</tr>`);
}else{
data.forEach(subd => {
@@ -45,9 +46,21 @@
}
}
let inboundTlsIcon = "";
if ($("#tls").checkbox("is checked")){
inboundTlsIcon = `<i class="green lock icon" title="TLS Mode"></i>`;
if (subd.BypassGlobalTLS){
inboundTlsIcon = `<i class="grey lock icon" title="TLS Bypass Enabled"></i>`;
}
}else{
inboundTlsIcon = `<i class="yellow lock open icon" title="Plain Text Mode"></i>`;
}
$("#subdList").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></td>
<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">WIP</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" onclick='editEndpoint("subd","${subd.RootOrMatchingDomain}")'><i class="edit icon"></i></button>
@@ -61,6 +74,6 @@
//Bind on tab switch events
tabSwitchEventBind["subd"] = function(){
listSubd();
listProxyEndpoints();
}
</script>