upstreams.html 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. <!DOCTYPE html>
  2. <html>
  3. <head>
  4. <!-- Notes: This should be open in its original path-->
  5. <link rel="stylesheet" href="../script/semantic/semantic.min.css">
  6. <script src="../script/jquery-3.6.0.min.js"></script>
  7. <script src="../script/semantic/semantic.min.js"></script>
  8. <style>
  9. .upstreamActions{
  10. position: absolute;
  11. top: 0.6em;
  12. right: 0.6em;
  13. }
  14. .upstreamLink{
  15. max-width: 220px;
  16. display: inline-block;
  17. word-break: break-all;
  18. }
  19. .ui.toggle.checkbox input:checked ~ label::before{
  20. background-color: #00ca52 !important;
  21. }
  22. @media (max-width: 499px) {
  23. .upstreamActions{
  24. position: relative;
  25. margin-top: 1em;
  26. margin-left: 0.4em;
  27. margin-bottom: 0.4em;
  28. }
  29. }
  30. </style>
  31. </head>
  32. <body>
  33. <br>
  34. <div class="ui container">
  35. <div class="ui header">
  36. <div class="content">
  37. Upstreams / Load Balance
  38. <div class="sub header epname"></div>
  39. </div>
  40. </div>
  41. <div class="ui divider"></div>
  42. <div class="ui small pointing secondary menu">
  43. <a class="item active narrowpadding" data-tab="upstreamlist">Upstreams</a>
  44. <a class="item narrowpadding" data-tab="newupstream">Add Upstream</a>
  45. </div>
  46. <div class="ui tab basic segment active" data-tab="upstreamlist">
  47. <!-- A list of current existing upstream on this reverse proxy-->
  48. <div id="upstreamTable">
  49. <div class="ui segment">
  50. <a><i class="ui loading spinner icon"></i> Loading</a>
  51. </div>
  52. </div>
  53. <div class="ui message">
  54. <i class="ui blue info circle icon"></i> Round-robin load balancing algorithm will be used for upstreams with same priority. Lower priority origin server will be used as fallback when all the higher priority server are offline.
  55. </div>
  56. </div>
  57. <div class="ui tab basic segment" data-tab="newupstream">
  58. <!-- Web Form to create a new upstream -->
  59. <h4 class="ui header">
  60. <i class="green add icon"></i>
  61. <div class="content">
  62. Add Upstream Server
  63. <div class="sub header">Create new fallback or load balance upstream</div>
  64. </div>
  65. </h4>
  66. <p style="margin-bottom: 0.4em;">Target IP address with port</p>
  67. <div class="ui fluid small input">
  68. <input type="text" placeholder="" onchange="cleanProxyTargetValue(this);"><br>
  69. </div>
  70. <small>E.g. 192.168.0.101:8000 or example.com</small>
  71. <br><br>
  72. <div class="ui checkbox">
  73. <input type="checkbox" id="requireTLS">
  74. <label>Require TLS<br>
  75. <small>Proxy target require HTTPS connection</small></label>
  76. </div><br>
  77. <div class="ui checkbox" style="margin-top: 0.6em;">
  78. <input type="checkbox" id="skipTlsVerification">
  79. <label>Skip Verification<br>
  80. <small>Check this if proxy target is using self signed certificates</small></label>
  81. </div><br>
  82. <div class="ui checkbox" style="margin-top: 0.4em;">
  83. <input type="checkbox" id="SkipWebSocketOriginCheck" ${upstream.SkipWebSocketOriginCheck?"checked":""}>
  84. <label>Skip WebSocket Origin Check<br>
  85. <small>Check this to allow cross-origin websocket requests</small></label>
  86. </div>
  87. <br><br>
  88. <button class="ui basic button"><i class="ui green circle check icon"></i> Create</button>
  89. </div>
  90. <div class="ui divider"></div>
  91. <div class="field" >
  92. <button class="ui basic button" style="float: right;" onclick="closeThisWrapper();">Close</button>
  93. </div>
  94. </div>
  95. <br><br><br><br>
  96. </div>
  97. <script>
  98. let origins = [];
  99. let editingEndpoint = {};
  100. $('.menu .item').tab();
  101. function initOriginList(){
  102. $.ajax({
  103. url: "/api/proxy/detail",
  104. method: "POST",
  105. data: {
  106. "type":"host",
  107. "epname": editingEndpoint.ep
  108. },
  109. success: function(data){
  110. if (data.error != undefined){
  111. //This endpoint not exists?
  112. alert(data.error);
  113. return;
  114. }else{
  115. $("#upstreamTable").html("");
  116. if (data.Origins != undefined){
  117. origins = data.Origins;
  118. console.log(origins);
  119. data.Origins.forEach(upstream => {
  120. let tlsIcon = "";
  121. if (upstream.RequireTLS){
  122. tlsIcon = `<i class="green lock icon" title="TLS Mode"></i>`;
  123. if (upstream.SkipCertValidations){
  124. tlsIcon = `<i class="yellow lock icon" title="TLS/SSL mode without verification"></i>`
  125. }
  126. }
  127. //Priority Arrows
  128. let upArrowClass = "";
  129. if (upstream.Priority == 0 ){
  130. //Cannot go any higher
  131. upArrowClass = "disabled";
  132. }
  133. let url = `${upstream.RequireTLS?"https://":"http://"}${upstream.OriginIpOrDomain}`
  134. $("#upstreamTable").append(`<div class="ui segment">
  135. <h4 class="ui header">
  136. <div class="ui toggle checkbox" style="display:inline-block;">
  137. <input type="checkbox" name="enabled" style="margin-top: 0.4em;" ${!upstream.Disabled?"checked":""}>
  138. <label></label>
  139. </div>
  140. <div class="content">
  141. <a href="${url}" target="_blank" class="upstreamLink">${upstream.OriginIpOrDomain} ${tlsIcon}</a>
  142. <div class="sub header">Online | Priority: ${upstream.Priority}</div>
  143. </div>
  144. </h4>
  145. <div class="ui divider"></div>
  146. <div class="ui checkbox">
  147. <input type="checkbox" name="example">
  148. <label>Require TLS<br>
  149. <small>Proxy target require HTTPS connection</small></label>
  150. </div><br>
  151. <div class="ui checkbox" style="margin-top: 0.6em;">
  152. <input type="checkbox" name="example">
  153. <label>Skip Verification<br>
  154. <small>Check this if proxy target is using self signed certificates</small></label>
  155. </div><br>
  156. <div class="ui checkbox" style="margin-top: 0.4em;">
  157. <input type="checkbox" class="SkipWebSocketOriginCheck" ${upstream.SkipWebSocketOriginCheck?"checked":""}>
  158. <label>Skip WebSocket Origin Check<br>
  159. <small>Check this to allow cross-origin websocket requests</small></label>
  160. </div><br>
  161. <div class="upstreamActions">
  162. <!-- Change Priority -->
  163. <button class="ui basic circular icon button ${upArrowClass} highPriorityButton" title="Higher Priority"><i class="ui arrow up icon"></i></button>
  164. <button class="ui basic circular icon button lowPriorityButton" title="Lower Priority"><i class="ui arrow down icon"></i></button>
  165. <button class="ui basic circular icon button" title="Edit Upstream Destination"><i class="ui grey edit icon"></i></button>
  166. <button class="ui basic circular icon button" title="Remove Upstream"><i class="ui red trash icon"></i></button>
  167. </div>
  168. </div>`);
  169. });
  170. if (data.Origins.length == 1){
  171. $(".lowPriorityButton").addClass('disabled');
  172. }
  173. $(".ui.checkbox").checkbox();
  174. }else{
  175. //Assume no origins
  176. $("#inlineEditTable").html(`<tr>
  177. <td colspan="2"><i class="ui red circle times icon"></i> Invalid Upstream Settings</td>
  178. </tr>`);
  179. }
  180. }
  181. }
  182. })
  183. }
  184. /* New Upstream Origin Functions */
  185. //Clearn the proxy target value, make sure user do not enter http:// or https://
  186. //and auto select TLS checkbox if https:// exists
  187. function cleanProxyTargetValue(input){
  188. let targetDomain = $(input).val().trim();
  189. if (targetDomain.startsWith("http://")){
  190. targetDomain = targetDomain.substr(7);
  191. $(input).val(targetDomain);
  192. $("#requireTLS").parent().checkbox("set unchecked");
  193. }else if (targetDomain.startsWith("https://")){
  194. targetDomain = targetDomain.substr(8);
  195. $(input).val(targetDomain);
  196. $("#requireTLS").parent().checkbox("set checked");
  197. }
  198. }
  199. if (window.location.hash.length > 1){
  200. let payloadHash = window.location.hash.substr(1);
  201. try{
  202. payloadHash = JSON.parse(decodeURIComponent(payloadHash));
  203. $(".epname").text(payloadHash.ep);
  204. editingEndpoint = payloadHash;
  205. initOriginList();
  206. }catch(ex){
  207. console.log("Unable to load endpoint data from hash")
  208. }
  209. }
  210. function closeThisWrapper(){
  211. parent.hideSideWrapper(true);
  212. }
  213. </script>
  214. </body>
  215. </html>