customHeaders.html 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  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. </head>
  9. <body>
  10. <br>
  11. <div class="ui container">
  12. <div class="ui header">
  13. <div class="content">
  14. Custom Headers
  15. <div class="sub header" id="epname"></div>
  16. </div>
  17. </div>
  18. <div class="ui divider"></div>
  19. <p>You can define custom headers to be sent
  20. together with the client request to the backend server in
  21. this reverse proxy endpoint / host.</p>
  22. <table class="ui very basic compacted unstackable celled table">
  23. <thead>
  24. <tr>
  25. <th>Key</th>
  26. <th>Value</th>
  27. <th>Remove</th>
  28. </tr></thead>
  29. <tbody id="headerTable">
  30. <tr>
  31. <td colspan="3"><i class="ui green circle check icon"></i> No Additonal Header</td>
  32. </tr>
  33. </tbody>
  34. </table>
  35. <div class="ui divider"></div>
  36. <h4>Edit Custom Header</h4>
  37. <p>Add or remove custom header(s) over this proxy target</p>
  38. <div class="scrolling content ui form">
  39. <div class="five small fields credentialEntry">
  40. <div class="field" align="center">
  41. <button id="toOriginButton" title="Downstream to Upstream" class="ui circular basic active button">Zoraxy <i class="angle double right blue icon" style="margin-right: 0.4em;"></i> Origin</button>
  42. <button id="toClientButton" title="Upstream to Downstream" class="ui circular basic button">Client <i class="angle double left orange icon" style="margin-left: 0.4em;"></i> Zoraxy</button>
  43. </div>
  44. <div class="field" align="center">
  45. <button id="headerModeAdd" class="ui circular basic active button"><i class="ui green circle add icon"></i> Add Header</button>
  46. <button id="headerModeRemove" class="ui circular basic button"><i class="ui red circle times icon"></i> Remove Header</button>
  47. </div>
  48. <div class="field">
  49. <label>Header Key</label>
  50. <input id="headerName" type="text" placeholder="X-Custom-Header" autocomplete="off">
  51. <small>The header key is <b>NOT</b> case sensitive</small>
  52. </div>
  53. <div class="field">
  54. <label>Header Value</label>
  55. <input id="headerValue" type="text" placeholder="value1,value2,value3" autocomplete="off">
  56. </div>
  57. <div class="field" >
  58. <button class="ui basic button" onclick="addCustomHeader();"><i class="green add icon"></i> Add Header Rewrite Rule</button>
  59. </div>
  60. <div class="ui divider"></div>
  61. </div>
  62. </div>
  63. <div class="ui divider"></div>
  64. <div class="field" >
  65. <button class="ui basic button" style="float: right;" onclick="closeThisWrapper();">Close</button>
  66. </div>
  67. </div>
  68. <br><br><br><br>
  69. <script>
  70. let editingEndpoint = {};
  71. if (window.location.hash.length > 1){
  72. let payloadHash = window.location.hash.substr(1);
  73. try{
  74. payloadHash = JSON.parse(decodeURIComponent(payloadHash));
  75. $("#epname").text(payloadHash.ep);
  76. editingEndpoint = payloadHash;
  77. }catch(ex){
  78. console.log("Unable to load endpoint data from hash")
  79. }
  80. }
  81. function closeThisWrapper(){
  82. parent.hideSideWrapper(true);
  83. }
  84. //Bind events to header mod mode
  85. $("#headerModeAdd").on("click", function(){
  86. $("#headerModeAdd").addClass("active");
  87. $("#headerModeRemove").removeClass("active");
  88. $("#headerValue").parent().show();
  89. });
  90. $("#headerModeRemove").on("click", function(){
  91. $("#headerModeAdd").removeClass("active");
  92. $("#headerModeRemove").addClass("active");
  93. $("#headerValue").parent().hide();
  94. });
  95. //Bind events to header directions option
  96. $("#toOriginButton").on("click", function(){
  97. $("#toOriginButton").addClass("active");
  98. $("#toClientButton").removeClass("active");
  99. });
  100. $("#toClientButton").on("click", function(){
  101. $("#toOriginButton").removeClass("active");
  102. $("#toClientButton").addClass("active");
  103. });
  104. //Return "add" or "remove" depending on mode user selected
  105. function getHeaderEditMode(){
  106. if ($("#headerModeAdd").hasClass("active")){
  107. return "add";
  108. }
  109. return "remove";
  110. }
  111. //Return "toOrigin" or "toClient"
  112. function getHeaderDirection(){
  113. if ($("#toOriginButton").hasClass("active")){
  114. return "toOrigin";
  115. }
  116. return "toClient";
  117. }
  118. //$("#debug").text(JSON.stringify(editingEndpoint));
  119. function addCustomHeader(){
  120. let name = $("#headerName").val().trim();
  121. let value = $("#headerValue").val().trim();
  122. if (name == ""){
  123. $("#headerName").parent().addClass("error");
  124. return
  125. }else{
  126. $("#headerName").parent().removeClass("error");
  127. }
  128. if (getHeaderEditMode() == "add"){
  129. if (value == ""){
  130. $("#headerValue").parent().addClass("error");
  131. return
  132. }else{
  133. $("#headerValue").parent().removeClass("error");
  134. }
  135. }
  136. $.ajax({
  137. url: "/api/proxy/header/add",
  138. data: {
  139. "type": getHeaderEditMode(),
  140. "domain": editingEndpoint.ep,
  141. "direction":getHeaderDirection(),
  142. "name": name,
  143. "value": value
  144. },
  145. success: function(data){
  146. if (data.error != undefined){
  147. if (parent != undefined && parent.msgbox != undefined){
  148. parent.msgbox(data.error,false);
  149. }else{
  150. alert(data.error);
  151. }
  152. }else{
  153. listCustomHeaders();
  154. if (parent != undefined && parent.msgbox != undefined){
  155. parent.msgbox("Custom header added",true);
  156. }
  157. //Clear the form
  158. $("#headerName").val("");
  159. $("#headerValue").val("");
  160. }
  161. }
  162. });
  163. }
  164. function deleteCustomHeader(name){
  165. $.ajax({
  166. url: "/api/proxy/header/remove",
  167. data: {
  168. //"type": editingEndpoint.ept,
  169. "domain": editingEndpoint.ep,
  170. "name": name,
  171. },
  172. success: function(data){
  173. listCustomHeaders();
  174. if (parent != undefined && parent.msgbox != undefined){
  175. parent.msgbox("Custom header removed",true);
  176. }
  177. }
  178. });
  179. }
  180. function listCustomHeaders(){
  181. $("#headerTable").html(`<tr><td colspan="3"><i class="ui loading spinner icon"></i> Loading</td></tr>`);
  182. $.ajax({
  183. url: "/api/proxy/header/list",
  184. data: {
  185. "type": editingEndpoint.ept,
  186. "domain": editingEndpoint.ep,
  187. },
  188. success: function(data){
  189. if (data.error != undefined){
  190. alert(data.error);
  191. }else{
  192. $("#headerTable").html("");
  193. data.forEach(header => {
  194. let editModeIcon = header.IsRemove?`<i class="ui red times circle icon"></i>`:`<i class="ui green add circle icon"></i>`;
  195. let direction = (header.Direction==0)?`<i class="angle double right blue icon"></i>`:`<i class="angle double left orange icon"></i>`;
  196. let valueField = header.Value;
  197. if (header.IsRemove){
  198. valueField = "<small style='color: grey;'>(Field Removed)</small>";
  199. }
  200. $("#headerTable").append(`
  201. <tr>
  202. <td>${direction} ${header.Key}</td>
  203. <td>${editModeIcon} ${valueField}</td>
  204. <td><button class="ui basic circular mini red icon button" onclick="deleteCustomHeader('${header.Key}');"><i class="ui trash icon"></i></button></td>
  205. </tr>
  206. `);
  207. });
  208. if (data.length == 0){
  209. $("#headerTable").html(`<tr>
  210. <td colspan="3"><i class="ui green circle check icon"></i> No Additonal Header</td>
  211. </tr>`);
  212. }
  213. }
  214. },
  215. });
  216. }
  217. listCustomHeaders();
  218. </script>
  219. </body>
  220. </html>