mirror of
https://github.com/Rain-kl/OpenFlare.git
synced 2026-10-11 01:36:37 +08:00
[优化] 添加 WebSocket 升级支持,更新配置和测试用例
This commit is contained in:
@@ -71,6 +71,7 @@ var OpenRestySendTimeout = 30
|
|||||||
var OpenRestyProxyConnectTimeout = 5
|
var OpenRestyProxyConnectTimeout = 5
|
||||||
var OpenRestyProxySendTimeout = 60
|
var OpenRestyProxySendTimeout = 60
|
||||||
var OpenRestyProxyReadTimeout = 60
|
var OpenRestyProxyReadTimeout = 60
|
||||||
|
var OpenRestyWebsocketEnabled = true
|
||||||
var OpenRestyProxyRequestBufferingEnabled = false
|
var OpenRestyProxyRequestBufferingEnabled = false
|
||||||
var OpenRestyProxyBufferingEnabled = true
|
var OpenRestyProxyBufferingEnabled = true
|
||||||
var OpenRestyProxyBuffers = "16 16k"
|
var OpenRestyProxyBuffers = "16 16k"
|
||||||
|
|||||||
@@ -114,6 +114,7 @@ func validateOpenRestyOption(key string, value string) error {
|
|||||||
return fmt.Errorf("%s 仅支持 epoll、kqueue、poll、select、rtsig、/dev/poll、eventport 或留空", key)
|
return fmt.Errorf("%s 仅支持 epoll、kqueue、poll、select、rtsig、/dev/poll、eventport 或留空", key)
|
||||||
}
|
}
|
||||||
case "OpenRestyEventsMultiAcceptEnabled",
|
case "OpenRestyEventsMultiAcceptEnabled",
|
||||||
|
"OpenRestyWebsocketEnabled",
|
||||||
"OpenRestyProxyRequestBufferingEnabled",
|
"OpenRestyProxyRequestBufferingEnabled",
|
||||||
"OpenRestyProxyBufferingEnabled",
|
"OpenRestyProxyBufferingEnabled",
|
||||||
"OpenRestyGzipEnabled",
|
"OpenRestyGzipEnabled",
|
||||||
|
|||||||
@@ -24,6 +24,8 @@ func TestValidateOpenRestyOption(t *testing.T) {
|
|||||||
{name: "large client header buffers invalid", key: "OpenRestyLargeClientHeaderBuffers", value: "4x16k", wantErr: true},
|
{name: "large client header buffers invalid", key: "OpenRestyLargeClientHeaderBuffers", value: "4x16k", wantErr: true},
|
||||||
{name: "proxy request buffering valid", key: "OpenRestyProxyRequestBufferingEnabled", value: "true"},
|
{name: "proxy request buffering valid", key: "OpenRestyProxyRequestBufferingEnabled", value: "true"},
|
||||||
{name: "proxy request buffering invalid", key: "OpenRestyProxyRequestBufferingEnabled", value: "on", wantErr: true},
|
{name: "proxy request buffering invalid", key: "OpenRestyProxyRequestBufferingEnabled", value: "on", wantErr: true},
|
||||||
|
{name: "websocket valid", key: "OpenRestyWebsocketEnabled", value: "false"},
|
||||||
|
{name: "websocket invalid", key: "OpenRestyWebsocketEnabled", value: "off", wantErr: true},
|
||||||
{name: "cache inactive valid", key: "OpenRestyCacheInactive", value: "30m"},
|
{name: "cache inactive valid", key: "OpenRestyCacheInactive", value: "30m"},
|
||||||
{name: "cache inactive invalid", key: "OpenRestyCacheInactive", value: "30", wantErr: true},
|
{name: "cache inactive invalid", key: "OpenRestyCacheInactive", value: "30", wantErr: true},
|
||||||
{name: "cache use stale valid", key: "OpenRestyCacheUseStale", value: "error timeout http_500"},
|
{name: "cache use stale valid", key: "OpenRestyCacheUseStale", value: "error timeout http_500"},
|
||||||
|
|||||||
@@ -71,6 +71,7 @@ func InitOptionMap() {
|
|||||||
common.OptionMap["OpenRestyProxyConnectTimeout"] = strconv.Itoa(common.OpenRestyProxyConnectTimeout)
|
common.OptionMap["OpenRestyProxyConnectTimeout"] = strconv.Itoa(common.OpenRestyProxyConnectTimeout)
|
||||||
common.OptionMap["OpenRestyProxySendTimeout"] = strconv.Itoa(common.OpenRestyProxySendTimeout)
|
common.OptionMap["OpenRestyProxySendTimeout"] = strconv.Itoa(common.OpenRestyProxySendTimeout)
|
||||||
common.OptionMap["OpenRestyProxyReadTimeout"] = strconv.Itoa(common.OpenRestyProxyReadTimeout)
|
common.OptionMap["OpenRestyProxyReadTimeout"] = strconv.Itoa(common.OpenRestyProxyReadTimeout)
|
||||||
|
common.OptionMap["OpenRestyWebsocketEnabled"] = strconv.FormatBool(common.OpenRestyWebsocketEnabled)
|
||||||
common.OptionMap["OpenRestyProxyRequestBufferingEnabled"] = strconv.FormatBool(common.OpenRestyProxyRequestBufferingEnabled)
|
common.OptionMap["OpenRestyProxyRequestBufferingEnabled"] = strconv.FormatBool(common.OpenRestyProxyRequestBufferingEnabled)
|
||||||
common.OptionMap["OpenRestyProxyBufferingEnabled"] = strconv.FormatBool(common.OpenRestyProxyBufferingEnabled)
|
common.OptionMap["OpenRestyProxyBufferingEnabled"] = strconv.FormatBool(common.OpenRestyProxyBufferingEnabled)
|
||||||
common.OptionMap["OpenRestyProxyBuffers"] = common.OpenRestyProxyBuffers
|
common.OptionMap["OpenRestyProxyBuffers"] = common.OpenRestyProxyBuffers
|
||||||
@@ -269,6 +270,8 @@ func updateOptionMap(key string, value string) {
|
|||||||
if v, err := strconv.Atoi(value); err == nil && v > 0 {
|
if v, err := strconv.Atoi(value); err == nil && v > 0 {
|
||||||
common.OpenRestyProxyReadTimeout = v
|
common.OpenRestyProxyReadTimeout = v
|
||||||
}
|
}
|
||||||
|
case "OpenRestyWebsocketEnabled":
|
||||||
|
common.OpenRestyWebsocketEnabled = value == "true"
|
||||||
case "OpenRestyProxyRequestBufferingEnabled":
|
case "OpenRestyProxyRequestBufferingEnabled":
|
||||||
common.OpenRestyProxyRequestBufferingEnabled = value == "true"
|
common.OpenRestyProxyRequestBufferingEnabled = value == "true"
|
||||||
case "OpenRestyProxyBufferingEnabled":
|
case "OpenRestyProxyBufferingEnabled":
|
||||||
|
|||||||
@@ -78,6 +78,7 @@ type openRestyConfigSnapshot struct {
|
|||||||
ProxyConnectTimeout int `json:"proxy_connect_timeout"`
|
ProxyConnectTimeout int `json:"proxy_connect_timeout"`
|
||||||
ProxySendTimeout int `json:"proxy_send_timeout"`
|
ProxySendTimeout int `json:"proxy_send_timeout"`
|
||||||
ProxyReadTimeout int `json:"proxy_read_timeout"`
|
ProxyReadTimeout int `json:"proxy_read_timeout"`
|
||||||
|
WebsocketEnabled bool `json:"websocket_enabled"`
|
||||||
ProxyRequestBuffering bool `json:"proxy_request_buffering"`
|
ProxyRequestBuffering bool `json:"proxy_request_buffering"`
|
||||||
ProxyBufferingEnabled bool `json:"proxy_buffering_enabled"`
|
ProxyBufferingEnabled bool `json:"proxy_buffering_enabled"`
|
||||||
ProxyBuffers string `json:"proxy_buffers"`
|
ProxyBuffers string `json:"proxy_buffers"`
|
||||||
@@ -454,6 +455,7 @@ func buildOpenRestyConfigSnapshot() openRestyConfigSnapshot {
|
|||||||
ProxyConnectTimeout: common.OpenRestyProxyConnectTimeout,
|
ProxyConnectTimeout: common.OpenRestyProxyConnectTimeout,
|
||||||
ProxySendTimeout: common.OpenRestyProxySendTimeout,
|
ProxySendTimeout: common.OpenRestyProxySendTimeout,
|
||||||
ProxyReadTimeout: common.OpenRestyProxyReadTimeout,
|
ProxyReadTimeout: common.OpenRestyProxyReadTimeout,
|
||||||
|
WebsocketEnabled: common.OpenRestyWebsocketEnabled,
|
||||||
ProxyRequestBuffering: common.OpenRestyProxyRequestBufferingEnabled,
|
ProxyRequestBuffering: common.OpenRestyProxyRequestBufferingEnabled,
|
||||||
ProxyBufferingEnabled: common.OpenRestyProxyBufferingEnabled,
|
ProxyBufferingEnabled: common.OpenRestyProxyBufferingEnabled,
|
||||||
ProxyBuffers: common.OpenRestyProxyBuffers,
|
ProxyBuffers: common.OpenRestyProxyBuffers,
|
||||||
@@ -514,6 +516,7 @@ func diffOpenRestyOptionDetails(left openRestyConfigSnapshot, right openRestyCon
|
|||||||
appendIfChanged("OpenRestyProxyConnectTimeout", fmt.Sprintf("%d", left.ProxyConnectTimeout), fmt.Sprintf("%d", right.ProxyConnectTimeout))
|
appendIfChanged("OpenRestyProxyConnectTimeout", fmt.Sprintf("%d", left.ProxyConnectTimeout), fmt.Sprintf("%d", right.ProxyConnectTimeout))
|
||||||
appendIfChanged("OpenRestyProxySendTimeout", fmt.Sprintf("%d", left.ProxySendTimeout), fmt.Sprintf("%d", right.ProxySendTimeout))
|
appendIfChanged("OpenRestyProxySendTimeout", fmt.Sprintf("%d", left.ProxySendTimeout), fmt.Sprintf("%d", right.ProxySendTimeout))
|
||||||
appendIfChanged("OpenRestyProxyReadTimeout", fmt.Sprintf("%d", left.ProxyReadTimeout), fmt.Sprintf("%d", right.ProxyReadTimeout))
|
appendIfChanged("OpenRestyProxyReadTimeout", fmt.Sprintf("%d", left.ProxyReadTimeout), fmt.Sprintf("%d", right.ProxyReadTimeout))
|
||||||
|
appendIfChanged("OpenRestyWebsocketEnabled", fmt.Sprintf("%t", left.WebsocketEnabled), fmt.Sprintf("%t", right.WebsocketEnabled))
|
||||||
appendIfChanged("OpenRestyProxyRequestBufferingEnabled", fmt.Sprintf("%t", left.ProxyRequestBuffering), fmt.Sprintf("%t", right.ProxyRequestBuffering))
|
appendIfChanged("OpenRestyProxyRequestBufferingEnabled", fmt.Sprintf("%t", left.ProxyRequestBuffering), fmt.Sprintf("%t", right.ProxyRequestBuffering))
|
||||||
appendIfChanged("OpenRestyProxyBufferingEnabled", fmt.Sprintf("%t", left.ProxyBufferingEnabled), fmt.Sprintf("%t", right.ProxyBufferingEnabled))
|
appendIfChanged("OpenRestyProxyBufferingEnabled", fmt.Sprintf("%t", left.ProxyBufferingEnabled), fmt.Sprintf("%t", right.ProxyBufferingEnabled))
|
||||||
appendIfChanged("OpenRestyProxyBuffers", left.ProxyBuffers, right.ProxyBuffers)
|
appendIfChanged("OpenRestyProxyBuffers", left.ProxyBuffers, right.ProxyBuffers)
|
||||||
@@ -559,6 +562,7 @@ func openRestyOptionKeys() []string {
|
|||||||
"OpenRestyProxyConnectTimeout",
|
"OpenRestyProxyConnectTimeout",
|
||||||
"OpenRestyProxySendTimeout",
|
"OpenRestyProxySendTimeout",
|
||||||
"OpenRestyProxyReadTimeout",
|
"OpenRestyProxyReadTimeout",
|
||||||
|
"OpenRestyWebsocketEnabled",
|
||||||
"OpenRestyProxyRequestBufferingEnabled",
|
"OpenRestyProxyRequestBufferingEnabled",
|
||||||
"OpenRestyProxyBufferingEnabled",
|
"OpenRestyProxyBufferingEnabled",
|
||||||
"OpenRestyProxyBuffers",
|
"OpenRestyProxyBuffers",
|
||||||
@@ -762,6 +766,11 @@ func renderProxyHeaderBlock(customHeaders []ProxyRouteCustomHeaderInput) string
|
|||||||
builder.WriteString(" proxy_set_header X-Real-IP $remote_addr;\n")
|
builder.WriteString(" proxy_set_header X-Real-IP $remote_addr;\n")
|
||||||
builder.WriteString(" proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n")
|
builder.WriteString(" proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;\n")
|
||||||
builder.WriteString(" proxy_set_header X-Forwarded-Proto $scheme;\n")
|
builder.WriteString(" proxy_set_header X-Forwarded-Proto $scheme;\n")
|
||||||
|
if common.OpenRestyWebsocketEnabled {
|
||||||
|
builder.WriteString(" proxy_http_version 1.1;\n")
|
||||||
|
builder.WriteString(" proxy_set_header Upgrade $http_upgrade;\n")
|
||||||
|
builder.WriteString(" proxy_set_header Connection $http_connection;\n")
|
||||||
|
}
|
||||||
for _, header := range customHeaders {
|
for _, header := range customHeaders {
|
||||||
builder.WriteString(fmt.Sprintf(" proxy_set_header %s %s;\n", header.Key, quoteNginxHeaderValue(header.Value)))
|
builder.WriteString(fmt.Sprintf(" proxy_set_header %s %s;\n", header.Key, quoteNginxHeaderValue(header.Value)))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -96,6 +96,9 @@ func TestCreateProxyRouteRejectsHTTPSWithoutCertificate(t *testing.T) {
|
|||||||
|
|
||||||
func TestPublishConfigVersionRendersCustomHeaders(t *testing.T) {
|
func TestPublishConfigVersionRendersCustomHeaders(t *testing.T) {
|
||||||
setupServiceTestDB(t)
|
setupServiceTestDB(t)
|
||||||
|
if err := model.UpdateOption("OpenRestyWebsocketEnabled", "true"); err != nil {
|
||||||
|
t.Fatalf("UpdateOption OpenRestyWebsocketEnabled failed: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
_, err := CreateProxyRoute(ProxyRouteInput{
|
_, err := CreateProxyRoute(ProxyRouteInput{
|
||||||
Domain: "custom.example.com",
|
Domain: "custom.example.com",
|
||||||
@@ -123,10 +126,52 @@ func TestPublishConfigVersionRendersCustomHeaders(t *testing.T) {
|
|||||||
if !strings.Contains(result.Version.SnapshotJSON, "custom_headers") {
|
if !strings.Contains(result.Version.SnapshotJSON, "custom_headers") {
|
||||||
t.Fatal("expected snapshot to include custom headers")
|
t.Fatal("expected snapshot to include custom headers")
|
||||||
}
|
}
|
||||||
|
if !strings.Contains(result.Version.RenderedConfig, "proxy_http_version 1.1;") {
|
||||||
|
t.Fatal("expected rendered config to enable HTTP/1.1 proxying for websocket upgrades")
|
||||||
|
}
|
||||||
|
if !strings.Contains(result.Version.RenderedConfig, "proxy_set_header Upgrade $http_upgrade;") {
|
||||||
|
t.Fatal("expected rendered config to forward websocket upgrade header")
|
||||||
|
}
|
||||||
|
if !strings.Contains(result.Version.RenderedConfig, "proxy_set_header Connection $http_connection;") {
|
||||||
|
t.Fatal("expected rendered config to forward websocket connection header")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestPreviewConfigVersionCanDisableWebsocketHeaders(t *testing.T) {
|
||||||
|
setupServiceTestDB(t)
|
||||||
|
|
||||||
|
_, err := CreateProxyRoute(ProxyRouteInput{
|
||||||
|
Domain: "ws-off.example.com",
|
||||||
|
OriginURL: "https://origin.internal",
|
||||||
|
Enabled: true,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("CreateProxyRoute failed: %v", err)
|
||||||
|
}
|
||||||
|
if err := model.UpdateOption("OpenRestyWebsocketEnabled", "false"); err != nil {
|
||||||
|
t.Fatalf("UpdateOption OpenRestyWebsocketEnabled failed: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
preview, err := PreviewConfigVersion()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("PreviewConfigVersion failed: %v", err)
|
||||||
|
}
|
||||||
|
if strings.Contains(preview.RenderedConfig, "proxy_http_version 1.1;") {
|
||||||
|
t.Fatal("expected preview config to omit websocket proxy_http_version when disabled")
|
||||||
|
}
|
||||||
|
if strings.Contains(preview.RenderedConfig, "proxy_set_header Upgrade $http_upgrade;") {
|
||||||
|
t.Fatal("expected preview config to omit websocket upgrade header when disabled")
|
||||||
|
}
|
||||||
|
if strings.Contains(preview.RenderedConfig, "proxy_set_header Connection $http_connection;") {
|
||||||
|
t.Fatal("expected preview config to omit websocket connection header when disabled")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPreviewAndDiffConfigVersion(t *testing.T) {
|
func TestPreviewAndDiffConfigVersion(t *testing.T) {
|
||||||
setupServiceTestDB(t)
|
setupServiceTestDB(t)
|
||||||
|
if err := model.UpdateOption("OpenRestyWebsocketEnabled", "true"); err != nil {
|
||||||
|
t.Fatalf("UpdateOption OpenRestyWebsocketEnabled failed: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
stableRoute, err := CreateProxyRoute(ProxyRouteInput{
|
stableRoute, err := CreateProxyRoute(ProxyRouteInput{
|
||||||
Domain: "stable.example.com",
|
Domain: "stable.example.com",
|
||||||
@@ -226,6 +271,9 @@ func TestPreviewAndDiffConfigVersion(t *testing.T) {
|
|||||||
if err = model.UpdateOption("OpenRestyProxyReadTimeout", "120"); err != nil {
|
if err = model.UpdateOption("OpenRestyProxyReadTimeout", "120"); err != nil {
|
||||||
t.Fatalf("UpdateOption failed: %v", err)
|
t.Fatalf("UpdateOption failed: %v", err)
|
||||||
}
|
}
|
||||||
|
if err = model.UpdateOption("OpenRestyWebsocketEnabled", "false"); err != nil {
|
||||||
|
t.Fatalf("UpdateOption OpenRestyWebsocketEnabled failed: %v", err)
|
||||||
|
}
|
||||||
diff, err = DiffConfigVersion()
|
diff, err = DiffConfigVersion()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("DiffConfigVersion after option change failed: %v", err)
|
t.Fatalf("DiffConfigVersion after option change failed: %v", err)
|
||||||
@@ -240,6 +288,7 @@ func TestPreviewAndDiffConfigVersion(t *testing.T) {
|
|||||||
t.Fatal("expected changed OpenResty option details to be reported")
|
t.Fatal("expected changed OpenResty option details to be reported")
|
||||||
}
|
}
|
||||||
found := false
|
found := false
|
||||||
|
foundWebsocket := false
|
||||||
for _, item := range diff.ChangedOptionDetails {
|
for _, item := range diff.ChangedOptionDetails {
|
||||||
if item.Key == "OpenRestyProxyReadTimeout" {
|
if item.Key == "OpenRestyProxyReadTimeout" {
|
||||||
found = true
|
found = true
|
||||||
@@ -247,10 +296,19 @@ func TestPreviewAndDiffConfigVersion(t *testing.T) {
|
|||||||
t.Fatalf("unexpected option diff values: %+v", item)
|
t.Fatalf("unexpected option diff values: %+v", item)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if item.Key == "OpenRestyWebsocketEnabled" {
|
||||||
|
foundWebsocket = true
|
||||||
|
if item.PreviousValue != "true" || item.CurrentValue != "false" {
|
||||||
|
t.Fatalf("unexpected websocket option diff values: %+v", item)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if !found {
|
if !found {
|
||||||
t.Fatal("expected OpenRestyProxyReadTimeout diff detail")
|
t.Fatal("expected OpenRestyProxyReadTimeout diff detail")
|
||||||
}
|
}
|
||||||
|
if !foundWebsocket {
|
||||||
|
t.Fatal("expected OpenRestyWebsocketEnabled diff detail")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCreateTLSCertificateRejectsInvalidPEM(t *testing.T) {
|
func TestCreateTLSCertificateRejectsInvalidPEM(t *testing.T) {
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ const defaultPerformanceFields = {
|
|||||||
OpenRestyProxyConnectTimeout: '5',
|
OpenRestyProxyConnectTimeout: '5',
|
||||||
OpenRestyProxySendTimeout: '60',
|
OpenRestyProxySendTimeout: '60',
|
||||||
OpenRestyProxyReadTimeout: '60',
|
OpenRestyProxyReadTimeout: '60',
|
||||||
|
OpenRestyWebsocketEnabled: true,
|
||||||
OpenRestyProxyRequestBufferingEnabled: false,
|
OpenRestyProxyRequestBufferingEnabled: false,
|
||||||
OpenRestyProxyBufferingEnabled: true,
|
OpenRestyProxyBufferingEnabled: true,
|
||||||
OpenRestyProxyBuffers: '16 16k',
|
OpenRestyProxyBuffers: '16 16k',
|
||||||
@@ -89,6 +90,8 @@ const performanceFieldTooltips: Record<string, string> = {
|
|||||||
proxy_connect_timeout: '连接上游源站的超时时间,单位秒。',
|
proxy_connect_timeout: '连接上游源站的超时时间,单位秒。',
|
||||||
proxy_send_timeout: '向上游发送请求的超时时间,单位秒。',
|
proxy_send_timeout: '向上游发送请求的超时时间,单位秒。',
|
||||||
proxy_read_timeout: '等待上游返回响应的超时时间,单位秒。',
|
proxy_read_timeout: '等待上游返回响应的超时时间,单位秒。',
|
||||||
|
websocket:
|
||||||
|
'控制是否为反向代理规则自动注入 WebSocket 升级所需的 HTTP/1.1、Upgrade 和 Connection 头。',
|
||||||
proxy_request_buffering:
|
proxy_request_buffering:
|
||||||
'控制请求体是否先在 Nginx 侧缓冲后再转发给上游,上传和流式场景经常会用到。',
|
'控制请求体是否先在 Nginx 侧缓冲后再转发给上游,上传和流式场景经常会用到。',
|
||||||
proxy_buffering:
|
proxy_buffering:
|
||||||
@@ -219,6 +222,10 @@ export function PerformancePage() {
|
|||||||
optionMap.OpenRestyProxyConnectTimeout ?? '5',
|
optionMap.OpenRestyProxyConnectTimeout ?? '5',
|
||||||
OpenRestyProxySendTimeout: optionMap.OpenRestyProxySendTimeout ?? '60',
|
OpenRestyProxySendTimeout: optionMap.OpenRestyProxySendTimeout ?? '60',
|
||||||
OpenRestyProxyReadTimeout: optionMap.OpenRestyProxyReadTimeout ?? '60',
|
OpenRestyProxyReadTimeout: optionMap.OpenRestyProxyReadTimeout ?? '60',
|
||||||
|
OpenRestyWebsocketEnabled: toBoolean(
|
||||||
|
optionMap.OpenRestyWebsocketEnabled,
|
||||||
|
true,
|
||||||
|
),
|
||||||
OpenRestyProxyRequestBufferingEnabled: toBoolean(
|
OpenRestyProxyRequestBufferingEnabled: toBoolean(
|
||||||
optionMap.OpenRestyProxyRequestBufferingEnabled,
|
optionMap.OpenRestyProxyRequestBufferingEnabled,
|
||||||
false,
|
false,
|
||||||
@@ -413,6 +420,10 @@ export function PerformancePage() {
|
|||||||
'OpenRestyProxyReadTimeout',
|
'OpenRestyProxyReadTimeout',
|
||||||
performanceFields.OpenRestyProxyReadTimeout.trim(),
|
performanceFields.OpenRestyProxyReadTimeout.trim(),
|
||||||
],
|
],
|
||||||
|
[
|
||||||
|
'OpenRestyWebsocketEnabled',
|
||||||
|
String(performanceFields.OpenRestyWebsocketEnabled),
|
||||||
|
],
|
||||||
[
|
[
|
||||||
'OpenRestyProxyRequestBufferingEnabled',
|
'OpenRestyProxyRequestBufferingEnabled',
|
||||||
String(performanceFields.OpenRestyProxyRequestBufferingEnabled),
|
String(performanceFields.OpenRestyProxyRequestBufferingEnabled),
|
||||||
@@ -927,6 +938,17 @@ export function PerformancePage() {
|
|||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
</ResourceField>
|
</ResourceField>
|
||||||
|
<ToggleField
|
||||||
|
label="websocket"
|
||||||
|
tooltip={performanceFieldTooltips.websocket}
|
||||||
|
checked={performanceFields.OpenRestyWebsocketEnabled}
|
||||||
|
onChange={(checked) =>
|
||||||
|
setPerformanceFields((previous) => ({
|
||||||
|
...previous,
|
||||||
|
OpenRestyWebsocketEnabled: checked,
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
/>
|
||||||
<ToggleField
|
<ToggleField
|
||||||
label="proxy_request_buffering"
|
label="proxy_request_buffering"
|
||||||
tooltip={performanceFieldTooltips.proxy_request_buffering}
|
tooltip={performanceFieldTooltips.proxy_request_buffering}
|
||||||
|
|||||||
@@ -59,6 +59,28 @@ function getUpgradeBadge(release: LatestReleaseInfo | null | undefined) {
|
|||||||
return {label: '最新', variant: 'success' as const};
|
return {label: '最新', variant: 'success' as const};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function formatLogTimestamp(value: string) {
|
||||||
|
const date = new Date(value);
|
||||||
|
if (Number.isNaN(date.getTime())) {
|
||||||
|
return '0000-00-00 00:00:00.000';
|
||||||
|
}
|
||||||
|
|
||||||
|
const year = date.getFullYear();
|
||||||
|
const month = `${date.getMonth() + 1}`.padStart(2, '0');
|
||||||
|
const day = `${date.getDate()}`.padStart(2, '0');
|
||||||
|
const hour = `${date.getHours()}`.padStart(2, '0');
|
||||||
|
const minute = `${date.getMinutes()}`.padStart(2, '0');
|
||||||
|
const second = `${date.getSeconds()}`.padStart(2, '0');
|
||||||
|
const millisecond = `${date.getMilliseconds()}`.padStart(3, '0');
|
||||||
|
|
||||||
|
return `${year}-${month}-${day} ${hour}:${minute}:${second}.${millisecond}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function formatLogLevel(level: string) {
|
||||||
|
const normalized = (level || 'info').toUpperCase();
|
||||||
|
return normalized.padEnd(8, ' ');
|
||||||
|
}
|
||||||
|
|
||||||
export function VersionUpgradeModal({
|
export function VersionUpgradeModal({
|
||||||
isOpen,
|
isOpen,
|
||||||
onClose,
|
onClose,
|
||||||
@@ -275,20 +297,24 @@ export function VersionUpgradeModal({
|
|||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div className="max-h-72 space-y-2 overflow-y-auto rounded-2xl border border-[var(--border-default)] bg-[var(--surface-elevated)] p-4">
|
<div className="max-h-72 overflow-y-auto rounded-2xl border border-[var(--border-default)] bg-[#0f172a] px-4 py-3">
|
||||||
{upgradeLogs.map((log, index) => (
|
{upgradeLogs.map((log, index) => (
|
||||||
<div
|
<pre
|
||||||
key={`${log.created_at}-${index}`}
|
key={`${log.created_at}-${index}`}
|
||||||
className="rounded-2xl border border-[var(--border-default)] bg-[var(--surface-panel)] px-4 py-3"
|
className="overflow-x-auto border-b border-white/8 py-2 font-mono text-[12px] leading-6 text-slate-200 last:border-b-0"
|
||||||
>
|
>
|
||||||
<div className="flex flex-wrap items-center justify-between gap-2 text-xs text-[var(--foreground-secondary)]">
|
<span className="text-slate-400">
|
||||||
<span>{formatDateTime(log.created_at)}</span>
|
{formatLogTimestamp(log.created_at)}
|
||||||
<span className="uppercase">{log.level || 'info'}</span>
|
</span>
|
||||||
</div>
|
<span className="text-slate-500"> | </span>
|
||||||
<p className="mt-2 text-sm leading-6 whitespace-pre-wrap text-[var(--foreground-primary)]">
|
<span className="text-cyan-300">
|
||||||
|
{formatLogLevel(log.level)}
|
||||||
|
</span>
|
||||||
|
<span className="text-slate-500"> | </span>
|
||||||
|
<span className="whitespace-pre-wrap break-all text-slate-100">
|
||||||
{log.message}
|
{log.message}
|
||||||
</p>
|
</span>
|
||||||
</div>
|
</pre>
|
||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
+2
-1
@@ -140,9 +140,10 @@ volumes:
|
|||||||
| `OpenRestyClientHeaderTimeout` | `client_header_timeout` 秒数 | `15` |
|
| `OpenRestyClientHeaderTimeout` | `client_header_timeout` 秒数 | `15` |
|
||||||
| `OpenRestyClientBodyTimeout` | `client_body_timeout` 秒数 | `15` |
|
| `OpenRestyClientBodyTimeout` | `client_body_timeout` 秒数 | `15` |
|
||||||
| `OpenRestySendTimeout` | `send_timeout` 秒数 | `30` |
|
| `OpenRestySendTimeout` | `send_timeout` 秒数 | `30` |
|
||||||
| `OpenRestyProxyConnectTimeout` | `proxy_connect_timeout` 秒数 | `5` |
|
| `OpenRestyProxyConnectTimeout` | `proxy_connect_timeout` 秒数 | `5` |
|
||||||
| `OpenRestyProxySendTimeout` | `proxy_send_timeout` 秒数 | `60` |
|
| `OpenRestyProxySendTimeout` | `proxy_send_timeout` 秒数 | `60` |
|
||||||
| `OpenRestyProxyReadTimeout` | `proxy_read_timeout` 秒数 | `60` |
|
| `OpenRestyProxyReadTimeout` | `proxy_read_timeout` 秒数 | `60` |
|
||||||
|
| `OpenRestyWebsocketEnabled` | 是否自动注入 WebSocket 升级所需代理头 | `true` |
|
||||||
| `OpenRestyProxyRequestBufferingEnabled` | 是否启用 `proxy_request_buffering` | `false` |
|
| `OpenRestyProxyRequestBufferingEnabled` | 是否启用 `proxy_request_buffering` | `false` |
|
||||||
| `OpenRestyProxyBufferingEnabled` | 是否启用 `proxy_buffering` | `true` |
|
| `OpenRestyProxyBufferingEnabled` | 是否启用 `proxy_buffering` | `true` |
|
||||||
| `OpenRestyProxyBuffers` | `proxy_buffers` 组合值,例如 `16 16k` | `16 16k` |
|
| `OpenRestyProxyBuffers` | `proxy_buffers` 组合值,例如 `16 16k` | `16 16k` |
|
||||||
|
|||||||
Reference in New Issue
Block a user