mirror of
https://github.com/tobychui/zoraxy.git
synced 2025-08-06 21:28:30 +02:00
Restructured proxy routing logic
- Moved virtual directory into host routing object - Generalized root and hosts routing struct - Optimized UI
This commit is contained in:
@@ -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>
|
@@ -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();
|
||||
}
|
||||
}
|
||||
})
|
||||
|
@@ -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,
|
||||
}
|
||||
|
@@ -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>
|
Reference in New Issue
Block a user