From d9e74df9ebf0ca6f2382ce4d34aac28ee20f3c10 Mon Sep 17 00:00:00 2001 From: kulikov-a Date: Sat, 6 Sep 2025 19:32:23 +0300 Subject: [PATCH] nginx_1.35 (#4600) --- www/nginx/Makefile | 3 +- www/nginx/pkg-descr | 9 +++ .../OPNsense/Nginx/Api/SettingsController.php | 26 +++++++++ .../OPNsense/Nginx/IndexController.php | 1 + .../OPNsense/Nginx/forms/httpserver.xml | 17 +++++- .../OPNsense/Nginx/forms/location.xml | 18 +++++- .../Nginx/forms/proxy_cache_valid.xml | 22 +++++++ .../OPNsense/Nginx/forms/settings.xml | 16 ++++- .../mvc/app/models/OPNsense/Nginx/Nginx.xml | 58 ++++++++++++++++++- .../mvc/app/views/OPNsense/Nginx/index.volt | 28 +++++++++ .../src/opnsense/scripts/nginx/setup.php | 24 +++++--- .../templates/OPNsense/Nginx/http.conf | 9 ++- .../templates/OPNsense/Nginx/location.conf | 11 +++- .../www/js/nginx/dist/configuration.min.js | 2 +- .../opnsense/www/js/nginx/src/nginx_config.js | 1 + 15 files changed, 228 insertions(+), 17 deletions(-) create mode 100644 www/nginx/src/opnsense/mvc/app/controllers/OPNsense/Nginx/forms/proxy_cache_valid.xml diff --git a/www/nginx/Makefile b/www/nginx/Makefile index a952c7337..c16651e7d 100644 --- a/www/nginx/Makefile +++ b/www/nginx/Makefile @@ -1,6 +1,5 @@ PLUGIN_NAME= nginx -PLUGIN_VERSION= 1.34 -PLUGIN_REVISION= 8 +PLUGIN_VERSION= 1.35 PLUGIN_COMMENT= Nginx HTTP server and reverse proxy PLUGIN_DEPENDS= nginx PLUGIN_MAINTAINER= franz.fabian.94@gmail.com diff --git a/www/nginx/pkg-descr b/www/nginx/pkg-descr index 0f7cb8ac8..ce2b4b95b 100644 --- a/www/nginx/pkg-descr +++ b/www/nginx/pkg-descr @@ -10,6 +10,15 @@ WWW: https://nginx.org/ Plugin Changelog ================ +1.35 + +* Global options sendfile directive typo fix +* Add HTTP/2 option to GUI +* Add multiple client authentication trusted CA support +* Add proxy_intercept_errors directive support +* Add Variables hashes size support +* Add proxy_cache_valid directive support with response codes and multiple selection options + 1.34 * Add the option to not log TLS handshakes diff --git a/www/nginx/src/opnsense/mvc/app/controllers/OPNsense/Nginx/Api/SettingsController.php b/www/nginx/src/opnsense/mvc/app/controllers/OPNsense/Nginx/Api/SettingsController.php index 0458bc2aa..7b2043b90 100644 --- a/www/nginx/src/opnsense/mvc/app/controllers/OPNsense/Nginx/Api/SettingsController.php +++ b/www/nginx/src/opnsense/mvc/app/controllers/OPNsense/Nginx/Api/SettingsController.php @@ -249,6 +249,32 @@ class SettingsController extends ApiMutableModelControllerBase return $this->setBase('resolver', 'resolver', $uuid); } + // proxy_cache_valid + public function searchproxyCacheValidAction() + { + return $this->searchBase('proxy_cache_valid', array('uuid', 'description', 'code', 'valid')); + } + + public function getproxyCacheValidAction($uuid = null) + { + return $this->getBase('proxy_cache_valid', 'proxy_cache_valid', $uuid); + } + + public function addproxyCacheValidAction() + { + return $this->addBase('proxy_cache_valid', 'proxy_cache_valid'); + } + + public function delproxyCacheValidAction($uuid) + { + return $this->delBase('proxy_cache_valid', $uuid); + } + + public function setproxyCacheValidAction($uuid) + { + return $this->setBase('proxy_cache_valid', 'proxy_cache_valid', $uuid); + } + // http server public function searchhttpserverAction() { diff --git a/www/nginx/src/opnsense/mvc/app/controllers/OPNsense/Nginx/IndexController.php b/www/nginx/src/opnsense/mvc/app/controllers/OPNsense/Nginx/IndexController.php index a30d036d1..01ad3330a 100644 --- a/www/nginx/src/opnsense/mvc/app/controllers/OPNsense/Nginx/IndexController.php +++ b/www/nginx/src/opnsense/mvc/app/controllers/OPNsense/Nginx/IndexController.php @@ -64,6 +64,7 @@ class IndexController extends \OPNsense\Base\IndexController $this->view->errorpage = $this->getForm("errorpage"); $this->view->tls_fingerprint = $this->getForm("tls_fingerprint"); $this->view->resolver = $this->getForm("resolver"); + $this->view->proxy_cache_valid = $this->getForm("proxy_cache_valid"); $this->view->syslog_target = $this->getForm("syslog_target"); $nginx = new Nginx(); $this->view->show_naxsi_download_button = diff --git a/www/nginx/src/opnsense/mvc/app/controllers/OPNsense/Nginx/forms/httpserver.xml b/www/nginx/src/opnsense/mvc/app/controllers/OPNsense/Nginx/forms/httpserver.xml index 33cf1ce52..21f8b4a28 100644 --- a/www/nginx/src/opnsense/mvc/app/controllers/OPNsense/Nginx/forms/httpserver.xml +++ b/www/nginx/src/opnsense/mvc/app/controllers/OPNsense/Nginx/forms/httpserver.xml @@ -113,7 +113,8 @@ httpserver.ca - dropdown + select_multiple + Trusted CA certificates httpserver.verify_client @@ -165,6 +166,13 @@ checkbox If the request scheme is not HTTPS, redirect to use HTTPS for this server. + + httpserver.http2 + + checkbox + Enable the HTTP/2 protocol. + true + httpserver.tls_protocols @@ -320,4 +328,11 @@ select_multiple Select custom error pages to display instead of the default builtin error pages. If at least one error page is selected here, all default error pages will be disabled. + + httpserver.proxy_intercept_errors + + checkbox + Intercept responses with codes greater than or equal to 300 and redirect to processing with custom error pages. + true + diff --git a/www/nginx/src/opnsense/mvc/app/controllers/OPNsense/Nginx/forms/location.xml b/www/nginx/src/opnsense/mvc/app/controllers/OPNsense/Nginx/forms/location.xml index d6ee67abb..23fdccff5 100644 --- a/www/nginx/src/opnsense/mvc/app/controllers/OPNsense/Nginx/forms/location.xml +++ b/www/nginx/src/opnsense/mvc/app/controllers/OPNsense/Nginx/forms/location.xml @@ -98,11 +98,19 @@ location.cache_valid - + text true Force caching of 200, 301 and 302 responses according to the request methods enabled for caching. Given in minutes; leave empty to rely on request/response headers from client and upstream. + + location.proxy_cache_valid + + select_multiple + + true + Force caching of response codes specified at Response Code Caching page. + location.cache_background_update @@ -335,4 +343,12 @@ select_multiple Select custom error pages to display instead of the default builtin error pages. Selection will override error pages configured on HTTP server. + + location.proxy_intercept_errors + + dropdown + + Intercept responses with codes greater than or equal to 300 and redirect to processing with custom error pages. + true + diff --git a/www/nginx/src/opnsense/mvc/app/controllers/OPNsense/Nginx/forms/proxy_cache_valid.xml b/www/nginx/src/opnsense/mvc/app/controllers/OPNsense/Nginx/forms/proxy_cache_valid.xml new file mode 100644 index 000000000..e37702e9d --- /dev/null +++ b/www/nginx/src/opnsense/mvc/app/controllers/OPNsense/Nginx/forms/proxy_cache_valid.xml @@ -0,0 +1,22 @@ +
+ + proxy_cache_valid.description + + text + Brief description for reference. + + + proxy_cache_valid.code + + true + + select_multiple + Enter a Respone codes or use "any" to cache any responses. + + + proxy_cache_valid.valid + + text + Specify caching time in minutes. + +
diff --git a/www/nginx/src/opnsense/mvc/app/controllers/OPNsense/Nginx/forms/settings.xml b/www/nginx/src/opnsense/mvc/app/controllers/OPNsense/Nginx/forms/settings.xml index 8ac01921c..3afcab4c6 100644 --- a/www/nginx/src/opnsense/mvc/app/controllers/OPNsense/Nginx/forms/settings.xml +++ b/www/nginx/src/opnsense/mvc/app/controllers/OPNsense/Nginx/forms/settings.xml @@ -31,7 +31,7 @@ true - nginx.http.enabled + nginx.http.sendfile checkbox Enable sendfile support (faster). @@ -56,7 +56,7 @@ nginx.http.server_names_hash_bucket_size - + text true @@ -66,6 +66,18 @@ text true + + nginx.http.variables_hash_bucket_size + + text + true + + + nginx.http.variables_hash_max_size + + text + true + nginx.http.bots_ua diff --git a/www/nginx/src/opnsense/mvc/app/models/OPNsense/Nginx/Nginx.xml b/www/nginx/src/opnsense/mvc/app/models/OPNsense/Nginx/Nginx.xml index fdc25d56d..423b56422 100644 --- a/www/nginx/src/opnsense/mvc/app/models/OPNsense/Nginx/Nginx.xml +++ b/www/nginx/src/opnsense/mvc/app/models/OPNsense/Nginx/Nginx.xml @@ -1,6 +1,6 @@ //OPNsense/Nginx - 1.34 + 1.35 nginx web server, reverse proxy and waf @@ -56,6 +56,14 @@ N 1 + + N + 1 + + + N + 1 + N @@ -352,6 +360,18 @@ N + + + + + Selected caching time settings not found + N + Y + Y 0 @@ -557,6 +577,15 @@ N Y + + Inherit + Y + + Inherit + On + Off + + @@ -827,6 +856,7 @@ ca N + Y Off @@ -881,6 +911,10 @@ 0 Y + + 1 + Y + Y Y @@ -1038,6 +1072,10 @@ N Y + + 0 + Y + @@ -1955,6 +1993,24 @@ + + + Y + /^[^" \t]+$/i + + + Y + any + Y + /(^\d{3}(,\d{3})*$)|(^any$)/ + Please use three digit response code(s) or use "any" word. + + + 1 + Y + + + Y diff --git a/www/nginx/src/opnsense/mvc/app/views/OPNsense/Nginx/index.volt b/www/nginx/src/opnsense/mvc/app/views/OPNsense/Nginx/index.volt index 5c715e748..f64990afb 100644 --- a/www/nginx/src/opnsense/mvc/app/views/OPNsense/Nginx/index.volt +++ b/www/nginx/src/opnsense/mvc/app/views/OPNsense/Nginx/index.volt @@ -193,6 +193,9 @@
  • {{ lang._('Cache Path')}}
  • +
  • + {{ lang._('Response Code Caching')}} +
  • {{ lang._('Error Pages')}}
  • @@ -603,6 +606,30 @@ +
    + + + + + + + + + + + + + + + + + + +
    {{ lang._('ID') }}{{ lang._('Description') }}{{ lang._('Codes') }}{{ lang._('Time') }}{{ lang._('Commands') }}
    + + +
    +
    @@ -825,6 +852,7 @@ {{ partial("layout_partials/base_dialog",['fields': limit_request_connection,'id':'limit_request_connectiondlg', 'label':lang._('Edit Request Connection Limit')]) }} {{ partial("layout_partials/base_dialog",['fields': limit_zone,'id':'limit_zonedlg', 'label':lang._('Edit Limit Zone')]) }} {{ partial("layout_partials/base_dialog",['fields': cache_path,'id':'cache_pathdlg', 'label':lang._('Edit Cache Path')]) }} +{{ partial("layout_partials/base_dialog",['fields': proxy_cache_valid,'id':'proxy_cache_validdlg', 'label':lang._('Edit Response Code Caching')]) }} {{ partial("layout_partials/base_dialog",['fields': sni_hostname_map,'id':'sni_hostname_mapdlg', 'label':lang._('Edit SNI Hostname Mapping')]) }} {{ partial("layout_partials/base_dialog",['fields': ipacl,'id':'ipacl_dlg', 'label':lang._('Edit IP ACL')]) }} {{ partial("layout_partials/base_dialog",['fields': errorpage,'id':'errorpage_dlg', 'label':lang._('Edit Error Page')]) }} diff --git a/www/nginx/src/opnsense/scripts/nginx/setup.php b/www/nginx/src/opnsense/scripts/nginx/setup.php index 96a863c74..2e92730c2 100755 --- a/www/nginx/src/opnsense/scripts/nginx/setup.php +++ b/www/nginx/src/opnsense/scripts/nginx/setup.php @@ -120,15 +120,25 @@ if (isset($nginx['http_server'])) { $cert['prv'] ); if (!empty($http_server['ca'])) { - foreach ($http_server['ca'] as $caref) { - $ca = find_ca($caref); - if (isset($ca)) { - export_pem_file( - KEY_DIRECTORY . $hostname . '_ca.pem', - $ca['crt'] - ); + syslog(LOG_DEBUG, "NGINX setup: Setting up the CA certs for {$hostname}."); + $ca_certs = []; + foreach ($http_server['ca'] as $carefs) { + foreach(explode(',', $carefs) as $caref) { + syslog(LOG_DEBUG, "NGINX setup: Searching for {$caref} CA data"); + $ca = find_ca($caref); + if (isset($ca)) { + syslog(LOG_DEBUG, "NGINX setup: client auth CA found. Adding to the list"); + $ca_certs[] = base64_decode($ca['crt']); + } } } + if (count($ca_certs) > 0) { + export_pem_file( + KEY_DIRECTORY . $hostname . '_ca.pem', + '', + implode("\n", $ca_certs) + ); + } } } } diff --git a/www/nginx/src/opnsense/service/templates/OPNsense/Nginx/http.conf b/www/nginx/src/opnsense/service/templates/OPNsense/Nginx/http.conf index 87592f4b4..f787eff2c 100644 --- a/www/nginx/src/opnsense/service/templates/OPNsense/Nginx/http.conf +++ b/www/nginx/src/opnsense/service/templates/OPNsense/Nginx/http.conf @@ -48,6 +48,12 @@ server_names_hash_max_size {{ OPNsense.Nginx.http.server_names_hash_max_size }}; {% if OPNsense.Nginx.http.server_names_hash_bucket_size is defined and OPNsense.Nginx.http.server_names_hash_bucket_size != '' %} server_names_hash_bucket_size {{ OPNsense.Nginx.http.server_names_hash_bucket_size }}; {% endif %} +{% if OPNsense.Nginx.http.variables_hash_max_size is defined and OPNsense.Nginx.http.variables_hash_max_size != '' %} +variables_hash_max_size {{ OPNsense.Nginx.http.variables_hash_max_size }}; +{% endif %} +{% if OPNsense.Nginx.http.variables_hash_bucket_size is defined and OPNsense.Nginx.http.variables_hash_bucket_size != '' %} +variables_hash_bucket_size {{ OPNsense.Nginx.http.variables_hash_bucket_size }}; +{% endif %} {% if OPNsense.Nginx.http.keepalive_timeout is defined and OPNsense.Nginx.http.keepalive_timeout != '' %} keepalive_timeout {{ OPNsense.Nginx.http.keepalive_timeout }}; {% endif %} @@ -117,7 +123,7 @@ server { {% for listen_address in server.listen_https_address.split(',') %} listen {{ listen_address }} ssl{% if server.proxy_protocol is defined and server.proxy_protocol == '1' %} proxy_protocol{% endif %}{% if server.default_server is defined and server.default_server == '1' %} default_server{% endif %}; {% endfor %} - http2 on; + http2 {% if server.http2|default("1") == "1" %}on{% else %}off{% endif %}; {% if server.tls_reject_handshake is defined and server.tls_reject_handshake == '1'%} ssl_reject_handshake on; {% endif %} @@ -246,6 +252,7 @@ server { root /usr/local/etc/nginx/views; } {% endif %} + proxy_intercept_errors {% if server.proxy_intercept_errors|default("0") == "1" %}on{% else %}off{% endif %}; {% if server.security_header is defined and server.security_header != '' %} {% set security_rule = helpers.getUUID(server.security_header) %} {% if security_rule is defined %} diff --git a/www/nginx/src/opnsense/service/templates/OPNsense/Nginx/location.conf b/www/nginx/src/opnsense/service/templates/OPNsense/Nginx/location.conf index 9f9b57603..71529378b 100644 --- a/www/nginx/src/opnsense/service/templates/OPNsense/Nginx/location.conf +++ b/www/nginx/src/opnsense/service/templates/OPNsense/Nginx/location.conf @@ -47,6 +47,9 @@ location {{ location.matchtype }} {{ location.urlpattern }} { error_page {{ errorpage.statuscodes.replace(',', ' ') }} {% if errorpage.response is defined and errorpage.response != '' %}={{ errorpage.response }} {% endif %}{% if errorpage.redirect is defined and errorpage.redirect != '' %}{{ errorpage.redirect }}{% else %}/error_{{ errorpage_uuid.replace('-', '') }}.html{% endif %}; {% endfor %} {% endif %} +{% if location.proxy_intercept_errors is defined and location.proxy_intercept_errors != 'Inherit' %} + proxy_intercept_errors {{ location.proxy_intercept_errors }}; +{% endif %} {% if location.force_https is defined and location.force_https == '1' %} if ($scheme != "https") { return 302 https://$host$request_uri; @@ -144,7 +147,13 @@ location {{ location.matchtype }} {{ location.urlpattern }} { proxy_cache_use_stale {{ location.cache_use_stale.replace(',', ' ') }}; {% endif %} {% if location.cache_valid is defined and location.cache_valid != '' %} - proxy_cache_valid {{ location.cache_valid }}m; + proxy_cache_valid {{ location.cache_valid }}m; +{% endif %} +{% if location.proxy_cache_valid is defined and location.proxy_cache_valid != '' %} +{% for pcache_valid_uuid in location.proxy_cache_valid.split(',') %} +{% set pcache_valid = helpers.getUUID(pcache_valid_uuid) %} + proxy_cache_valid {{ pcache_valid.code.replace(',', ' ') }} {{ pcache_valid.valid }}m; +{% endfor %} {% endif %} proxy_cache_min_uses {{ location.cache_min_uses|default('1') }}; proxy_cache_background_update {% if location.cache_background_update is defined and location.cache_background_update == '1' %}on{% else %}off{% endif %}; diff --git a/www/nginx/src/opnsense/www/js/nginx/dist/configuration.min.js b/www/nginx/src/opnsense/www/js/nginx/dist/configuration.min.js index 3ef498d00..d25e07387 100644 --- a/www/nginx/src/opnsense/www/js/nginx/dist/configuration.min.js +++ b/www/nginx/src/opnsense/www/js/nginx/dist/configuration.min.js @@ -1 +1 @@ -!function(t){var e={};function n(i){if(e[i])return e[i].exports;var s=e[i]={i:i,l:!1,exports:{}};return t[i].call(s.exports,s,s.exports,n),s.l=!0,s.exports}n.m=t,n.c=e,n.d=function(t,e,i){n.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:i})},n.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},n.t=function(t,e){if(1&e&&(t=n(t)),8&e)return t;if(4&e&&"object"==typeof t&&t&&t.__esModule)return t;var i=Object.create(null);if(n.r(i),Object.defineProperty(i,"default",{enumerable:!0,value:t}),2&e&&"string"!=typeof t)for(var s in t)n.d(i,s,function(e){return t[e]}.bind(null,s));return i},n.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return n.d(e,"a",e),e},n.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},n.p="",n(n.s=25)}({25:function(t,e,n){"use strict";n.r(e);var i=Backbone.View.extend({tagName:"div",attributes:{class:"container-fluid"},child_views:[],createModel:null,upstreamCollection:null,initialize:function(t){this.dataField=$(t.dataField),this.entryclass=t.entryclass,this.createModel=t.createModel,this.upstreamCollection=t.upstreamCollection,this.listenTo(this.collection,"add remove reset",this.render),this.listenTo(this.collection,"change",this.update),this.dataField.after(this.$el)},events:{"click .add":"addEntry"},render:function(){this.child_views.forEach(t=>t.remove()),this.$el.html(""),this.child_views=[],this.update(),this.collection.each(t=>{const e=new this.entryclass({model:t,collection:this.collection,upstreamCollection:this.upstreamCollection});this.child_views.push(e),this.$el.append(e.$el),e.render()}),this.$el.append($('\n
    \n \n
    '))},update:function(){this.dataField.data("data",this.collection.toJSON())},addEntry:function(t){t.preventDefault(),this.collection.add(this.createModel())}});var s=Backbone.Collection.extend({url:"/api/nginx/settings/searchupstream",parse:function(t){return t.rows}});const a=Backbone.View.extend({tagName:"div",attributes:{class:"row"},events:{"keyup .key":function(){this.model.set("hostname",this.key.value)},"change .value":function(){this.model.set("upstream",this.value.value)},"click .delete":"deleteEntry"},key:null,value:null,delBtn:null,first:null,second:null,third:null,upstreamCollection:null,initialize:function(t){this.upstreamCollection=t.upstreamCollection,this.listenTo(this.upstreamCollection,"update reset add remove",this.regenerate_list),this.first=document.createElement("div"),this.first.classList.add("col-sm-5"),this.key=document.createElement("input"),this.first.append(this.key),this.key.type="text",this.key.classList.add("key"),this.key.value=this.model.get("hostname"),this.second=document.createElement("div"),this.second.classList.add("col-sm-5"),this.value=document.createElement("select"),this.second.append(this.value),this.value.classList.add("value"),this.value.classList.add("form-control"),this.value.value=this.model.get("upstream"),this.third=document.createElement("div"),this.third.classList.add("col-sm-2"),this.third.style.textAlign="right",this.delBtn=document.createElement("button"),this.delBtn.classList.add("delete"),this.delBtn.classList.add("btn"),this.delBtn.innerHTML='',this.third.append(this.delBtn),this.model.has("upstream")&&0!==this.upstreamCollection.where({uuid:this.model.get("upstream")}).length||this.upstreamCollection.length>0&&this.model.set("upstream",this.upstreamCollection.at(0).get("uuid")),this.$el.append(this.first).append(this.second).append(this.third)},render:function(){$(this.key).val(this.model.get("hostname")),this.regenerate_list(),$(this.value).val(this.model.get("upstream"))},deleteEntry:function(t){t.preventDefault(),this.collection.remove(this.model)},regenerate_list:function(){const t=$(this.value);t.html(""),this.upstreamCollection.each(e=>t.append(``)),t.val(this.model.get("upstream")),t.selectpicker("refresh")}}),l=Backbone.View.extend({tagName:"div",attributes:{class:"row"},events:{"keyup .key":function(){this.model.set("network",this.key.value)},"change .value":function(){this.model.set("action",this.value.value)},"click .delete":"deleteEntry"},key:null,value:null,delBtn:null,first:null,second:null,third:null,upstreamCollection:null,initialize:function(t){this.upstreamCollection=t.upstreamCollection,this.listenTo(this.upstreamCollection,"update reset add remove",this.regenerate_list),this.first=document.createElement("div"),this.first.classList.add("col-sm-5"),this.key=document.createElement("input"),this.first.append(this.key),this.key.type="text",this.key.classList.add("key"),this.key.value=this.model.get("network"),this.second=document.createElement("div"),this.second.classList.add("col-sm-5"),this.value=document.createElement("select"),this.second.append(this.value),this.value.classList.add("value"),this.value.classList.add("form-control"),this.value.value=this.model.get("action"),this.third=document.createElement("div"),this.third.classList.add("col-sm-2"),this.third.style.textAlign="right",this.delBtn=document.createElement("button"),this.delBtn.classList.add("delete"),this.delBtn.classList.add("btn"),this.delBtn.innerHTML='',this.third.append(this.delBtn),this.$el.append(this.first).append(this.second).append(this.third)},render:function(){$(this.key).val(this.model.get("network")),this.regenerate_list(),$(this.value).val(this.model.get("action"))},deleteEntry:function(t){t.preventDefault(),this.collection.remove(this.model)},regenerate_list:function(){const t=$(this.value);t.html(""),this.upstreamCollection.each(e=>t.append(``)),t.val(this.model.get("action")),t.selectpicker("refresh")}});var o=Backbone.Collection.extend({initialize:function(){let t=this;$("#snihostname\\.data").change(function(){t.regenerateFromView()})},regenerateFromView:function(){let t=$("#snihostname\\.data").data("data");_.isArray(t)||(t=[]),this.reset(t)}}),r=Backbone.Model.extend({}),d=Backbone.Model.extend({}),c=Backbone.Collection.extend({initialize:function(){let t=this;$("#ipacl\\.data").change(function(){t.regenerateFromView()})},regenerateFromView:function(){let t=$("#ipacl\\.data").data("data");_.isArray(t)||(t=[]),this.reset(t)}});const u=new s,h=new Backbone.Collection([{name:"Deny",value:"deny"},{name:"Allow",value:"allow"}]);$(document).ready(function(){mapDataToFormUI({frm_nginx:"/api/nginx/settings/get"}).done(function(){formatTokenizersUI(),$('select[data-allownew="false"]').selectpicker("refresh"),updateServiceControlUI("nginx")}),""!==window.location.hash&&$('a[href="'+window.location.hash+'"]').click(),$(".nav-tabs a").on("shown.bs.tab",function(t){history.pushState(null,null,t.target.hash)}),$(".reload_btn").click(function(){$(".reloadAct_progress").addClass("fa-spin"),ajaxCall("/api/nginx/service/reconfigure",{},function(){$(".reloadAct_progress").removeClass("fa-spin")})}),$('[id*="save_"]').each(function(){$(this).click(function(){let t=$(this).closest("form").attr("id"),e=$(this).closest("form").attr("data-title");saveFormToEndpoint("/api/nginx/settings/set",t,function(){$("#"+t+"_progress").addClass("fa fa-spinner fa-pulse"),ajaxCall("/api/nginx/service/reconfigure",{},function(n,i){$("#"+t+"_progress").removeClass("fa fa-spinner fa-pulse"),void 0===n||"success"===i&&"ok"===n.status?updateServiceControlUI("nginx"):BootstrapDialog.show({type:BootstrapDialog.TYPE_WARNING,title:e,message:JSON.stringify(n),draggable:!0})})})})}),["upstream","upstreamserver","location","credential","userlist","httpserver","streamserver","httprewrite","custompolicy","security_header","ipacl","limit_zone","cache_path","limit_request_connection","snifwd","errorpage","tls_fingerprint","resolver","syslog_target","naxsirule"].forEach(function(t){$("#grid-"+t).UIBootgrid({search:"/api/nginx/settings/search"+t,get:"/api/nginx/settings/get"+t+"/",set:"/api/nginx/settings/set"+t+"/",add:"/api/nginx/settings/add"+t+"/",del:"/api/nginx/settings/del"+t+"/",commands:{copy_uuid:{method:function(t){navigator.clipboard.writeText($(this).data("row-id"))}}},options:{selection:!1,multiSelect:!1,formatters:{commands:function(t,e){return''},response:function(t,e){return"none"==e.response?"unchanged":e.response},statuscodes:function(t,e){const n=[],i=e.statuscodes.split(",");for(let t of i)n.push(t.substr(0,3));return n.join(", ")}}}})}),bind_naxsi_rule_dl_button(),function(){let t=new i({dataField:document.getElementById("snihostname.data"),upstreamCollection:u,entryclass:a,collection:new o,createModel:function(){return new r({hostname:"localhost"})}});window.snifield=t,t.render(),$("#grid-upstream").on("loaded.rs.jquery.bootgrid",function(){u.fetch()}),u.fetch()}();let t=new i({dataField:document.getElementById("ipacl.data"),upstreamCollection:h,entryclass:l,collection:new c,createModel:function(){return new d({network:"::",action:"deny"})}});window.ipaclfield=t,t.render()})}}); \ No newline at end of file +!function(t){var e={};function n(i){if(e[i])return e[i].exports;var s=e[i]={i:i,l:!1,exports:{}};return t[i].call(s.exports,s,s.exports,n),s.l=!0,s.exports}n.m=t,n.c=e,n.d=function(t,e,i){n.o(t,e)||Object.defineProperty(t,e,{enumerable:!0,get:i})},n.r=function(t){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},n.t=function(t,e){if(1&e&&(t=n(t)),8&e)return t;if(4&e&&"object"==typeof t&&t&&t.__esModule)return t;var i=Object.create(null);if(n.r(i),Object.defineProperty(i,"default",{enumerable:!0,value:t}),2&e&&"string"!=typeof t)for(var s in t)n.d(i,s,function(e){return t[e]}.bind(null,s));return i},n.n=function(t){var e=t&&t.__esModule?function(){return t.default}:function(){return t};return n.d(e,"a",e),e},n.o=function(t,e){return Object.prototype.hasOwnProperty.call(t,e)},n.p="",n(n.s=25)}({25:function(t,e,n){"use strict";n.r(e);var i=Backbone.View.extend({tagName:"div",attributes:{class:"container-fluid"},child_views:[],createModel:null,upstreamCollection:null,initialize:function(t){this.dataField=$(t.dataField),this.entryclass=t.entryclass,this.createModel=t.createModel,this.upstreamCollection=t.upstreamCollection,this.listenTo(this.collection,"add remove reset",this.render),this.listenTo(this.collection,"change",this.update),this.dataField.after(this.$el)},events:{"click .add":"addEntry"},render:function(){this.child_views.forEach(t=>t.remove()),this.$el.html(""),this.child_views=[],this.update(),this.collection.each(t=>{const e=new this.entryclass({model:t,collection:this.collection,upstreamCollection:this.upstreamCollection});this.child_views.push(e),this.$el.append(e.$el),e.render()}),this.$el.append($('\n
    \n \n
    '))},update:function(){this.dataField.data("data",this.collection.toJSON())},addEntry:function(t){t.preventDefault(),this.collection.add(this.createModel())}});var s=Backbone.Collection.extend({url:"/api/nginx/settings/searchupstream",parse:function(t){return t.rows}});const a=Backbone.View.extend({tagName:"div",attributes:{class:"row"},events:{"keyup .key":function(){this.model.set("hostname",this.key.value)},"change .value":function(){this.model.set("upstream",this.value.value)},"click .delete":"deleteEntry"},key:null,value:null,delBtn:null,first:null,second:null,third:null,upstreamCollection:null,initialize:function(t){this.upstreamCollection=t.upstreamCollection,this.listenTo(this.upstreamCollection,"update reset add remove",this.regenerate_list),this.first=document.createElement("div"),this.first.classList.add("col-sm-5"),this.key=document.createElement("input"),this.first.append(this.key),this.key.type="text",this.key.classList.add("key"),this.key.value=this.model.get("hostname"),this.second=document.createElement("div"),this.second.classList.add("col-sm-5"),this.value=document.createElement("select"),this.second.append(this.value),this.value.classList.add("value"),this.value.classList.add("form-control"),this.value.value=this.model.get("upstream"),this.third=document.createElement("div"),this.third.classList.add("col-sm-2"),this.third.style.textAlign="right",this.delBtn=document.createElement("button"),this.delBtn.classList.add("delete"),this.delBtn.classList.add("btn"),this.delBtn.innerHTML='',this.third.append(this.delBtn),this.model.has("upstream")&&0!==this.upstreamCollection.where({uuid:this.model.get("upstream")}).length||this.upstreamCollection.length>0&&this.model.set("upstream",this.upstreamCollection.at(0).get("uuid")),this.$el.append(this.first).append(this.second).append(this.third)},render:function(){$(this.key).val(this.model.get("hostname")),this.regenerate_list(),$(this.value).val(this.model.get("upstream"))},deleteEntry:function(t){t.preventDefault(),this.collection.remove(this.model)},regenerate_list:function(){const t=$(this.value);t.html(""),this.upstreamCollection.each(e=>t.append(``)),t.val(this.model.get("upstream")),t.selectpicker("refresh")}}),l=Backbone.View.extend({tagName:"div",attributes:{class:"row"},events:{"keyup .key":function(){this.model.set("network",this.key.value)},"change .value":function(){this.model.set("action",this.value.value)},"click .delete":"deleteEntry"},key:null,value:null,delBtn:null,first:null,second:null,third:null,upstreamCollection:null,initialize:function(t){this.upstreamCollection=t.upstreamCollection,this.listenTo(this.upstreamCollection,"update reset add remove",this.regenerate_list),this.first=document.createElement("div"),this.first.classList.add("col-sm-5"),this.key=document.createElement("input"),this.first.append(this.key),this.key.type="text",this.key.classList.add("key"),this.key.value=this.model.get("network"),this.second=document.createElement("div"),this.second.classList.add("col-sm-5"),this.value=document.createElement("select"),this.second.append(this.value),this.value.classList.add("value"),this.value.classList.add("form-control"),this.value.value=this.model.get("action"),this.third=document.createElement("div"),this.third.classList.add("col-sm-2"),this.third.style.textAlign="right",this.delBtn=document.createElement("button"),this.delBtn.classList.add("delete"),this.delBtn.classList.add("btn"),this.delBtn.innerHTML='',this.third.append(this.delBtn),this.$el.append(this.first).append(this.second).append(this.third)},render:function(){$(this.key).val(this.model.get("network")),this.regenerate_list(),$(this.value).val(this.model.get("action"))},deleteEntry:function(t){t.preventDefault(),this.collection.remove(this.model)},regenerate_list:function(){const t=$(this.value);t.html(""),this.upstreamCollection.each(e=>t.append(``)),t.val(this.model.get("action")),t.selectpicker("refresh")}});var o=Backbone.Collection.extend({initialize:function(){let t=this;$("#snihostname\\.data").change(function(){t.regenerateFromView()})},regenerateFromView:function(){let t=$("#snihostname\\.data").data("data");_.isArray(t)||(t=[]),this.reset(t)}}),r=Backbone.Model.extend({}),d=Backbone.Model.extend({}),c=Backbone.Collection.extend({initialize:function(){let t=this;$("#ipacl\\.data").change(function(){t.regenerateFromView()})},regenerateFromView:function(){let t=$("#ipacl\\.data").data("data");_.isArray(t)||(t=[]),this.reset(t)}});const u=new s,h=new Backbone.Collection([{name:"Deny",value:"deny"},{name:"Allow",value:"allow"}]);$(document).ready(function(){mapDataToFormUI({frm_nginx:"/api/nginx/settings/get"}).done(function(){formatTokenizersUI(),$('select[data-allownew="false"]').selectpicker("refresh"),updateServiceControlUI("nginx")}),""!==window.location.hash&&$('a[href="'+window.location.hash+'"]').click(),$(".nav-tabs a").on("shown.bs.tab",function(t){history.pushState(null,null,t.target.hash)}),$(".reload_btn").click(function(){$(".reloadAct_progress").addClass("fa-spin"),ajaxCall("/api/nginx/service/reconfigure",{},function(){$(".reloadAct_progress").removeClass("fa-spin")})}),$('[id*="save_"]').each(function(){$(this).click(function(){let t=$(this).closest("form").attr("id"),e=$(this).closest("form").attr("data-title");saveFormToEndpoint("/api/nginx/settings/set",t,function(){$("#"+t+"_progress").addClass("fa fa-spinner fa-pulse"),ajaxCall("/api/nginx/service/reconfigure",{},function(n,i){$("#"+t+"_progress").removeClass("fa fa-spinner fa-pulse"),void 0===n||"success"===i&&"ok"===n.status?updateServiceControlUI("nginx"):BootstrapDialog.show({type:BootstrapDialog.TYPE_WARNING,title:e,message:JSON.stringify(n),draggable:!0})})})})}),["upstream","upstreamserver","location","credential","userlist","httpserver","streamserver","httprewrite","custompolicy","security_header","ipacl","limit_zone","cache_path","proxy_cache_valid","limit_request_connection","snifwd","errorpage","tls_fingerprint","resolver","syslog_target","naxsirule"].forEach(function(t){$("#grid-"+t).UIBootgrid({search:"/api/nginx/settings/search"+t,get:"/api/nginx/settings/get"+t+"/",set:"/api/nginx/settings/set"+t+"/",add:"/api/nginx/settings/add"+t+"/",del:"/api/nginx/settings/del"+t+"/",commands:{copy_uuid:{method:function(t){navigator.clipboard.writeText($(this).data("row-id"))}}},options:{selection:!1,multiSelect:!1,formatters:{commands:function(t,e){return''},response:function(t,e){return"none"==e.response?"unchanged":e.response},statuscodes:function(t,e){const n=[],i=e.statuscodes.split(",");for(let t of i)n.push(t.substr(0,3));return n.join(", ")}}}})}),bind_naxsi_rule_dl_button(),function(){let t=new i({dataField:document.getElementById("snihostname.data"),upstreamCollection:u,entryclass:a,collection:new o,createModel:function(){return new r({hostname:"localhost"})}});window.snifield=t,t.render(),$("#grid-upstream").on("loaded.rs.jquery.bootgrid",function(){u.fetch()}),u.fetch()}();let t=new i({dataField:document.getElementById("ipacl.data"),upstreamCollection:h,entryclass:l,collection:new c,createModel:function(){return new d({network:"::",action:"deny"})}});window.ipaclfield=t,t.render()})}}); diff --git a/www/nginx/src/opnsense/www/js/nginx/src/nginx_config.js b/www/nginx/src/opnsense/www/js/nginx/src/nginx_config.js index e61a2469b..4272efdaa 100644 --- a/www/nginx/src/opnsense/www/js/nginx/src/nginx_config.js +++ b/www/nginx/src/opnsense/www/js/nginx/src/nginx_config.js @@ -66,6 +66,7 @@ function init_grids() { 'ipacl', 'limit_zone', 'cache_path', + 'proxy_cache_valid', 'limit_request_connection', 'snifwd', 'errorpage',