mirror of
https://github.com/tobychui/zoraxy.git
synced 2025-06-01 13:17:21 +02:00
Exposed dpcore timeout options
- Exposed idle timeout and response timeout option - Updated upstream edit UI to use the new API - Updated geodb
This commit is contained in:
parent
36c1f149e6
commit
caf4ab331b
@ -83,9 +83,12 @@ type requestCanceler interface {
|
||||
}
|
||||
|
||||
type DpcoreOptions struct {
|
||||
IgnoreTLSVerification bool //Disable all TLS verification when request pass through this proxy router
|
||||
FlushInterval time.Duration //Duration to flush in normal requests. Stream request or keep-alive request will always flush with interval of -1 (immediately)
|
||||
UseH2CRoundTripper bool //Use H2C RoundTripper for HTTP/2.0 connection
|
||||
IgnoreTLSVerification bool //Disable all TLS verification when request pass through this proxy router
|
||||
FlushInterval time.Duration //Duration to flush in normal requests. Stream request or keep-alive request will always flush with interval of -1 (immediately)
|
||||
MaxConcurrentConnection int //Maxmium concurrent requests to this server
|
||||
ResponseHeaderTimeout int64 //Timeout for response header, set to 0 for default
|
||||
IdleConnectionTimeout int64 //Idle connection timeout, set to 0 for default
|
||||
UseH2CRoundTripper bool //Use H2C RoundTripper for HTTP/2.0 connection
|
||||
}
|
||||
|
||||
func NewDynamicProxyCore(target *url.URL, prepender string, dpcOptions *DpcoreOptions) *ReverseProxy {
|
||||
@ -106,18 +109,30 @@ func NewDynamicProxyCore(target *url.URL, prepender string, dpcOptions *DpcoreOp
|
||||
|
||||
//Hack the default transporter to handle more connections
|
||||
optimalConcurrentConnection := 32
|
||||
if dpcOptions.MaxConcurrentConnection > 0 {
|
||||
optimalConcurrentConnection = dpcOptions.MaxConcurrentConnection
|
||||
}
|
||||
thisTransporter.(*http.Transport).IdleConnTimeout = 30 * time.Second
|
||||
thisTransporter.(*http.Transport).MaxIdleConns = optimalConcurrentConnection * 2
|
||||
thisTransporter.(*http.Transport).MaxIdleConnsPerHost = optimalConcurrentConnection
|
||||
thisTransporter.(*http.Transport).IdleConnTimeout = 30 * time.Second
|
||||
thisTransporter.(*http.Transport).MaxConnsPerHost = optimalConcurrentConnection * 2
|
||||
thisTransporter.(*http.Transport).DisableCompression = true
|
||||
|
||||
if dpcOptions.ResponseHeaderTimeout > 0 {
|
||||
//Set response header timeout
|
||||
thisTransporter.(*http.Transport).ResponseHeaderTimeout = time.Duration(dpcOptions.ResponseHeaderTimeout) * time.Millisecond
|
||||
}
|
||||
|
||||
if dpcOptions.IdleConnectionTimeout > 0 {
|
||||
//Set idle connection timeout
|
||||
thisTransporter.(*http.Transport).IdleConnTimeout = time.Duration(dpcOptions.IdleConnectionTimeout) * time.Millisecond
|
||||
}
|
||||
|
||||
if dpcOptions.IgnoreTLSVerification {
|
||||
//Ignore TLS certificate validation error
|
||||
thisTransporter.(*http.Transport).TLSClientConfig.InsecureSkipVerify = true
|
||||
}
|
||||
|
||||
//TODO: Add user adjustable timeout option here
|
||||
if dpcOptions.UseH2CRoundTripper {
|
||||
//Use H2C RoundTripper for HTTP/2.0 connection
|
||||
thisTransporter = modh2c.NewH2CRoundTripper()
|
||||
|
@ -43,8 +43,12 @@ type Upstream struct {
|
||||
SkipWebSocketOriginCheck bool //Skip origin check on websocket upgrade connections
|
||||
|
||||
//Load balancing configs
|
||||
Weight int //Random weight for round robin, 0 for fallback only
|
||||
MaxConn int //TODO: Maxmium connection to this server, 0 for unlimited
|
||||
Weight int //Random weight for round robin, 0 for fallback only
|
||||
|
||||
//HTTP Transport Config
|
||||
MaxConn int //Maxmium concurrent requests to this upstream dpcore instance
|
||||
RespTimeout int64 //Response header timeout in milliseconds
|
||||
IdleTimeout int64 //Idle connection timeout in milliseconds
|
||||
|
||||
//currentConnectionCounts atomic.Uint64 //Counter for number of client currently connected
|
||||
proxy *dpcore.ReverseProxy
|
||||
|
@ -39,8 +39,11 @@ func (u *Upstream) StartProxy() error {
|
||||
}
|
||||
|
||||
proxy := dpcore.NewDynamicProxyCore(path, "", &dpcore.DpcoreOptions{
|
||||
IgnoreTLSVerification: u.SkipCertValidations,
|
||||
FlushInterval: 100 * time.Millisecond,
|
||||
IgnoreTLSVerification: u.SkipCertValidations,
|
||||
FlushInterval: 100 * time.Millisecond,
|
||||
ResponseHeaderTimeout: u.RespTimeout,
|
||||
IdleConnectionTimeout: u.IdleTimeout,
|
||||
MaxConcurrentConnection: u.MaxConn,
|
||||
})
|
||||
|
||||
u.proxy = proxy
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -79,6 +79,25 @@ func ReverseProxyUpstreamAdd(w http.ResponseWriter, r *http.Request) {
|
||||
utils.SendErrorResponse(w, "upstream origin not set")
|
||||
return
|
||||
}
|
||||
|
||||
//Response timeout in seconds, set to 0 for default
|
||||
respTimeout, err := utils.PostInt(r, "respt")
|
||||
if err != nil {
|
||||
respTimeout = 0
|
||||
}
|
||||
|
||||
//Idle timeout in seconds, set to 0 for default
|
||||
idleTimeout, err := utils.PostInt(r, "idlet")
|
||||
if err != nil {
|
||||
idleTimeout = 0
|
||||
}
|
||||
|
||||
//Max concurrent connection to dpcore instance, set to 0 for default
|
||||
maxConn, err := utils.PostInt(r, "maxconn")
|
||||
if err != nil {
|
||||
maxConn = 0
|
||||
}
|
||||
|
||||
requireTLS, _ := utils.PostBool(r, "tls")
|
||||
skipTlsValidation, _ := utils.PostBool(r, "tlsval")
|
||||
bpwsorg, _ := utils.PostBool(r, "bpwsorg")
|
||||
@ -91,7 +110,9 @@ func ReverseProxyUpstreamAdd(w http.ResponseWriter, r *http.Request) {
|
||||
SkipCertValidations: skipTlsValidation,
|
||||
SkipWebSocketOriginCheck: bpwsorg,
|
||||
Weight: 1,
|
||||
MaxConn: 0,
|
||||
MaxConn: maxConn,
|
||||
RespTimeout: int64(respTimeout),
|
||||
IdleTimeout: int64(idleTimeout),
|
||||
}
|
||||
|
||||
//Add the new upstream to endpoint
|
||||
|
@ -57,6 +57,17 @@
|
||||
margin-bottom: 0.4em;
|
||||
}
|
||||
}
|
||||
|
||||
.advanceUpstreamOptions{
|
||||
padding: 0.6em;
|
||||
background-color: var(--theme_advance);
|
||||
width: 100%;
|
||||
border-radius: 0.4em;
|
||||
}
|
||||
|
||||
.advanceUpstreamOptions.ui.accordion .content{
|
||||
padding: 1em !important;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
@ -121,6 +132,38 @@
|
||||
<label>Skip WebSocket Origin Check<br>
|
||||
<small>Check this to allow cross-origin websocket requests</small></label>
|
||||
</div>
|
||||
<div class="ui advanceUpstreamOptions accordion" style="margin-top:0.6em;">
|
||||
<div class="title">
|
||||
<i class="dropdown icon"></i>
|
||||
Advanced Options
|
||||
</div>
|
||||
<div class="content">
|
||||
<p>Max Concurrent Connections</p>
|
||||
<div class="ui mini fluid input" style="margin-top: -0.6em;">
|
||||
<input type="number" min="0" id="maxConn" value="0">
|
||||
</div>
|
||||
<small>Set to 0 for default value (32 connections)</small>
|
||||
<br><br>
|
||||
<p>Response Timeout</p>
|
||||
<div class="ui mini right labeled fluid input" style="margin-top: -0.6em;">
|
||||
<input type="number" min="0" id="respTimeout" value="0">
|
||||
<div class="ui basic label">
|
||||
Seconds
|
||||
</div>
|
||||
</div>
|
||||
<small>Maximum waiting time for server header response, set to 0 for default</small>
|
||||
<br><br>
|
||||
<p>Idle Timeout</p>
|
||||
<div class="ui mini right labeled fluid input" style="margin-top: -0.6em;">
|
||||
<input type="number" min="0" id="idleTimeout" value="0">
|
||||
<div class="ui basic label">
|
||||
Seconds
|
||||
</div>
|
||||
</div>
|
||||
<small>Maximum allowed keep-alive time forcefully closes the connection, set to 0 for default</small>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<br><br>
|
||||
<button class="ui basic button" onclick="addNewUpstream();"><i class="ui green circle add icon"></i> Create</button>
|
||||
</div>
|
||||
@ -172,6 +215,8 @@
|
||||
renderUpstreamEntryToTable(upstream, false);
|
||||
});
|
||||
|
||||
$(".advanceUpstreamOptions.accordion").accordion();
|
||||
|
||||
let totalUpstreams = data.ActiveOrigins.length + data.InactiveOrigins.length;
|
||||
if (totalUpstreams == 1){
|
||||
$(".lowPriorityButton").addClass('disabled');
|
||||
@ -227,6 +272,8 @@
|
||||
let url = `${upstream.RequireTLS?"https://":"http://"}${upstream.OriginIpOrDomain}`
|
||||
let payload = encodeURIComponent(JSON.stringify(upstream));
|
||||
let domUID = newUID();
|
||||
|
||||
//Timeout values are stored as ms in the backend
|
||||
$("#upstreamTable").append(`<div class="ui upstreamEntry ${isActive?"":"inactive"} basic segment" data-domid="${domUID}" data-payload="${payload}" data-priority="${upstream.Priority}">
|
||||
<h4 class="ui header">
|
||||
<div class="ui toggle checkbox" style="display:inline-block;">
|
||||
@ -262,6 +309,39 @@
|
||||
<label>Skip WebSocket Origin Check<br>
|
||||
<small>Check this to allow cross-origin websocket requests</small></label>
|
||||
</div><br>
|
||||
<!-- Advance Settings -->
|
||||
<div class="ui advanceUpstreamOptions accordion" style="margin-top:0.6em;">
|
||||
<div class="title">
|
||||
<i class="dropdown icon"></i>
|
||||
Advanced Options
|
||||
</div>
|
||||
<div class="content">
|
||||
<p>Max Concurrent Connections</p>
|
||||
<div class="ui mini fluid input" style="margin-top: -0.6em;">
|
||||
<input type="number" min="0" class="maxConn" value="${upstream.MaxConn}">
|
||||
</div>
|
||||
<small>Set to 0 for default value (32 connections)</small>
|
||||
<br>
|
||||
<p style="margin-top: 0.6em;">Response Timeout</p>
|
||||
<div class="ui mini right labeled fluid input" style="margin-top: -0.6em;">
|
||||
<input type="number" min="0" class="respTimeout" value="${upstream.RespTimeout/1000}">
|
||||
<div class="ui basic label">
|
||||
Seconds
|
||||
</div>
|
||||
</div>
|
||||
<small>Maximum waiting time before Zoraxy receive server header response, set to 0 for default</small>
|
||||
<br>
|
||||
<p style="margin-top: 0.6em;">Idle Timeout</p>
|
||||
<div class="ui mini right labeled fluid input" style="margin-top: -0.6em;">
|
||||
<input type="number" min="0" class="idleTimeout" value="${upstream.IdleTimeout/1000}">
|
||||
<div class="ui basic label">
|
||||
Seconds
|
||||
</div>
|
||||
</div>
|
||||
<small>Maximum allowed keep-alive time before Zoraxy forcefully close the connection, set to 0 for default</small>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="upstreamActions">
|
||||
<!-- Change Priority -->
|
||||
@ -316,12 +396,32 @@
|
||||
let skipVerification = $("#skipTlsVerification")[0].checked;
|
||||
let skipWebSocketOriginCheck = $("#SkipWebSocketOriginCheck")[0].checked;
|
||||
let activateLoadbalancer = $("#activateNewUpstreamCheckbox")[0].checked;
|
||||
let maxConn = $("#maxConn").val();
|
||||
let respTimeout = $("#respTimeout").val();
|
||||
let idleTimeout = $("#idleTimeout").val();
|
||||
|
||||
if (maxConn == "" || isNaN(maxConn)){
|
||||
maxConn = 0;
|
||||
}
|
||||
|
||||
if (respTimeout == "" || isNaN(respTimeout)){
|
||||
respTimeout = 0;
|
||||
}
|
||||
|
||||
if (idleTimeout == "" || isNaN(idleTimeout)){
|
||||
idleTimeout = 0;
|
||||
}
|
||||
|
||||
|
||||
if (origin == ""){
|
||||
parent.msgbox("Upstream origin cannot be empty", false);
|
||||
return;
|
||||
}
|
||||
|
||||
//Convert seconds to ms
|
||||
respTimeout = parseInt(respTimeout) * 1000;
|
||||
idleTimeout = parseInt(idleTimeout) * 1000;
|
||||
|
||||
$.cjax({
|
||||
url: "/api/proxy/upstream/add",
|
||||
method: "POST",
|
||||
@ -332,6 +432,9 @@
|
||||
"tlsval": skipVerification,
|
||||
"bpwsorg":skipWebSocketOriginCheck,
|
||||
"active": activateLoadbalancer,
|
||||
"maxconn": maxConn,
|
||||
"respt": respTimeout,
|
||||
"idlet": idleTimeout,
|
||||
},
|
||||
success: function(data){
|
||||
if (data.error != undefined){
|
||||
@ -340,6 +443,9 @@
|
||||
parent.msgbox("New upstream origin added");
|
||||
initOriginList();
|
||||
$("#originURL").val("");
|
||||
$("#maxConn").val("0");
|
||||
$("#respTimeout").val("0");
|
||||
$("#idleTimeout").val("0");
|
||||
}
|
||||
}
|
||||
})
|
||||
@ -356,11 +462,34 @@
|
||||
let skipTLSVerification = $(upstream).find(".skipVerificationCheckbox")[0].checked;
|
||||
let skipWebSocketOriginCheck = $(upstream).find(".SkipWebSocketOriginCheck")[0].checked;
|
||||
|
||||
//Advance options
|
||||
let maxConn = $(upstream).find(".maxConn").val();
|
||||
let respTimeout = $(upstream).find(".respTimeout").val();
|
||||
let idleTimeout = $(upstream).find(".idleTimeout").val();
|
||||
|
||||
if (maxConn == "" || isNaN(maxConn)){
|
||||
maxConn = 0;
|
||||
}
|
||||
|
||||
if (respTimeout == "" || isNaN(respTimeout)){
|
||||
respTimeout = 0;
|
||||
}
|
||||
|
||||
if (idleTimeout == "" || isNaN(idleTimeout)){
|
||||
idleTimeout = 0;
|
||||
}
|
||||
|
||||
respTimeout = parseInt(respTimeout) * 1000;
|
||||
idleTimeout = parseInt(idleTimeout) * 1000;
|
||||
|
||||
//Update the original setting with new one just applied
|
||||
originalSettings.OriginIpOrDomain = $(upstream).find(".newOrigin").val();
|
||||
originalSettings.RequireTLS = requireTLS;
|
||||
originalSettings.SkipCertValidations = skipTLSVerification;
|
||||
originalSettings.SkipWebSocketOriginCheck = skipWebSocketOriginCheck;
|
||||
originalSettings.MaxConn = parseInt(maxConn);
|
||||
originalSettings.RespTimeout = respTimeout;
|
||||
originalSettings.IdleTimeout = idleTimeout;
|
||||
|
||||
//console.log(originalSettings);
|
||||
return originalSettings;
|
||||
|
Loading…
x
Reference in New Issue
Block a user