upstreams.html 12 KB

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