Added Disable Chunk Transfer Encoding option

- Added disable chunk transfer encoding on UI #685
- Added optional to disable static web server listen to all interface #688
This commit is contained in:
Toby Chui 2025-06-15 13:46:35 +08:00
parent 31ba4f20ae
commit 4a37a989a0
10 changed files with 140 additions and 63 deletions

View File

@ -193,6 +193,7 @@ func RegisterStaticWebServerAPIs(authRouter *auth.RouterDef) {
authRouter.HandleFunc("/api/webserv/stop", staticWebServer.HandleStopServer)
authRouter.HandleFunc("/api/webserv/setPort", HandleStaticWebServerPortChange)
authRouter.HandleFunc("/api/webserv/setDirList", staticWebServer.SetEnableDirectoryListing)
authRouter.HandleFunc("/api/webserv/disableListenAllInterface", staticWebServer.SetDisableListenToAllInterface)
/* File Manager */
if *allowWebFileManager {
authRouter.HandleFunc("/api/fs/list", staticWebServer.FileManager.HandleList)

View File

@ -72,6 +72,7 @@ type ResponseRewriteRuleSet struct {
/* Advance Usecase Options */
HostHeaderOverwrite string //Force overwrite of request "Host" header (advanced usecase)
NoRemoveHopByHop bool //Do not remove hop-by-hop headers (advanced usecase)
DisableChunkedTransferEncoding bool //Disable chunked transfer encoding
/* System Information Payload */
Version string //Version number of Zoraxy, use for X-Proxy-By
@ -287,7 +288,7 @@ func (p *ReverseProxy) ProxyHTTP(rw http.ResponseWriter, req *http.Request, rrr
rewriteUserAgent(outreq.Header, "Zoraxy/"+rrr.Version)
//Fix proxmox transfer encoding bug if detected Proxmox Cookie
if domainsniff.IsProxmox(req) {
if rrr.DisableChunkedTransferEncoding || domainsniff.IsProxmox(req) {
outreq.TransferEncoding = []string{"identity"}
}

View File

@ -11,7 +11,6 @@ import (
"sort"
"strings"
"imuslab.com/zoraxy/mod/dynamicproxy/domainsniff"
"imuslab.com/zoraxy/mod/dynamicproxy/dpcore"
"imuslab.com/zoraxy/mod/dynamicproxy/rewrite"
"imuslab.com/zoraxy/mod/netutils"
@ -193,6 +192,7 @@ func (h *ProxyHandler) hostRequest(w http.ResponseWriter, r *http.Request, targe
PathPrefix: "",
UpstreamHeaders: upstreamHeaders,
DownstreamHeaders: downstreamHeaders,
DisableChunkedTransferEncoding: target.DisableChunkedTransferEncoding,
HostHeaderOverwrite: headerRewriteOptions.RequestHostOverwrite,
NoRemoveHopByHop: headerRewriteOptions.DisableHopByHopHeaderRemoval,
Version: target.parent.Option.HostVersion,
@ -244,8 +244,8 @@ func (h *ProxyHandler) vdirRequest(w http.ResponseWriter, r *http.Request, targe
h.Parent.logRequest(r, true, 101, "vdir-websocket", r.Host, target.Domain)
wspHandler := websocketproxy.NewProxy(u, websocketproxy.Options{
SkipTLSValidation: target.SkipCertValidations,
SkipOriginCheck: target.parent.EnableWebsocketCustomHeaders, //You should not use websocket via virtual directory. But keep this to true for compatibility
CopyAllHeaders: domainsniff.RequireWebsocketHeaderCopy(r), //Left this as default to prevent nginx user setting / as vdir
SkipOriginCheck: true, //You should not use websocket via virtual directory. But keep this to true for compatibility
CopyAllHeaders: target.parent.EnableWebsocketCustomHeaders, //Left this as default to prevent nginx user setting / as vdir
UserDefinedHeaders: target.parent.HeaderRewriteRules.UserDefinedHeaders,
Logger: h.Parent.Option.Logger,
})
@ -286,6 +286,7 @@ func (h *ProxyHandler) vdirRequest(w http.ResponseWriter, r *http.Request, targe
PathPrefix: target.MatchingPath,
UpstreamHeaders: upstreamHeaders,
DownstreamHeaders: downstreamHeaders,
DisableChunkedTransferEncoding: target.parent.DisableChunkedTransferEncoding,
HostHeaderOverwrite: headerRewriteOptions.RequestHostOverwrite,
Version: target.parent.parent.Option.HostVersion,
})

View File

@ -194,6 +194,9 @@ type ProxyEndpoint struct {
//Uptime Monitor
DisableUptimeMonitor bool //Disable uptime monitor for this endpoint
// Chunked Transfer Encoding
DisableChunkedTransferEncoding bool //Disable chunked transfer encoding for this endpoint
//Access Control
AccessFilterUUID string //Access filter ID

View File

@ -22,6 +22,7 @@ type StaticWebServerStatus struct {
WebRoot string
Running bool
EnableWebDirManager bool
DisableListenToAllInterface bool
}
// Handle getting current static web server status
@ -33,6 +34,7 @@ func (ws *WebServer) HandleGetStatus(w http.ResponseWriter, r *http.Request) {
WebRoot: ws.option.WebRoot,
Running: ws.isRunning,
EnableWebDirManager: ws.option.EnableWebDirManager,
DisableListenToAllInterface: ws.option.DisableListenToAllInterface,
}
js, _ := json.Marshal(currentStatus)
@ -91,3 +93,19 @@ func (ws *WebServer) SetEnableDirectoryListing(w http.ResponseWriter, r *http.Re
ws.option.EnableDirectoryListing = enableList
utils.SendOK(w)
}
// Get or set disable listen to all interface settings
func (ws *WebServer) SetDisableListenToAllInterface(w http.ResponseWriter, r *http.Request) {
disableListen, err := utils.PostBool(r, "disable")
if err != nil {
utils.SendErrorResponse(w, "invalid setting given")
return
}
err = ws.option.Sysdb.Write("webserv", "disableListenToAllInterface", disableListen)
if err != nil {
utils.SendErrorResponse(w, "unable to save setting")
return
}
ws.option.DisableListenToAllInterface = disableListen
utils.SendOK(w)
}

View File

@ -25,11 +25,19 @@ import (
//go:embed templates/*
var templates embed.FS
/*
WebServerOptions define the default option for the webserv
might get override by user settings loaded from db
Any changes in here might need to also update the StaticWebServerStatus struct
in handler.go. See handler.go for more information.
*/
type WebServerOptions struct {
Port string //Port for listening
EnableDirectoryListing bool //Enable listing of directory
WebRoot string //Folder for stroing the static web folders
EnableWebDirManager bool //Enable web file manager to handle files in web directory
DisableListenToAllInterface bool // Disable listening to all interfaces, only listen to localhost
Logger *logger.Logger //System logger
Sysdb *database.Database //Database for storing configs
}
@ -92,6 +100,11 @@ func (ws *WebServer) RestorePreviousState() {
ws.option.Sysdb.Read("webserv", "dirlist", &enableDirList)
ws.option.EnableDirectoryListing = enableDirList
//Set disable listen to all interface
disableListenToAll := ws.option.DisableListenToAllInterface
ws.option.Sysdb.Read("webserv", "disableListenToAllInterface", &disableListenToAll)
ws.option.DisableListenToAllInterface = disableListenToAll
//Check the running state
webservRunning := true
ws.option.Sysdb.Read("webserv", "enabled", &webservRunning)
@ -156,8 +169,12 @@ func (ws *WebServer) Start() error {
fs := http.FileServer(http.Dir(filepath.Join(ws.option.WebRoot, "html")))
ws.mux.Handle("/", ws.fsMiddleware(fs))
listenAddr := ":" + ws.option.Port
if ws.option.DisableListenToAllInterface {
listenAddr = "127.0.0.1:" + ws.option.Port
}
ws.server = &http.Server{
Addr: ":" + ws.option.Port,
Addr: listenAddr,
Handler: ws.mux,
}

View File

@ -556,6 +556,9 @@ func ReverseProxyHandleEditEndpoint(w http.ResponseWriter, r *http.Request) {
proxyRateLimit = 1000
}
// Disable chunked Encoding
disableChunkedEncoding, _ := utils.PostBool(r, "dChunkedEnc")
//Load the previous basic auth credentials from current proxy rules
targetProxyEntry, err := dynamicProxyRouter.LoadProxy(rootNameOrMatchingDomain)
if err != nil {
@ -596,6 +599,7 @@ func ReverseProxyHandleEditEndpoint(w http.ResponseWriter, r *http.Request) {
newProxyEndpoint.RateLimit = proxyRateLimit
newProxyEndpoint.UseStickySession = useStickySession
newProxyEndpoint.DisableUptimeMonitor = disbleUtm
newProxyEndpoint.DisableChunkedTransferEncoding = disableChunkedEncoding
newProxyEndpoint.Tags = tags
//Prepare to replace the current routing rule

View File

@ -223,10 +223,10 @@
<div id="httprpEditModalSideMenu" class="four wide column">
<div class="ui secondary fluid vertical menu">
<a class="active item hrpedit_menu_item" cfgpage="downstream">
<i class="angle double white right icon"></i> <span class="editorSideMenuText">Downstream</span>
<i class="home icon"></i> <span class="editorSideMenuText">Host</span>
</a>
<a class="item hrpedit_menu_item" cfgpage="upstream">
<i class="angle double left icon"></i> <span class="editorSideMenuText">Upstream</span>
<i class="server icon"></i> <span class="editorSideMenuText">Destinations</span>
</a>
<a class="item hrpedit_menu_item" cfgpage="vdirs">
<i class="angle folder icon"></i> <span class="editorSideMenuText">Virtual Directory</span>
@ -256,7 +256,7 @@
</div>
<div id="httprpEditModalContentWindow" class="twelve wide column">
<div style="height:100%;">
<!-- Downstream -->
<!-- Host -->
<div class="rpconfig_content" rpcfg="downstream">
<div class="ui segment">
<h3>
@ -288,10 +288,11 @@
</div>
</div>
<!-- Upstream -->
<!-- Destinations -->
<div class="rpconfig_content" rpcfg="upstream">
<div class="ui segment">
<div class="upstream_list">
<b>Enabled Upstreams</b>
<div class="upstream_list" style="margin-top: 0.4em;">
</div>
<button class="ui basic compact button editUpstreamButton" style="margin-left: 0.4em; margin-top: 1em;"><i class="grey server icon"></i> Edit Upstreams</button>
@ -308,17 +309,18 @@
<small>Enable stick session on load balancing</small></label>
</div>
<br>
<div class="ui disabled checkbox" style="margin-top: 0.4em;">
<div class="ui checkbox" style="margin-top: 0.4em;">
<input type="checkbox" class="DisableChunkedTransferEncoding">
<label>Disable Chunked Transfer Encoding<br>
<small>Enable this option if your upstream uses a legacy HTTP server implementation</small></label>
<small>Enable this option if your upstream uses a legacy HTTP server implementation (e.g. Proxmox / opencloud)</small></label>
</div>
</div>
</div>
<!-- Virtual Directories-->
<div class="rpconfig_content" rpcfg="vdirs">
<div class="ui segment">
<div class="vdir_list">
<b>List of Virtual Directories</b>
<div class="vdir_list" style="margin-top:0.4em;">
</div>
<div class="ui divider"></div>
@ -719,6 +721,7 @@
let requireRateLimit = $(editor).find(".RequireRateLimit")[0].checked;
let rateLimit = $(editor).find(".RateLimit").val();
let bypassGlobalTLS = $(editor).find(".BypassGlobalTLS")[0].checked;
let disableChunkedTransferEncoding = $(editor).find(".DisableChunkedTransferEncoding")[0].checked;
let tags = getTagsArrayFromEndpoint(uuid);
if (tags.length > 0){
tags = tags.join(",");
@ -726,7 +729,7 @@
tags = "";
}
console.log({
cfgPayload = {
"type": epttype,
"rootname": uuid,
"ss":useStickySession,
@ -734,24 +737,16 @@
"bpgtls": bypassGlobalTLS,
"authprovider" :authProviderType,
"rate" :requireRateLimit,
"dChunkedEnc": disableChunkedTransferEncoding,
"ratenum" :rateLimit,
"tags": tags,
});
};
console.log("updating proxy config:", cfgPayload);
$.cjax({
url: "/api/proxy/edit",
method: "POST",
data: {
"type": epttype,
"rootname": uuid,
"ss":useStickySession,
"dutm": DisableUptimeMonitor,
"bpgtls": bypassGlobalTLS,
"authprovider" :authProviderType,
"rate" :requireRateLimit,
"ratenum" :rateLimit,
"tags": tags,
},
data: cfgPayload,
success: function(data){
if (data.error !== undefined){
msgbox(data.error, false, 6000);
@ -1143,6 +1138,12 @@
saveProxyInlineEdit(uuid);
});
editor.find(".DisableChunkedTransferEncoding").off("change");
editor.find(".DisableChunkedTransferEncoding").prop("checked", subd.DisableChunkedTransferEncoding);
editor.find(".DisableChunkedTransferEncoding").on("change", function() {
saveProxyInlineEdit(uuid);
});
/* ------------ Vdirs ------------ */
editor.find(".vdir_list").html(renderVirtualDirectoryList(subd));
editor.find(".editVdirBtn").off("click").on("click", function(){

View File

@ -29,6 +29,13 @@
<small>If this folder do not contains any index files, list the directory of this folder.</small>
</div>
</div>
<div class="inline field">
<div class="ui toggle checkbox">
<input id="webserv_enableAllInterfaces" type="checkbox" class="hidden">
<label>Listening to All Interfaces</label>
<small>When disabled, the web server will only listen to localhost (127.0.0.1) and only reachable via reverse proxy rules.</small>
</div>
</div>
<div class="field">
<label>Document Root Folder</label>
<input id="webserv_docRoot" type="text" readonly="true">
@ -136,6 +143,13 @@
$("#webserv_dirManager").remove();
}
if (!data.DisableListenToAllInterface){
//Options on UI is flipped
$("#webserv_enableAllInterfaces").parent().checkbox("set checked");
}else{
$("#webserv_enableAllInterfaces").parent().checkbox("set unchecked");
}
$("#webserv_listenPort").val(data.ListeningPort);
updateWebServLinkExample(data.ListeningPort);
@ -178,6 +192,23 @@
}
})
});
$("#webserv_enableAllInterfaces").off("change").on("change", function(){
let disable = !$(this)[0].checked;
$.cjax({
url: "/api/webserv/disableListenAllInterface",
method: "POST",
data: {"disable": disable},
success: function(data){
if (data.error != undefined){
msgbox(data.error, false);
}else{
msgbox("Listening interface setting updated");
}
}
})
});
$("#webserv_listenPort").off("change").on("change", function(){
let newPort = $(this).val();

View File

@ -22,7 +22,7 @@
<br>
<div class="ui container">
<p>Tags currently applied to this host name / proxy rule</p>
<div style="max-height: 300px; overflow-y: scroll;">
<div>
<table class="ui compact basic unstackable celled table">
<thead>
<tr>