Добавлление gzip
Теперь ответы сжимаются , что увеличивает скорость работы.
This commit is contained in:
109
Backend/WebServer/compression.go
Normal file
109
Backend/WebServer/compression.go
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
package webserver
|
||||||
|
|
||||||
|
import (
|
||||||
|
"compress/gzip"
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
"sync"
|
||||||
|
)
|
||||||
|
|
||||||
|
var compressibleTypes = map[string]bool{
|
||||||
|
"text/html": true,
|
||||||
|
"text/css": true,
|
||||||
|
"text/javascript": true,
|
||||||
|
"text/plain": true,
|
||||||
|
"text/xml": true,
|
||||||
|
"text/csv": true,
|
||||||
|
"application/javascript": true,
|
||||||
|
"application/json": true,
|
||||||
|
"application/xml": true,
|
||||||
|
"application/wasm": true,
|
||||||
|
"application/xhtml+xml": true,
|
||||||
|
"application/rss+xml": true,
|
||||||
|
"application/atom+xml": true,
|
||||||
|
"application/manifest+json": true,
|
||||||
|
"image/svg+xml": true,
|
||||||
|
}
|
||||||
|
|
||||||
|
var gzipWriterPool = sync.Pool{
|
||||||
|
New: func() interface{} {
|
||||||
|
w, _ := gzip.NewWriterLevel(io.Discard, gzip.DefaultCompression)
|
||||||
|
return w
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
type gzipResponseWriter struct {
|
||||||
|
http.ResponseWriter
|
||||||
|
gzWriter *gzip.Writer
|
||||||
|
headerWritten bool
|
||||||
|
compressed bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *gzipResponseWriter) Write(data []byte) (int, error) {
|
||||||
|
if !g.headerWritten {
|
||||||
|
g.detectAndSetHeaders()
|
||||||
|
}
|
||||||
|
if g.compressed {
|
||||||
|
return g.gzWriter.Write(data)
|
||||||
|
}
|
||||||
|
return g.ResponseWriter.Write(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *gzipResponseWriter) WriteHeader(statusCode int) {
|
||||||
|
if !g.headerWritten {
|
||||||
|
g.detectAndSetHeaders()
|
||||||
|
}
|
||||||
|
g.ResponseWriter.WriteHeader(statusCode)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *gzipResponseWriter) detectAndSetHeaders() {
|
||||||
|
g.headerWritten = true
|
||||||
|
contentType := g.ResponseWriter.Header().Get("Content-Type")
|
||||||
|
if contentType == "" {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
mimeType := strings.SplitN(contentType, ";", 2)[0]
|
||||||
|
mimeType = strings.TrimSpace(mimeType)
|
||||||
|
|
||||||
|
if compressibleTypes[mimeType] {
|
||||||
|
g.ResponseWriter.Header().Set("Content-Encoding", "gzip")
|
||||||
|
g.ResponseWriter.Header().Add("Vary", "Accept-Encoding")
|
||||||
|
g.ResponseWriter.Header().Del("Content-Length")
|
||||||
|
g.compressed = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *gzipResponseWriter) Flush() {
|
||||||
|
if g.compressed {
|
||||||
|
g.gzWriter.Flush()
|
||||||
|
}
|
||||||
|
if flusher, ok := g.ResponseWriter.(http.Flusher); ok {
|
||||||
|
flusher.Flush()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *gzipResponseWriter) close() {
|
||||||
|
if g.compressed {
|
||||||
|
g.gzWriter.Close()
|
||||||
|
gzipWriterPool.Put(g.gzWriter)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func clientAcceptsGzip(r *http.Request) bool {
|
||||||
|
return strings.Contains(r.Header.Get("Accept-Encoding"), "gzip")
|
||||||
|
}
|
||||||
|
|
||||||
|
func isAlreadyCompressed(header http.Header) bool {
|
||||||
|
return header.Get("Content-Encoding") != ""
|
||||||
|
}
|
||||||
|
|
||||||
|
func newGzipResponseWriter(w http.ResponseWriter) *gzipResponseWriter {
|
||||||
|
gz := gzipWriterPool.Get().(*gzip.Writer)
|
||||||
|
gz.Reset(w)
|
||||||
|
return &gzipResponseWriter{
|
||||||
|
ResponseWriter: w,
|
||||||
|
gzWriter: gz,
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -170,10 +170,19 @@ func isRootFileRoutingEnabled(host string) bool {
|
|||||||
return site.Root_file_routing
|
return site.Root_file_routing
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// По умолчанию роутинг выключен
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Проверяет включено ли сжатие для сайта
|
||||||
|
func isSiteCompressionEnabled(host string) bool {
|
||||||
|
for _, site := range config.ConfigData.Site_www {
|
||||||
|
if site.Host == host {
|
||||||
|
return site.IsCompressionEnabled()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
// Проверка vAccess с обработкой ошибки
|
// Проверка vAccess с обработкой ошибки
|
||||||
// Возвращает true если доступ разрешён, false если заблокирован
|
// Возвращает true если доступ разрешён, false если заблокирован
|
||||||
func checkVAccessAndHandle(w http.ResponseWriter, r *http.Request, filePath string, host string) bool {
|
func checkVAccessAndHandle(w http.ResponseWriter, r *http.Request, filePath string, host string) bool {
|
||||||
@@ -246,6 +255,13 @@ func handler(w http.ResponseWriter, r *http.Request) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Сжатие ответа (gzip)
|
||||||
|
if isSiteCompressionEnabled(host) && clientAcceptsGzip(r) {
|
||||||
|
gzw := newGzipResponseWriter(w)
|
||||||
|
defer gzw.close()
|
||||||
|
w = gzw
|
||||||
|
}
|
||||||
|
|
||||||
// Проверяем существование директории сайта
|
// Проверяем существование директории сайта
|
||||||
if _, err := os.Stat("WebServer/www/" + host + "/public_www"); err != nil {
|
if _, err := os.Stat("WebServer/www/" + host + "/public_www"); err != nil {
|
||||||
http.ServeFile(w, r, "WebServer/tools/error_page/index.html")
|
http.ServeFile(w, r, "WebServer/tools/error_page/index.html")
|
||||||
|
|||||||
@@ -306,26 +306,30 @@ func StartHandlerProxy(w http.ResponseWriter, r *http.Request) (valid bool) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Сжатие ответа (gzip) — только если бэкенд не сжал сам
|
||||||
|
var gzw *gzipResponseWriter
|
||||||
|
if proxyConfig.IsCompressionEnabled() && clientAcceptsGzip(r) && !isAlreadyCompressed(resp.Header) {
|
||||||
|
gzw = newGzipResponseWriter(w)
|
||||||
|
defer gzw.close()
|
||||||
|
w = gzw
|
||||||
|
}
|
||||||
|
|
||||||
// Устанавливаем статус код
|
// Устанавливаем статус код
|
||||||
w.WriteHeader(resp.StatusCode)
|
w.WriteHeader(resp.StatusCode)
|
||||||
|
|
||||||
// Копируем тело ответа с поддержкой streaming (SSE, chunked responses)
|
// Копируем тело ответа с поддержкой streaming (SSE, chunked responses)
|
||||||
// Используем буферизированное копирование с принудительной отправкой данных
|
|
||||||
flusher, canFlush := w.(http.Flusher)
|
flusher, canFlush := w.(http.Flusher)
|
||||||
|
|
||||||
// Буфер для чанков (32KB - оптимальный размер для баланса производительности)
|
|
||||||
buffer := make([]byte, 32*1024)
|
buffer := make([]byte, 32*1024)
|
||||||
|
|
||||||
for {
|
for {
|
||||||
n, err := resp.Body.Read(buffer)
|
n, err := resp.Body.Read(buffer)
|
||||||
if n > 0 {
|
if n > 0 {
|
||||||
// Записываем прочитанные данные
|
|
||||||
if _, writeErr := w.Write(buffer[:n]); writeErr != nil {
|
if _, writeErr := w.Write(buffer[:n]); writeErr != nil {
|
||||||
log.Printf("Ошибка записи тела ответа: %v", writeErr)
|
log.Printf("Ошибка записи тела ответа: %v", writeErr)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
// Принудительно отправляем данные клиенту (критично для SSE)
|
|
||||||
if canFlush {
|
if canFlush {
|
||||||
flusher.Flush()
|
flusher.Flush()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ type ProxyInfo struct {
|
|||||||
ServiceHTTPSuse bool `json:"ServiceHTTPSuse"`
|
ServiceHTTPSuse bool `json:"ServiceHTTPSuse"`
|
||||||
AutoHTTPS bool `json:"AutoHTTPS"`
|
AutoHTTPS bool `json:"AutoHTTPS"`
|
||||||
AutoCreateSSL bool `json:"AutoCreateSSL"`
|
AutoCreateSSL bool `json:"AutoCreateSSL"`
|
||||||
|
Compression *bool `json:"Compression"`
|
||||||
Status string `json:"Status"`
|
Status string `json:"Status"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -156,6 +156,7 @@ func AddSiteToConfig(siteData SiteInfo) error {
|
|||||||
Status: siteData.Status,
|
Status: siteData.Status,
|
||||||
Root_file: siteData.RootFile,
|
Root_file: siteData.RootFile,
|
||||||
Root_file_routing: siteData.RootFileRouting,
|
Root_file_routing: siteData.RootFileRouting,
|
||||||
|
Compression: siteData.Compression,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Добавляем в массив
|
// Добавляем в массив
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ func GetSitesList() []SiteInfo {
|
|||||||
RootFile: site.Root_file,
|
RootFile: site.Root_file,
|
||||||
RootFileRouting: site.Root_file_routing,
|
RootFileRouting: site.Root_file_routing,
|
||||||
AutoCreateSSL: site.AutoCreateSSL,
|
AutoCreateSSL: site.AutoCreateSSL,
|
||||||
|
Compression: site.Compression,
|
||||||
}
|
}
|
||||||
sites = append(sites, siteInfo)
|
sites = append(sites, siteInfo)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,5 +8,6 @@ type SiteInfo struct {
|
|||||||
RootFile string `json:"root_file"`
|
RootFile string `json:"root_file"`
|
||||||
RootFileRouting bool `json:"root_file_routing"`
|
RootFileRouting bool `json:"root_file_routing"`
|
||||||
AutoCreateSSL bool `json:"auto_create_ssl"`
|
AutoCreateSSL bool `json:"auto_create_ssl"`
|
||||||
|
Compression *bool `json:"Compression"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -22,6 +22,14 @@ type Site_www struct {
|
|||||||
Root_file string `json:"root_file"`
|
Root_file string `json:"root_file"`
|
||||||
Root_file_routing bool `json:"root_file_routing"`
|
Root_file_routing bool `json:"root_file_routing"`
|
||||||
AutoCreateSSL bool `json:"AutoCreateSSL"`
|
AutoCreateSSL bool `json:"AutoCreateSSL"`
|
||||||
|
Compression *bool `json:"Compression"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s Site_www) IsCompressionEnabled() bool {
|
||||||
|
if s.Compression == nil {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return *s.Compression
|
||||||
}
|
}
|
||||||
|
|
||||||
type Soft_Settings struct {
|
type Soft_Settings struct {
|
||||||
@@ -42,6 +50,14 @@ type Proxy_Service struct {
|
|||||||
ServiceHTTPSuse bool `json:"ServiceHTTPSuse"`
|
ServiceHTTPSuse bool `json:"ServiceHTTPSuse"`
|
||||||
AutoHTTPS bool `json:"AutoHTTPS"`
|
AutoHTTPS bool `json:"AutoHTTPS"`
|
||||||
AutoCreateSSL bool `json:"AutoCreateSSL"`
|
AutoCreateSSL bool `json:"AutoCreateSSL"`
|
||||||
|
Compression *bool `json:"Compression"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p Proxy_Service) IsCompressionEnabled() bool {
|
||||||
|
if p.Compression == nil {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return *p.Compression
|
||||||
}
|
}
|
||||||
|
|
||||||
func LoadConfig() {
|
func LoadConfig() {
|
||||||
@@ -88,6 +104,20 @@ func migrateConfig(originalData []byte) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Проверяем Site_www на наличие Compression
|
||||||
|
if rawSites, ok := rawConfig["Site_www"]; ok {
|
||||||
|
var sites2 []map[string]interface{}
|
||||||
|
if err := json.Unmarshal(rawSites, &sites2); err == nil {
|
||||||
|
for i, site := range sites2 {
|
||||||
|
if _, exists := site["Compression"]; !exists {
|
||||||
|
needsSave = true
|
||||||
|
compressionTrue := true
|
||||||
|
ConfigData.Site_www[i].Compression = &compressionTrue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Проверяем Proxy_Service
|
// Проверяем Proxy_Service
|
||||||
if rawProxies, ok := rawConfig["Proxy_Service"]; ok {
|
if rawProxies, ok := rawConfig["Proxy_Service"]; ok {
|
||||||
var proxies []map[string]interface{}
|
var proxies []map[string]interface{}
|
||||||
@@ -101,6 +131,20 @@ func migrateConfig(originalData []byte) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Проверяем Proxy_Service на наличие Compression
|
||||||
|
if rawProxies, ok := rawConfig["Proxy_Service"]; ok {
|
||||||
|
var proxies2 []map[string]interface{}
|
||||||
|
if err := json.Unmarshal(rawProxies, &proxies2); err == nil {
|
||||||
|
for i, proxy := range proxies2 {
|
||||||
|
if _, exists := proxy["Compression"]; !exists {
|
||||||
|
needsSave = true
|
||||||
|
compressionTrue := true
|
||||||
|
ConfigData.Proxy_Service[i].Compression = &compressionTrue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Проверяем Soft_Settings на наличие ACME_enabled
|
// Проверяем Soft_Settings на наличие ACME_enabled
|
||||||
if rawSettings, ok := rawConfig["Soft_Settings"]; ok {
|
if rawSettings, ok := rawConfig["Soft_Settings"]; ok {
|
||||||
var settings map[string]interface{}
|
var settings map[string]interface{}
|
||||||
|
|||||||
@@ -64,6 +64,8 @@
|
|||||||
"formStatus": "Status",
|
"formStatus": "Status",
|
||||||
"formRouting": "Root file routing",
|
"formRouting": "Root file routing",
|
||||||
"formRoutingHint": "If enabled, all requests to non-existent files will be redirected to the root file",
|
"formRoutingHint": "If enabled, all requests to non-existent files will be redirected to the root file",
|
||||||
|
"formCompression": "Gzip compression",
|
||||||
|
"formCompressionHint": "Compress text responses (HTML, CSS, JS, JSON, SVG) to reduce traffic",
|
||||||
"deleteTitle": "Delete Site",
|
"deleteTitle": "Delete Site",
|
||||||
"deleteConfirm": "Are you sure you want to delete site \"{name}\" ({host})?",
|
"deleteConfirm": "Are you sure you want to delete site \"{name}\" ({host})?",
|
||||||
"deleteWarning": "This action is IRREVERSIBLE!"
|
"deleteWarning": "This action is IRREVERSIBLE!"
|
||||||
@@ -88,6 +90,8 @@
|
|||||||
"formLocalPort": "Local Port",
|
"formLocalPort": "Local Port",
|
||||||
"formServiceHttps": "HTTPS to service",
|
"formServiceHttps": "HTTPS to service",
|
||||||
"formServiceHttpsHint": "Use HTTPS when connecting to the local service",
|
"formServiceHttpsHint": "Use HTTPS when connecting to the local service",
|
||||||
|
"formCompression": "Gzip compression",
|
||||||
|
"formCompressionHint": "Compress text responses (HTML, CSS, JS, JSON, SVG) to reduce traffic",
|
||||||
"formAutoHttps": "Auto HTTPS",
|
"formAutoHttps": "Auto HTTPS",
|
||||||
"formAutoHttpsHint": "Automatically redirect HTTP requests to HTTPS",
|
"formAutoHttpsHint": "Automatically redirect HTTP requests to HTTPS",
|
||||||
"deleteTitle": "Delete Proxy",
|
"deleteTitle": "Delete Proxy",
|
||||||
|
|||||||
@@ -64,6 +64,8 @@
|
|||||||
"formStatus": "Статус",
|
"formStatus": "Статус",
|
||||||
"formRouting": "Root file routing",
|
"formRouting": "Root file routing",
|
||||||
"formRoutingHint": "Если включено, все запросы к несуществующим файлам будут перенаправляться на root файл",
|
"formRoutingHint": "Если включено, все запросы к несуществующим файлам будут перенаправляться на root файл",
|
||||||
|
"formCompression": "Gzip сжатие",
|
||||||
|
"formCompressionHint": "Сжатие текстовых ответов (HTML, CSS, JS, JSON, SVG) для уменьшения трафика",
|
||||||
"deleteTitle": "Удалить сайт",
|
"deleteTitle": "Удалить сайт",
|
||||||
"deleteConfirm": "Вы действительно хотите удалить сайт \"{name}\" ({host})?",
|
"deleteConfirm": "Вы действительно хотите удалить сайт \"{name}\" ({host})?",
|
||||||
"deleteWarning": "Это действие НЕОБРАТИМО!"
|
"deleteWarning": "Это действие НЕОБРАТИМО!"
|
||||||
@@ -88,6 +90,8 @@
|
|||||||
"formLocalPort": "Локальный порт",
|
"formLocalPort": "Локальный порт",
|
||||||
"formServiceHttps": "HTTPS к сервису",
|
"formServiceHttps": "HTTPS к сервису",
|
||||||
"formServiceHttpsHint": "Использовать HTTPS при подключении к локальному сервису",
|
"formServiceHttpsHint": "Использовать HTTPS при подключении к локальному сервису",
|
||||||
|
"formCompression": "Gzip сжатие",
|
||||||
|
"formCompressionHint": "Сжатие текстовых ответов (HTML, CSS, JS, JSON, SVG) для уменьшения трафика",
|
||||||
"formAutoHttps": "Авто HTTPS",
|
"formAutoHttps": "Авто HTTPS",
|
||||||
"formAutoHttpsHint": "Автоматически перенаправлять HTTP запросы на HTTPS",
|
"formAutoHttpsHint": "Автоматически перенаправлять HTTP запросы на HTTPS",
|
||||||
"deleteTitle": "Удалить прокси",
|
"deleteTitle": "Удалить прокси",
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ export const useProxiesStore = defineStore('proxies', {
|
|||||||
LocalPort: proxyData.localPort,
|
LocalPort: proxyData.localPort,
|
||||||
ServiceHTTPSuse: proxyData.serviceHttps,
|
ServiceHTTPSuse: proxyData.serviceHttps,
|
||||||
AutoHTTPS: proxyData.autoHttps,
|
AutoHTTPS: proxyData.autoHttps,
|
||||||
|
Compression: proxyData.compression !== undefined ? proxyData.compression : true,
|
||||||
AutoCreateSSL: proxyData.autoSSL,
|
AutoCreateSSL: proxyData.autoSSL,
|
||||||
})
|
})
|
||||||
const result = await api.saveConfig(JSON.stringify(config))
|
const result = await api.saveConfig(JSON.stringify(config))
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ const form = reactive({
|
|||||||
localAddr: '127.0.0.1',
|
localAddr: '127.0.0.1',
|
||||||
localPort: '',
|
localPort: '',
|
||||||
serviceHttps: false,
|
serviceHttps: false,
|
||||||
|
compression: true,
|
||||||
certMode: 'none',
|
certMode: 'none',
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -26,6 +27,7 @@ const createProxy = async () => {
|
|||||||
enabled: true,
|
enabled: true,
|
||||||
serviceHttps: form.serviceHttps,
|
serviceHttps: form.serviceHttps,
|
||||||
autoHttps: form.serviceHttps,
|
autoHttps: form.serviceHttps,
|
||||||
|
compression: form.compression,
|
||||||
autoSSL: false,
|
autoSSL: false,
|
||||||
})
|
})
|
||||||
creating.value = false
|
creating.value = false
|
||||||
@@ -70,6 +72,14 @@ const createProxy = async () => {
|
|||||||
<VToggle v-model="form.serviceHttps" :label="t('common.enabled')" />
|
<VToggle v-model="form.serviceHttps" :label="t('common.enabled')" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<div class="form-label-row">
|
||||||
|
<VTooltip :text="t('proxies.formCompressionHint')" />
|
||||||
|
<label class="form-label">{{ t('proxies.formCompression') }}</label>
|
||||||
|
</div>
|
||||||
|
<VToggle v-model="form.compression" :label="t('common.enabled')" />
|
||||||
|
</div>
|
||||||
|
|
||||||
<SslUploadSection v-model="form.certMode" />
|
<SslUploadSection v-model="form.certMode" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ const form = reactive({
|
|||||||
localPort: '',
|
localPort: '',
|
||||||
enabled: true,
|
enabled: true,
|
||||||
serviceHttps: false,
|
serviceHttps: false,
|
||||||
|
compression: true,
|
||||||
autoHttps: true,
|
autoHttps: true,
|
||||||
autoSSL: false,
|
autoSSL: false,
|
||||||
})
|
})
|
||||||
@@ -33,6 +34,7 @@ onMounted(async () => {
|
|||||||
form.localPort = proxy.LocalPort
|
form.localPort = proxy.LocalPort
|
||||||
form.enabled = proxy.Enable
|
form.enabled = proxy.Enable
|
||||||
form.serviceHttps = proxy.ServiceHTTPSuse
|
form.serviceHttps = proxy.ServiceHTTPSuse
|
||||||
|
form.compression = proxy.Compression !== false
|
||||||
form.autoHttps = proxy.AutoHTTPS
|
form.autoHttps = proxy.AutoHTTPS
|
||||||
form.autoSSL = proxy.AutoCreateSSL || false
|
form.autoSSL = proxy.AutoCreateSSL || false
|
||||||
}
|
}
|
||||||
@@ -50,6 +52,7 @@ const saveProxy = async () => {
|
|||||||
config.Proxy_Service[idx].Enable = form.enabled
|
config.Proxy_Service[idx].Enable = form.enabled
|
||||||
config.Proxy_Service[idx].ServiceHTTPSuse = form.serviceHttps
|
config.Proxy_Service[idx].ServiceHTTPSuse = form.serviceHttps
|
||||||
config.Proxy_Service[idx].AutoHTTPS = form.serviceHttps
|
config.Proxy_Service[idx].AutoHTTPS = form.serviceHttps
|
||||||
|
config.Proxy_Service[idx].Compression = form.compression
|
||||||
config.Proxy_Service[idx].AutoCreateSSL = form.autoSSL
|
config.Proxy_Service[idx].AutoCreateSSL = form.autoSSL
|
||||||
const result = await api.saveConfig(JSON.stringify(config))
|
const result = await api.saveConfig(JSON.stringify(config))
|
||||||
if (isSuccess(result)) {
|
if (isSuccess(result)) {
|
||||||
@@ -120,7 +123,11 @@ const confirmDelete = async () => {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Toggles -->
|
<!-- Toggles -->
|
||||||
<div class="form-row">
|
<div class="form-row form-row-3">
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="form-label">{{ t('proxies.formCompression') }}:</label>
|
||||||
|
<VToggle v-model="form.compression" :label="t('common.enabled')" />
|
||||||
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label class="form-label">HTTPS:</label>
|
<label class="form-label">HTTPS:</label>
|
||||||
<VToggle v-model="form.serviceHttps" :label="t('common.enabled')" />
|
<VToggle v-model="form.serviceHttps" :label="t('common.enabled')" />
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ const form = reactive({
|
|||||||
rootFile: 'index.html',
|
rootFile: 'index.html',
|
||||||
status: 'active',
|
status: 'active',
|
||||||
routing: true,
|
routing: true,
|
||||||
|
compression: true,
|
||||||
certMode: 'none',
|
certMode: 'none',
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -36,6 +37,7 @@ const createSite = async () => {
|
|||||||
root_file: form.rootFile,
|
root_file: form.rootFile,
|
||||||
status: form.status,
|
status: form.status,
|
||||||
root_file_routing: form.routing,
|
root_file_routing: form.routing,
|
||||||
|
Compression: form.compression,
|
||||||
AutoCreateSSL: form.certMode === 'auto',
|
AutoCreateSSL: form.certMode === 'auto',
|
||||||
}
|
}
|
||||||
const result = await sitesStore.create(siteData)
|
const result = await sitesStore.create(siteData)
|
||||||
@@ -82,6 +84,14 @@ const createSite = async () => {
|
|||||||
<VToggle v-model="form.routing" :label="t('common.enabled')" />
|
<VToggle v-model="form.routing" :label="t('common.enabled')" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="form-group">
|
||||||
|
<div class="form-label-row">
|
||||||
|
<VTooltip :text="t('sites.formCompressionHint')" />
|
||||||
|
<label class="form-label">{{ t('sites.formCompression') }}</label>
|
||||||
|
</div>
|
||||||
|
<VToggle v-model="form.compression" :label="t('common.enabled')" />
|
||||||
|
</div>
|
||||||
|
|
||||||
<SslUploadSection v-model="form.certMode" />
|
<SslUploadSection v-model="form.certMode" />
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ const form = reactive({
|
|||||||
rootFile: 'index.html',
|
rootFile: 'index.html',
|
||||||
status: 'active',
|
status: 'active',
|
||||||
routing: true,
|
routing: true,
|
||||||
|
compression: true,
|
||||||
autoSSL: false,
|
autoSSL: false,
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -38,6 +39,7 @@ onMounted(async () => {
|
|||||||
form.rootFile = site.root_file
|
form.rootFile = site.root_file
|
||||||
form.status = site.status
|
form.status = site.status
|
||||||
form.routing = site.root_file_routing
|
form.routing = site.root_file_routing
|
||||||
|
form.compression = site.Compression !== false
|
||||||
form.autoSSL = site.AutoCreateSSL || false
|
form.autoSSL = site.AutoCreateSSL || false
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -65,6 +67,7 @@ const saveSite = async () => {
|
|||||||
config.Site_www[idx].root_file = form.rootFile
|
config.Site_www[idx].root_file = form.rootFile
|
||||||
config.Site_www[idx].status = form.status
|
config.Site_www[idx].status = form.status
|
||||||
config.Site_www[idx].root_file_routing = form.routing
|
config.Site_www[idx].root_file_routing = form.routing
|
||||||
|
config.Site_www[idx].Compression = form.compression
|
||||||
config.Site_www[idx].AutoCreateSSL = form.autoSSL
|
config.Site_www[idx].AutoCreateSSL = form.autoSSL
|
||||||
const result = await api.saveConfig(JSON.stringify(config))
|
const result = await api.saveConfig(JSON.stringify(config))
|
||||||
if (isSuccess(result)) {
|
if (isSuccess(result)) {
|
||||||
@@ -147,7 +150,11 @@ const confirmDelete = async () => {
|
|||||||
<VSelect v-model="form.rootFile" :label="t('sites.formRootFile')" :options="rootFileOptions" />
|
<VSelect v-model="form.rootFile" :label="t('sites.formRootFile')" :options="rootFileOptions" />
|
||||||
|
|
||||||
<!-- Toggles -->
|
<!-- Toggles -->
|
||||||
<div class="form-row">
|
<div class="form-row form-row-3">
|
||||||
|
<div class="form-group">
|
||||||
|
<label class="form-label">{{ t('sites.formCompression') }}:</label>
|
||||||
|
<VToggle v-model="form.compression" :label="t('common.enabled')" />
|
||||||
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label class="form-label">{{ t('sites.formRouting') }}:</label>
|
<label class="form-label">{{ t('sites.formRouting') }}:</label>
|
||||||
<VToggle v-model="form.routing" :label="t('common.enabled')" />
|
<VToggle v-model="form.routing" :label="t('common.enabled')" />
|
||||||
|
|||||||
Reference in New Issue
Block a user