upstreams.html 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667
  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <!-- Notes: This should be open in its original path-->
  5. <meta charset="utf-8">
  6. <meta name="zoraxy.csrf.Token" content="{{.csrfToken}}">
  7. <link rel="stylesheet" href="../script/semantic/semantic.min.css">
  8. <script src="../script/jquery-3.6.0.min.js"></script>
  9. <script src="../script/semantic/semantic.min.js"></script>
  10. <script src="../script/utils.js"></script>
  11. <style>
  12. .upstreamActions{
  13. position: absolute;
  14. top: 0.6em;
  15. right: 0.6em;
  16. }
  17. .upstreamLink{
  18. max-width: 220px;
  19. display: inline-block;
  20. word-break: break-all;
  21. }
  22. .upstreamEntry .ui.toggle.checkbox input:checked ~ label::before{
  23. background-color: #00ca52 !important;
  24. }
  25. #activateNewUpstream.ui.toggle.checkbox input:checked ~ label::before{
  26. background-color: #00ca52 !important;
  27. }
  28. #upstreamTable{
  29. max-height: 480px;
  30. border-radius: 0.3em;
  31. padding: 0.3em;
  32. overflow-y: auto;
  33. }
  34. body.darkTheme #upstreamTable{
  35. border: 1px solid var(--button_border_color);
  36. }
  37. .upstreamEntry.inactive{
  38. background-color: #f3f3f3 !important;
  39. }
  40. .upstreamEntry{
  41. border-radius: 0.4em !important;
  42. border: 1px solid rgb(233, 233, 233) !important;
  43. }
  44. @media (max-width: 499px) {
  45. .upstreamActions{
  46. position: relative;
  47. margin-top: 1em;
  48. margin-left: 0.4em;
  49. margin-bottom: 0.4em;
  50. }
  51. }
  52. .advanceUpstreamOptions{
  53. padding: 0.6em;
  54. background-color: var(--theme_advance);
  55. width: 100%;
  56. border-radius: 0.4em;
  57. }
  58. .advanceUpstreamOptions.ui.accordion .content{
  59. padding: 1em !important;
  60. }
  61. </style>
  62. </head>
  63. <body>
  64. <link rel="stylesheet" href="../darktheme.css">
  65. <script src="../script/darktheme.js"></script>
  66. <br>
  67. <div class="ui container">
  68. <div class="ui header">
  69. <div class="content">
  70. Upstreams / Load Balance
  71. <div class="sub header epname"></div>
  72. </div>
  73. </div>
  74. <div class="ui divider"></div>
  75. <div class="ui small pointing secondary menu">
  76. <a class="item active narrowpadding" data-tab="upstreamlist">Upstreams</a>
  77. <a class="item narrowpadding" data-tab="newupstream">Add Upstream</a>
  78. </div>
  79. <div class="ui tab basic segment active" data-tab="upstreamlist">
  80. <!-- A list of current existing upstream on this reverse proxy-->
  81. <div id="upstreamTable">
  82. <div class="ui segment">
  83. <a><i class="ui loading spinner icon"></i> Loading</a>
  84. </div>
  85. </div>
  86. <div class="ui message">
  87. <i class="ui blue info circle icon"></i> Weighted random will be used for load-balancing. Set weight to 0 for fallback only.
  88. </div>
  89. </div>
  90. <div class="ui tab basic segment" data-tab="newupstream">
  91. <!-- Web Form to create a new upstream -->
  92. <h4 class="ui header">
  93. <i class="green add icon"></i>
  94. <div class="content">
  95. Add Upstream Server
  96. <div class="sub header">Create new load balance or fallback upstream origin</div>
  97. </div>
  98. </h4>
  99. <p style="margin-bottom: 0.4em;">Target IP address with port</p>
  100. <div class="ui fluid small input">
  101. <input type="text" id="originURL" onchange="cleanProxyTargetValue(this);"><br>
  102. </div>
  103. <small>E.g. 192.168.0.101:8000 or example.com</small>
  104. <br><br>
  105. <div id="activateNewUpstream" class="ui toggle checkbox" style="display:inline-block;">
  106. <input type="checkbox" id="activateNewUpstreamCheckbox" style="margin-top: 0.4em;" checked>
  107. <label>Activate<br>
  108. <small>Enable this upstream for load balancing</small></label>
  109. </div><br>
  110. <div class="ui checkbox" style="margin-top: 1.2em;">
  111. <input type="checkbox" id="requireTLS">
  112. <label>Require TLS<br>
  113. <small>Proxy target require HTTPS connection</small></label>
  114. </div><br>
  115. <div class="ui checkbox" style="margin-top: 0.6em;">
  116. <input type="checkbox" id="skipTlsVerification">
  117. <label>Skip Verification<br>
  118. <small>Check this if proxy target is using self signed certificates</small></label>
  119. </div><br>
  120. <div class="ui checkbox" style="margin-top: 0.4em;">
  121. <input type="checkbox" id="SkipWebSocketOriginCheck" checked>
  122. <label>Skip WebSocket Origin Check<br>
  123. <small>Check this to allow cross-origin websocket requests</small></label>
  124. </div>
  125. <div class="ui advanceUpstreamOptions accordion" style="margin-top:0.6em;">
  126. <div class="title">
  127. <i class="dropdown icon"></i>
  128. Advanced Options
  129. </div>
  130. <div class="content">
  131. <p>Max Concurrent Connections</p>
  132. <div class="ui mini fluid input" style="margin-top: -0.6em;">
  133. <input type="number" min="0" id="maxConn" value="0">
  134. </div>
  135. <small>Set to 0 for default value (32 connections)</small>
  136. <br><br>
  137. <p>Response Timeout</p>
  138. <div class="ui mini right labeled fluid input" style="margin-top: -0.6em;">
  139. <input type="number" min="0" id="respTimeout" value="0">
  140. <div class="ui basic label">
  141. Seconds
  142. </div>
  143. </div>
  144. <small>Maximum waiting time for server header response, set to 0 for default</small>
  145. <br><br>
  146. <p>Idle Timeout</p>
  147. <div class="ui mini right labeled fluid input" style="margin-top: -0.6em;">
  148. <input type="number" min="0" id="idleTimeout" value="0">
  149. <div class="ui basic label">
  150. Seconds
  151. </div>
  152. </div>
  153. <small>Maximum allowed keep-alive time forcefully closes the connection, set to 0 for default</small>
  154. </div>
  155. </div>
  156. <br><br>
  157. <button class="ui basic button" onclick="addNewUpstream();"><i class="ui green circle add icon"></i> Create</button>
  158. </div>
  159. <div class="ui divider"></div>
  160. <div class="field" >
  161. <button class="ui basic button" style="float: right;" onclick="closeThisWrapper();">Close</button>
  162. </div>
  163. </div>
  164. <br><br><br><br>
  165. </div>
  166. <script>
  167. let origins = [];
  168. let editingEndpoint = {};
  169. $('.menu .item').tab();
  170. function initOriginList(){
  171. $.ajax({
  172. url: "/api/proxy/upstream/list",
  173. method: "GET",
  174. data: {
  175. "type":"host",
  176. "ep": editingEndpoint.ep
  177. },
  178. success: function(data){
  179. if (data.error != undefined){
  180. //This endpoint not exists?
  181. alert(data.error);
  182. return;
  183. }else{
  184. $("#upstreamTable").html("");
  185. if (data.ActiveOrigins.length == 0){
  186. //There is no upstream for this proxy rule
  187. $("#upstreamTable").append(`<tr>
  188. <td colspan="2"><b><i class="ui yellow exclamation triangle icon"></i> No Active Upstream Origin</b><br>
  189. This HTTP proxy rule will always return Error 521 when requested. To fix this, add or enable a upstream origin to this proxy endpoint.
  190. <div class="ui divider"></div>
  191. </td>
  192. </tr>`);
  193. }
  194. data.ActiveOrigins.forEach(upstream => {
  195. renderUpstreamEntryToTable(upstream, true);
  196. });
  197. data.InactiveOrigins.forEach(upstream => {
  198. renderUpstreamEntryToTable(upstream, false);
  199. });
  200. $(".advanceUpstreamOptions.accordion").accordion();
  201. let totalUpstreams = data.ActiveOrigins.length + data.InactiveOrigins.length;
  202. if (totalUpstreams == 1){
  203. $(".lowPriorityButton").addClass('disabled');
  204. }
  205. if (parent && parent.document.getElementById("httpProxyList") != null){
  206. //Also update the parent display
  207. let element = $(parent.document.getElementById("httpProxyList")).find(".upstreamList.editing");
  208. let upstreams = "";
  209. data.ActiveOrigins.forEach(upstream => {
  210. //Check if the upstreams require TLS connections
  211. let tlsIcon = "";
  212. if (upstream.RequireTLS){
  213. tlsIcon = `<i class="green lock icon" title="TLS Mode"></i>`;
  214. if (upstream.SkipCertValidations){
  215. tlsIcon = `<i class="yellow lock icon" title="TLS/SSL mode without verification"></i>`
  216. }
  217. }
  218. let upstreamLink = `${upstream.RequireTLS?"https://":"http://"}${upstream.OriginIpOrDomain}`;
  219. upstreams += `<a href="${upstreamLink}" target="_blank">${upstream.OriginIpOrDomain} ${tlsIcon}</a><br>`;
  220. });
  221. if (data.ActiveOrigins.length == 0){
  222. upstreams = `<i class="ui yellow exclamation triangle icon"></i> No Active Upstream Origin<br>`
  223. }
  224. $(element).html(upstreams);
  225. }
  226. $(".ui.checkbox").checkbox();
  227. }
  228. }
  229. })
  230. }
  231. function renderUpstreamEntryToTable(upstream, isActive){
  232. function newUID(){return"00000000-0000-4000-8000-000000000000".replace(/0/g,function(){return(0|Math.random()*16).toString(16)})};
  233. let tlsIcon = "";
  234. if (upstream.RequireTLS){
  235. tlsIcon = `<i class="green lock icon" title="TLS Mode"></i>`;
  236. if (upstream.SkipCertValidations){
  237. tlsIcon = `<i class="yellow lock icon" title="TLS/SSL mode without verification"></i>`
  238. }
  239. }
  240. //Priority Arrows
  241. let downArrowClass = "";
  242. if (upstream.Weight == 0 ){
  243. //Cannot go any lower
  244. downArrowClass = "disabled";
  245. }
  246. let url = `${upstream.RequireTLS?"https://":"http://"}${upstream.OriginIpOrDomain}`
  247. let payload = encodeURIComponent(JSON.stringify(upstream));
  248. let domUID = newUID();
  249. //Timeout values are stored as ms in the backend
  250. $("#upstreamTable").append(`<div class="ui upstreamEntry ${isActive?"":"inactive"} basic segment" data-domid="${domUID}" data-payload="${payload}" data-priority="${upstream.Priority}">
  251. <h4 class="ui header">
  252. <div class="ui toggle checkbox" style="display:inline-block;">
  253. <input type="checkbox" class="enableState" name="enabled" style="margin-top: 0.4em;" onchange="saveUpstreamUpdate('${domUID}');" ${isActive?"checked":""}>
  254. <label></label>
  255. </div>
  256. <div class="content">
  257. <a href="${url}" target="_blank" class="upstreamLink">${upstream.OriginIpOrDomain} ${tlsIcon}</a>
  258. <div class="sub header">${isActive?(upstream.Weight==0?"Fallback Only":"Active"):"Inactive"} | Weight: ${upstream.Weight}x </div>
  259. </div>
  260. </h4>
  261. <div class="advanceOptions" style="display:none;">
  262. <div class="upstreamOriginField">
  263. <p>New upstream origin IP address or domain</p>
  264. <div class="ui small fluid input" style="margin-top: -0.6em;">
  265. <input type="text" class="newOrigin" value="${upstream.OriginIpOrDomain}" onchange="handleAutoOriginClean('${domUID}');">
  266. </div>
  267. <small>e.g. 192.168.0.101:8000 or example.com</small>
  268. </div>
  269. <div class="ui divider"></div>
  270. <div class="ui checkbox">
  271. <input type="checkbox" class="reqTLSCheckbox" ${upstream.RequireTLS?"checked":""}>
  272. <label>Require TLS<br>
  273. <small>Proxy target require HTTPS connection</small></label>
  274. </div><br>
  275. <div class="ui checkbox" style="margin-top: 0.6em;">
  276. <input type="checkbox" class="skipVerificationCheckbox" ${upstream.SkipCertValidations?"checked":""}>
  277. <label>Skip Verification<br>
  278. <small>Check this if proxy target is using self signed certificates</small></label>
  279. </div><br>
  280. <div class="ui checkbox" style="margin-top: 0.4em;">
  281. <input type="checkbox" class="SkipWebSocketOriginCheck" ${upstream.SkipWebSocketOriginCheck?"checked":""}>
  282. <label>Skip WebSocket Origin Check<br>
  283. <small>Check this to allow cross-origin websocket requests</small></label>
  284. </div><br>
  285. <!-- Advance Settings -->
  286. <div class="ui advanceUpstreamOptions accordion" style="margin-top:0.6em;">
  287. <div class="title">
  288. <i class="dropdown icon"></i>
  289. Advanced Options
  290. </div>
  291. <div class="content">
  292. <p>Max Concurrent Connections</p>
  293. <div class="ui mini fluid input" style="margin-top: -0.6em;">
  294. <input type="number" min="0" class="maxConn" value="${upstream.MaxConn}">
  295. </div>
  296. <small>Set to 0 for default value (32 connections)</small>
  297. <br>
  298. <p style="margin-top: 0.6em;">Response Timeout</p>
  299. <div class="ui mini right labeled fluid input" style="margin-top: -0.6em;">
  300. <input type="number" min="0" class="respTimeout" value="${upstream.RespTimeout/1000}">
  301. <div class="ui basic label">
  302. Seconds
  303. </div>
  304. </div>
  305. <small>Maximum waiting time before Zoraxy receive server header response, set to 0 for default</small>
  306. <br>
  307. <p style="margin-top: 0.6em;">Idle Timeout</p>
  308. <div class="ui mini right labeled fluid input" style="margin-top: -0.6em;">
  309. <input type="number" min="0" class="idleTimeout" value="${upstream.IdleTimeout/1000}">
  310. <div class="ui basic label">
  311. Seconds
  312. </div>
  313. </div>
  314. <small>Maximum allowed keep-alive time before Zoraxy forcefully close the connection, set to 0 for default</small>
  315. </div>
  316. </div>
  317. </div>
  318. <div class="upstreamActions">
  319. <!-- Change Priority -->
  320. <button class="ui basic circular icon button highPriorityButton" title="Increase Weight" onclick="increaseUpstreamWeight('${domUID}');"><i class="ui arrow up icon"></i></button>
  321. <button class="ui basic circular icon button lowPriorityButton ${downArrowClass}" title="Reduce Weight" onclick="decreaseUpstreamWeight('${domUID}');"><i class="ui arrow down icon"></i></button>
  322. <button class="ui basic circular icon editbtn button" onclick="handleUpstreamOriginEdit('${domUID}');" title="Edit Upstream Destination"><i class="ui grey edit icon"></i></button>
  323. <button style="display:none;" class="ui basic circular icon trashbtn button" onclick="removeUpstream('${domUID}');" title="Remove Upstream"><i class="ui red trash icon"></i></button>
  324. <button style="display:none;" class="ui basic circular icon savebtn button" onclick="saveUpstreamUpdate('${domUID}');" title="Save Changes"><i class="ui green save icon"></i></button>
  325. <button style="display:none;" class="ui basic circular icon cancelbtn button" onclick="initOriginList();" title="Cancel"><i class="ui grey times icon"></i></button>
  326. </div>
  327. </div>`);
  328. }
  329. /* New Upstream Origin Functions */
  330. //Clearn the proxy target value, make sure user do not enter http:// or https://
  331. //and auto select TLS checkbox if https:// exists
  332. function cleanProxyTargetValue(input){
  333. let targetDomain = $(input).val().trim();
  334. if (targetDomain.startsWith("http://")){
  335. targetDomain = targetDomain.substr(7);
  336. $(input).val(targetDomain);
  337. $("#requireTLS").parent().checkbox("set unchecked");
  338. }else if (targetDomain.startsWith("https://")){
  339. targetDomain = targetDomain.substr(8);
  340. $(input).val(targetDomain);
  341. $("#requireTLS").parent().checkbox("set checked");
  342. }else{
  343. //URL does not contains https or http protocol tag
  344. //sniff header
  345. $.cjax({
  346. url: "/api/proxy/tlscheck",
  347. method: "POST",
  348. data: {url: targetDomain},
  349. success: function(data){
  350. if (data.error != undefined){
  351. }else if (data == "https"){
  352. $("#requireTLS").parent().checkbox("set checked");
  353. }else if (data == "http"){
  354. $("#requireTLS").parent().checkbox("set unchecked");
  355. }
  356. }
  357. })
  358. }
  359. }
  360. //Add a new upstream to this http proxy rule
  361. function addNewUpstream(){
  362. let origin = $("#originURL").val().trim();
  363. let requireTLS = $("#requireTLS")[0].checked;
  364. let skipVerification = $("#skipTlsVerification")[0].checked;
  365. let skipWebSocketOriginCheck = $("#SkipWebSocketOriginCheck")[0].checked;
  366. let activateLoadbalancer = $("#activateNewUpstreamCheckbox")[0].checked;
  367. let maxConn = $("#maxConn").val();
  368. let respTimeout = $("#respTimeout").val();
  369. let idleTimeout = $("#idleTimeout").val();
  370. if (maxConn == "" || isNaN(maxConn)){
  371. maxConn = 0;
  372. }
  373. if (respTimeout == "" || isNaN(respTimeout)){
  374. respTimeout = 0;
  375. }
  376. if (idleTimeout == "" || isNaN(idleTimeout)){
  377. idleTimeout = 0;
  378. }
  379. if (origin == ""){
  380. parent.msgbox("Upstream origin cannot be empty", false);
  381. return;
  382. }
  383. //Convert seconds to ms
  384. respTimeout = parseInt(respTimeout) * 1000;
  385. idleTimeout = parseInt(idleTimeout) * 1000;
  386. $.cjax({
  387. url: "/api/proxy/upstream/add",
  388. method: "POST",
  389. data:{
  390. "ep": editingEndpoint.ep,
  391. "origin": origin,
  392. "tls": requireTLS,
  393. "tlsval": skipVerification,
  394. "bpwsorg":skipWebSocketOriginCheck,
  395. "active": activateLoadbalancer,
  396. "maxconn": maxConn,
  397. "respt": respTimeout,
  398. "idlet": idleTimeout,
  399. },
  400. success: function(data){
  401. if (data.error != undefined){
  402. parent.msgbox(data.error, false);
  403. }else{
  404. parent.msgbox("New upstream origin added");
  405. initOriginList();
  406. $("#originURL").val("");
  407. $("#maxConn").val("0");
  408. $("#respTimeout").val("0");
  409. $("#idleTimeout").val("0");
  410. }
  411. }
  412. })
  413. }
  414. //Get a upstream setting data from DOM element
  415. function getUpstreamSettingFromDOM(upstream){
  416. //Get the original setting from DOM payload
  417. let originalSettings = $(upstream).attr("data-payload");
  418. originalSettings = JSON.parse(decodeURIComponent(originalSettings));
  419. //Get the updated settings if any
  420. let requireTLS = $(upstream).find(".reqTLSCheckbox")[0].checked;
  421. let skipTLSVerification = $(upstream).find(".skipVerificationCheckbox")[0].checked;
  422. let skipWebSocketOriginCheck = $(upstream).find(".SkipWebSocketOriginCheck")[0].checked;
  423. //Advance options
  424. let maxConn = $(upstream).find(".maxConn").val();
  425. let respTimeout = $(upstream).find(".respTimeout").val();
  426. let idleTimeout = $(upstream).find(".idleTimeout").val();
  427. if (maxConn == "" || isNaN(maxConn)){
  428. maxConn = 0;
  429. }
  430. if (respTimeout == "" || isNaN(respTimeout)){
  431. respTimeout = 0;
  432. }
  433. if (idleTimeout == "" || isNaN(idleTimeout)){
  434. idleTimeout = 0;
  435. }
  436. respTimeout = parseInt(respTimeout) * 1000;
  437. idleTimeout = parseInt(idleTimeout) * 1000;
  438. //Update the original setting with new one just applied
  439. originalSettings.OriginIpOrDomain = $(upstream).find(".newOrigin").val();
  440. originalSettings.RequireTLS = requireTLS;
  441. originalSettings.SkipCertValidations = skipTLSVerification;
  442. originalSettings.SkipWebSocketOriginCheck = skipWebSocketOriginCheck;
  443. originalSettings.MaxConn = parseInt(maxConn);
  444. originalSettings.RespTimeout = respTimeout;
  445. originalSettings.IdleTimeout = idleTimeout;
  446. //console.log(originalSettings);
  447. return originalSettings;
  448. }
  449. //Handle setting change on upstream config
  450. function saveUpstreamUpdate(upstreamDomID){
  451. let targetDOM = $(`.upstreamEntry[data-domid=${upstreamDomID}]`);
  452. let originalSettings = $(targetDOM).attr("data-payload");
  453. originalSettings = JSON.parse(decodeURIComponent(originalSettings));
  454. let newConfig = getUpstreamSettingFromDOM(targetDOM);
  455. let isActive = $(targetDOM).find(".enableState")[0].checked;
  456. console.log(newConfig);
  457. $.cjax({
  458. url: "/api/proxy/upstream/update",
  459. method: "POST",
  460. data: {
  461. ep: editingEndpoint.ep,
  462. origin: originalSettings.OriginIpOrDomain, //Original ip or domain as key
  463. payload: JSON.stringify(newConfig),
  464. active: isActive,
  465. },
  466. success: function(data){
  467. if (data.error != undefined){
  468. parent.msgbox(data.error, false);
  469. }else{
  470. parent.msgbox("Upstream setting updated");
  471. initOriginList();
  472. }
  473. }
  474. })
  475. }
  476. //Edit the upstream origin of this upstream entry
  477. function handleUpstreamOriginEdit(upstreamDomID){
  478. let targetDOM = $(`.upstreamEntry[data-domid=${upstreamDomID}]`);
  479. let originalSettings = getUpstreamSettingsFromDomID(upstreamDomID);
  480. let originIP = originalSettings.OriginIpOrDomain;
  481. //Change the UI to edit mode
  482. $(".editbtn").hide();
  483. $(".lowPriorityButton").hide();
  484. $(".highPriorityButton").hide();
  485. $(targetDOM).find(".trashbtn").show();
  486. $(targetDOM).find(".savebtn").show();
  487. $(targetDOM).find(".cancelbtn").show();
  488. $(targetDOM).find(".advanceOptions").show();
  489. }
  490. //Check if the entered URL contains http or https
  491. function handleAutoOriginClean(domid){
  492. let targetDOM = $(`.upstreamEntry[data-domid=${domid}]`);
  493. let targetTLSCheckbox = $(targetDOM).find(".reqTLSCheckbox");
  494. let targetDomain = $(targetDOM).find(".newOrigin").val().trim();
  495. if (targetDomain.startsWith("http://")){
  496. targetDomain = targetDomain.substr(7);
  497. $(input).val(targetDomain);
  498. $(targetTLSCheckbox).parent().checkbox("set unchecked");
  499. }else if (targetDomain.startsWith("https://")){
  500. targetDomain = targetDomain.substr(8);
  501. $(input).val(targetDomain);
  502. $(targetTLSCheckbox).parent().checkbox("set checked");
  503. }else{
  504. //URL does not contains https or http protocol tag
  505. //sniff header
  506. $.cjax({
  507. url: "/api/proxy/tlscheck",
  508. method: "POST",
  509. data: {url: targetDomain},
  510. success: function(data){
  511. if (data.error != undefined){
  512. }else if (data == "https"){
  513. $(targetTLSCheckbox).parent().checkbox("set checked");
  514. }else if (data == "http"){
  515. $(targetTLSCheckbox).parent().checkbox("set unchecked");
  516. }
  517. }
  518. })
  519. }
  520. }
  521. function getUpstreamSettingsFromDomID(domid){
  522. let targetDOM = $(`.upstreamEntry[data-domid=${domid}]`);
  523. if (targetDOM.length == 0){
  524. return undefined;
  525. }
  526. let upstreamSettings = $(targetDOM).attr("data-payload");
  527. upstreamSettings = JSON.parse(decodeURIComponent(upstreamSettings));
  528. return upstreamSettings;
  529. }
  530. function increaseUpstreamWeight(domid){
  531. let upstreamSetting = getUpstreamSettingsFromDomID(domid);
  532. let originIP = upstreamSetting.OriginIpOrDomain;
  533. let currentWeight = upstreamSetting.Weight;
  534. setUpstreamWeight(originIP, currentWeight+1);
  535. }
  536. function decreaseUpstreamWeight(domid){
  537. let upstreamSetting = getUpstreamSettingsFromDomID(domid);
  538. let originIP = upstreamSetting.OriginIpOrDomain;
  539. let currentWeight = upstreamSetting.Weight;
  540. setUpstreamWeight(originIP, currentWeight-1);
  541. }
  542. //Set a weight of a upstream
  543. function setUpstreamWeight(originIP, newWeight){
  544. $.cjax({
  545. url: "/api/proxy/upstream/setPriority",
  546. method: "POST",
  547. data: {
  548. ep: editingEndpoint.ep,
  549. origin: originIP,
  550. weight: newWeight,
  551. },
  552. success: function(data){
  553. if (data.error != undefined){
  554. parent.msgbox(data.error, false);
  555. }else{
  556. parent.msgbox("Upstream Weight Updated");
  557. initOriginList();
  558. }
  559. }
  560. })
  561. }
  562. //Handle removal of an upstream
  563. function removeUpstream(domid){
  564. let targetDOM = $(`.upstreamEntry[data-domid=${domid}]`);
  565. let originalSettings = $(targetDOM).attr("data-payload");
  566. originalSettings = JSON.parse(decodeURIComponent(originalSettings));
  567. let UpstreamKey = originalSettings.OriginIpOrDomain;
  568. if (!confirm("Confirm removing " + UpstreamKey + " from upstream?")){
  569. return;
  570. }
  571. //Remove the upstream
  572. $.cjax({
  573. url: "/api/proxy/upstream/remove",
  574. method: "POST",
  575. data: {
  576. ep: editingEndpoint.ep,
  577. origin: originalSettings.OriginIpOrDomain, //Original ip or domain as key
  578. },
  579. success: function(data){
  580. if (data.error != undefined){
  581. parent.msgbox(data.error, false);
  582. }else{
  583. parent.msgbox("Upstream deleted");
  584. initOriginList();
  585. }
  586. }
  587. })
  588. }
  589. if (window.location.hash.length > 1){
  590. let payloadHash = window.location.hash.substr(1);
  591. try{
  592. payloadHash = JSON.parse(decodeURIComponent(payloadHash));
  593. $(".epname").text(payloadHash.ep);
  594. editingEndpoint = payloadHash;
  595. initOriginList();
  596. }catch(ex){
  597. console.log("Unable to load endpoint data from hash")
  598. }
  599. }
  600. function closeThisWrapper(){
  601. parent.hideSideWrapper(true);
  602. }
  603. </script>
  604. </body>
  605. </html>