customHeaders.html 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244
  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. $("#headerValue").val("");
  95. });
  96. //Bind events to header directions option
  97. $("#toOriginButton").on("click", function(){
  98. $("#toOriginButton").addClass("active");
  99. $("#toClientButton").removeClass("active");
  100. });
  101. $("#toClientButton").on("click", function(){
  102. $("#toOriginButton").removeClass("active");
  103. $("#toClientButton").addClass("active");
  104. });
  105. //Return "add" or "remove" depending on mode user selected
  106. function getHeaderEditMode(){
  107. if ($("#headerModeAdd").hasClass("active")){
  108. return "add";
  109. }
  110. return "remove";
  111. }
  112. //Return "toOrigin" or "toClient"
  113. function getHeaderDirection(){
  114. if ($("#toOriginButton").hasClass("active")){
  115. return "toOrigin";
  116. }
  117. return "toClient";
  118. }
  119. //$("#debug").text(JSON.stringify(editingEndpoint));
  120. function addCustomHeader(){
  121. let name = $("#headerName").val().trim();
  122. let value = $("#headerValue").val().trim();
  123. if (name == ""){
  124. $("#headerName").parent().addClass("error");
  125. return
  126. }else{
  127. $("#headerName").parent().removeClass("error");
  128. }
  129. if (getHeaderEditMode() == "add"){
  130. if (value == ""){
  131. $("#headerValue").parent().addClass("error");
  132. return
  133. }else{
  134. $("#headerValue").parent().removeClass("error");
  135. }
  136. }
  137. $.ajax({
  138. url: "/api/proxy/header/add",
  139. data: {
  140. "type": getHeaderEditMode(),
  141. "domain": editingEndpoint.ep,
  142. "direction":getHeaderDirection(),
  143. "name": name,
  144. "value": value
  145. },
  146. success: function(data){
  147. if (data.error != undefined){
  148. if (parent != undefined && parent.msgbox != undefined){
  149. parent.msgbox(data.error,false);
  150. }else{
  151. alert(data.error);
  152. }
  153. }else{
  154. listCustomHeaders();
  155. if (parent != undefined && parent.msgbox != undefined){
  156. parent.msgbox("Custom header added",true);
  157. }
  158. //Clear the form
  159. $("#headerName").val("");
  160. $("#headerValue").val("");
  161. }
  162. }
  163. });
  164. }
  165. function deleteCustomHeader(name){
  166. $.ajax({
  167. url: "/api/proxy/header/remove",
  168. data: {
  169. //"type": editingEndpoint.ept,
  170. "domain": editingEndpoint.ep,
  171. "name": name,
  172. },
  173. success: function(data){
  174. listCustomHeaders();
  175. if (parent != undefined && parent.msgbox != undefined){
  176. parent.msgbox("Custom header removed",true);
  177. }
  178. }
  179. });
  180. }
  181. function listCustomHeaders(){
  182. $("#headerTable").html(`<tr><td colspan="3"><i class="ui loading spinner icon"></i> Loading</td></tr>`);
  183. $.ajax({
  184. url: "/api/proxy/header/list",
  185. data: {
  186. "type": editingEndpoint.ept,
  187. "domain": editingEndpoint.ep,
  188. },
  189. success: function(data){
  190. if (data.error != undefined){
  191. alert(data.error);
  192. }else{
  193. $("#headerTable").html("");
  194. data.forEach(header => {
  195. let editModeIcon = header.IsRemove?`<i class="ui red times circle icon"></i>`:`<i class="ui green add circle icon"></i>`;
  196. let direction = (header.Direction==0)?`<i class="angle double right blue icon"></i>`:`<i class="angle double left orange icon"></i>`;
  197. let valueField = header.Value;
  198. if (header.IsRemove){
  199. valueField = "<small style='color: grey;'>(Field Removed)</small>";
  200. }
  201. $("#headerTable").append(`
  202. <tr>
  203. <td>${direction} ${header.Key}</td>
  204. <td>${editModeIcon} ${valueField}</td>
  205. <td><button class="ui basic circular mini red icon button" onclick="deleteCustomHeader('${header.Key}');"><i class="ui trash icon"></i></button></td>
  206. </tr>
  207. `);
  208. });
  209. if (data.length == 0){
  210. $("#headerTable").html(`<tr>
  211. <td colspan="3"><i class="ui green circle check icon"></i> No Additonal Header</td>
  212. </tr>`);
  213. }
  214. }
  215. },
  216. });
  217. }
  218. listCustomHeaders();
  219. </script>
  220. </body>
  221. </html>