Большое обновление GUI интерфейс
Большое обновление GUI интерфейс - Добавлен фраемворr Walles - Удалена консольная версия - Проработан интерфейс и дизайн - Добавлено кеширование для быстрой реакции. - Сделан .ps1 сборщик для удобной сборки проекта. - Обновлён Readme
This commit is contained in:
@@ -4,7 +4,7 @@ import (
|
||||
"fmt"
|
||||
"os/exec"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
"syscall"
|
||||
"time"
|
||||
config "vServer/Backend/config"
|
||||
tools "vServer/Backend/tools"
|
||||
@@ -14,6 +14,11 @@ var mysqlProcess *exec.Cmd
|
||||
var mysql_status bool = false
|
||||
var mysql_secure bool = false
|
||||
|
||||
// GetMySQLStatus возвращает статус MySQL
|
||||
func GetMySQLStatus() bool {
|
||||
return mysql_status
|
||||
}
|
||||
|
||||
var mysqldPath string
|
||||
var configPath string
|
||||
var dataDirAbs string
|
||||
@@ -86,16 +91,8 @@ func StartMySQLServer(secure bool) {
|
||||
mysql_port = config.ConfigData.Soft_Settings.Mysql_port
|
||||
mysql_ip = config.ConfigData.Soft_Settings.Mysql_host
|
||||
|
||||
if tools.Port_check("MySQL", mysql_ip, strconv.Itoa(mysql_port)) {
|
||||
return
|
||||
}
|
||||
|
||||
if mysql_status {
|
||||
tools.Logs_file(1, "MySQL", "Сервер MySQL уже запущен", "logs_mysql.log", true)
|
||||
return
|
||||
}
|
||||
|
||||
if false {
|
||||
tools.Logs_file(1, "MySQL", "Сервер MySQL уже запущен", "logs_mysql.log", false)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -105,9 +102,9 @@ func StartMySQLServer(secure bool) {
|
||||
|
||||
// Выбор сообщения
|
||||
if secure {
|
||||
tools.Logs_file(0, "MySQL", "Запуск сервера MySQL в режиме безопасности", "logs_mysql.log", true)
|
||||
tools.Logs_file(0, "MySQL", "Запуск сервера MySQL в режиме безопасности", "logs_mysql.log", false)
|
||||
} else {
|
||||
tools.Logs_file(0, "MySQL", "Запуск сервера MySQL в обычном режиме", "logs_mysql.log", true)
|
||||
tools.Logs_file(0, "MySQL", "Запуск сервера MySQL в обычном режиме", "logs_mysql.log", false)
|
||||
}
|
||||
|
||||
// Общая логика запуска
|
||||
@@ -115,7 +112,7 @@ func StartMySQLServer(secure bool) {
|
||||
mysqlProcess.Dir = binDirAbs
|
||||
tools.Logs_console(mysqlProcess, console_mysql)
|
||||
|
||||
tools.Logs_file(0, "MySQL", fmt.Sprintf("Сервер MySQL запущен на %s:%d", mysql_ip, mysql_port), "logs_mysql.log", true)
|
||||
tools.Logs_file(0, "MySQL", fmt.Sprintf("Сервер MySQL запущен на %s:%d", mysql_ip, mysql_port), "logs_mysql.log", false)
|
||||
|
||||
mysql_status = true
|
||||
|
||||
@@ -124,22 +121,30 @@ func StartMySQLServer(secure bool) {
|
||||
// StopMySQLServer останавливает MySQL сервер
|
||||
func StopMySQLServer() {
|
||||
|
||||
if mysql_status {
|
||||
|
||||
cmd := exec.Command("taskkill", "/F", "/IM", "mysqld.exe")
|
||||
|
||||
err := cmd.Run()
|
||||
tools.CheckError(err)
|
||||
|
||||
tools.Logs_file(0, "MySQL", "Сервер MySQL остановлен", "logs_mysql.log", true)
|
||||
mysql_status = false
|
||||
|
||||
} else {
|
||||
|
||||
tools.Logs_file(1, "MySQL", "Сервер MySQL уже остановлен", "logs_mysql.log", true)
|
||||
|
||||
if !mysql_status {
|
||||
return // Уже остановлен
|
||||
}
|
||||
|
||||
// Сначала пробуем завершить процесс корректно
|
||||
if mysqlProcess != nil && mysqlProcess.Process != nil {
|
||||
mysqlProcess.Process.Kill()
|
||||
mysqlProcess = nil
|
||||
}
|
||||
|
||||
// Дополнительно убиваем все mysqld.exe процессы
|
||||
cmd := exec.Command("taskkill", "/F", "/IM", "mysqld.exe")
|
||||
|
||||
// Скрываем окно taskkill
|
||||
cmd.SysProcAttr = &syscall.SysProcAttr{
|
||||
HideWindow: true,
|
||||
CreationFlags: 0x08000000,
|
||||
}
|
||||
|
||||
cmd.Run()
|
||||
|
||||
tools.Logs_file(0, "MySQL", "Сервер MySQL остановлен", "logs_mysql.log", false)
|
||||
mysql_status = false
|
||||
|
||||
}
|
||||
|
||||
func ResetPasswordMySQL() {
|
||||
|
||||
@@ -1,195 +0,0 @@
|
||||
package webserver
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"time"
|
||||
admin "vServer/Backend/admin"
|
||||
config "vServer/Backend/config"
|
||||
tools "vServer/Backend/tools"
|
||||
)
|
||||
|
||||
var Secure_post bool = false
|
||||
|
||||
func CommandListener() {
|
||||
|
||||
fmt.Println("Введите help для получения списка команд")
|
||||
fmt.Println("")
|
||||
|
||||
for {
|
||||
var cmd string
|
||||
|
||||
fmt.Print(tools.Color(" > ", tools.Оранжевый))
|
||||
|
||||
fmt.Scanln(&cmd)
|
||||
|
||||
switch cmd {
|
||||
case "help":
|
||||
|
||||
fmt.Println(" ------------------------------------------")
|
||||
fmt.Println(" 1: mysql_stop - Остановить MySQL")
|
||||
fmt.Println(" 2: mysql_start - Запустить MySQL")
|
||||
fmt.Println(" 3: mysql_pass - Сбросить пароль MySQL")
|
||||
fmt.Println(" 4: clear - Очистить консоль")
|
||||
fmt.Println(" 5: cert_reload - Перезагрузить SSL сертификаты")
|
||||
fmt.Println(" 6: admin_toggle - Переключить режим админки (embed/файловая система)")
|
||||
fmt.Println(" 7: config_reload - Перезагрузить конфигурацию")
|
||||
fmt.Println(" 8: restart - Перезапустить сервер")
|
||||
fmt.Println(" 9: php_console - Открыть PHP консоль")
|
||||
fmt.Println(" 10: exit - выйти из программы")
|
||||
fmt.Println(" ------------------------------------------")
|
||||
fmt.Println("")
|
||||
|
||||
case "mysql_stop":
|
||||
StopMySQLServer()
|
||||
|
||||
case "mysql_start":
|
||||
StartMySQLServer(false)
|
||||
|
||||
case "mysql_pass":
|
||||
ResetPasswordMySQL()
|
||||
|
||||
case "clear":
|
||||
ClearConsole()
|
||||
|
||||
case "cert_reload":
|
||||
ReloadCertificates()
|
||||
|
||||
case "admin_toggle":
|
||||
AdminToggle()
|
||||
|
||||
case "config_reload":
|
||||
ConfigReload()
|
||||
|
||||
case "restart":
|
||||
RestartServer()
|
||||
|
||||
case "time_run":
|
||||
fmt.Println(tools.ServerUptime("get"))
|
||||
|
||||
case "secure_post":
|
||||
|
||||
if Secure_post {
|
||||
Secure_post = false
|
||||
fmt.Println("Secure post is disabled")
|
||||
} else {
|
||||
Secure_post = true
|
||||
fmt.Println("Secure post is enabled")
|
||||
}
|
||||
|
||||
case "exit":
|
||||
fmt.Println("Завершение...")
|
||||
os.Exit(0)
|
||||
|
||||
default:
|
||||
|
||||
fmt.Println(" Неизвестная команда. Введите 'help' для получения списка команд")
|
||||
fmt.Println("")
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func RestartServer() {
|
||||
fmt.Println("")
|
||||
fmt.Println("⏹️ Перезагрузка сервера...")
|
||||
|
||||
// Останавливаем все сервисы
|
||||
fmt.Println("⏹️ Останавливаем сервисы...")
|
||||
fmt.Println("")
|
||||
|
||||
// Останавливаем HTTP/HTTPS серверы
|
||||
StopHTTPServer()
|
||||
StopHTTPSServer()
|
||||
|
||||
// Останавливаем MySQL
|
||||
if mysql_status {
|
||||
StopMySQLServer()
|
||||
time.Sleep(1 * time.Second)
|
||||
}
|
||||
|
||||
// Останавливаем PHP
|
||||
PHP_Stop()
|
||||
time.Sleep(1 * time.Second)
|
||||
|
||||
fmt.Println("")
|
||||
fmt.Println("✅ Все сервисы остановлены")
|
||||
|
||||
// Перезагружаем конфигурацию
|
||||
fmt.Println("📋 Перезагружаем конфигурацию...")
|
||||
fmt.Println("")
|
||||
config.LoadConfig()
|
||||
|
||||
// Запускаем сервисы заново
|
||||
fmt.Println("🚀 Запускаем сервисы...")
|
||||
fmt.Println("")
|
||||
|
||||
// Запускаем HTTP/HTTPS серверы
|
||||
go StartHTTP()
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
go StartHTTPS()
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
|
||||
// Запускаем PHP
|
||||
PHP_Start()
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
|
||||
// Запускаем MySQL
|
||||
StartMySQLServer(false)
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
|
||||
fmt.Println("✅ Сервер успешно перезагружен!")
|
||||
fmt.Println("")
|
||||
}
|
||||
|
||||
func ClearConsole() {
|
||||
// Очищаем консоль, но сохраняем первые три строки
|
||||
fmt.Print("\033[H\033[2J") // ANSI escape code для очистки экрана
|
||||
|
||||
println("")
|
||||
println(tools.Color("vServer", tools.Жёлтый) + tools.Color(" 1.0.0", tools.Голубой))
|
||||
println(tools.Color("Автор: ", tools.Зелёный) + tools.Color("Суманеев Роман (c) 2025", tools.Голубой))
|
||||
println(tools.Color("Официальный сайт: ", tools.Зелёный) + tools.Color("https://voxsel.ru", tools.Голубой))
|
||||
|
||||
println("")
|
||||
|
||||
// Восстанавливаем первые три строки
|
||||
fmt.Println("Введите help для получения списка команд")
|
||||
fmt.Println("")
|
||||
}
|
||||
|
||||
// Переключает режим админки между embed и файловой системой
|
||||
func AdminToggle() {
|
||||
fmt.Println("")
|
||||
|
||||
if admin.UseEmbedded {
|
||||
// Переключаем на файловую систему
|
||||
admin.UseEmbedded = false
|
||||
fmt.Println("🔄 Режим изменен: Embedded → Файловая система")
|
||||
fmt.Println("✅ Админка переключена на файловую систему")
|
||||
fmt.Println("📁 Файлы будут загружаться с диска из Backend/admin/html/")
|
||||
fmt.Println("💡 Теперь можно редактировать файлы и изменения будут видны сразу")
|
||||
} else {
|
||||
// Переключаем обратно на embedded
|
||||
admin.UseEmbedded = true
|
||||
fmt.Println("🔄 Режим изменен: Файловая система → Embedded")
|
||||
fmt.Println("✅ Админка переключена на embedded режим")
|
||||
fmt.Println("📦 Файлы загружаются из встроенных ресурсов")
|
||||
fmt.Println("🚀 Быстрая загрузка, но изменения требуют перекомпиляции")
|
||||
}
|
||||
|
||||
fmt.Println("")
|
||||
}
|
||||
|
||||
// Перезагружает конфигурацию без перезапуска сервисов
|
||||
func ConfigReload() {
|
||||
fmt.Println("")
|
||||
fmt.Println("📋 Перезагружаем конфигурацию...")
|
||||
|
||||
// Загружаем новую конфигурацию
|
||||
config.LoadConfig()
|
||||
|
||||
fmt.Println("✅ Конфигурация успешно перезагружена!")
|
||||
fmt.Println("💡 Изменения применятся к новым запросам")
|
||||
fmt.Println("")
|
||||
}
|
||||
@@ -4,12 +4,34 @@ import (
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
"sync"
|
||||
"vServer/Backend/config"
|
||||
tools "vServer/Backend/tools"
|
||||
)
|
||||
|
||||
var (
|
||||
siteStatusCache map[string]bool
|
||||
statusMutex sync.RWMutex
|
||||
)
|
||||
|
||||
func StartHandler() {
|
||||
http.HandleFunc("/", handler)
|
||||
updateSiteStatusCache()
|
||||
}
|
||||
|
||||
func updateSiteStatusCache() {
|
||||
statusMutex.Lock()
|
||||
defer statusMutex.Unlock()
|
||||
|
||||
siteStatusCache = make(map[string]bool)
|
||||
for _, site := range config.ConfigData.Site_www {
|
||||
siteStatusCache[site.Host] = site.Status == "active"
|
||||
}
|
||||
}
|
||||
|
||||
// UpdateSiteStatusCache - экспортируемая функция для обновления кэша
|
||||
func UpdateSiteStatusCache() {
|
||||
updateSiteStatusCache()
|
||||
}
|
||||
|
||||
// Проверка wildcard паттерна для alias
|
||||
@@ -175,6 +197,17 @@ func checkVAccessAndHandle(w http.ResponseWriter, r *http.Request, filePath stri
|
||||
return true
|
||||
}
|
||||
|
||||
// Проверяет включен ли сайт (оптимизировано через кэш)
|
||||
func isSiteActive(host string) bool {
|
||||
statusMutex.RLock()
|
||||
defer statusMutex.RUnlock()
|
||||
|
||||
if status, exists := siteStatusCache[host]; exists {
|
||||
return status
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Обработчик запросов
|
||||
func handler(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
@@ -187,6 +220,13 @@ func handler(w http.ResponseWriter, r *http.Request) {
|
||||
return // Если прокси обработал запрос, прерываем выполнение
|
||||
}
|
||||
|
||||
// Проверяем статус сайта
|
||||
if !isSiteActive(host) {
|
||||
http.ServeFile(w, r, "WebServer/tools/error_page/index.html")
|
||||
tools.Logs_file(2, "H503", "🚫 Сайт отключен: "+host, "logs_http.log", false)
|
||||
return
|
||||
}
|
||||
|
||||
// ЕДИНСТВЕННАЯ ПРОВЕРКА vAccess - простая проверка запрошенного пути
|
||||
if !checkVAccessAndHandle(w, r, r.URL.Path, host) {
|
||||
return
|
||||
|
||||
@@ -8,6 +8,11 @@ import (
|
||||
var httpServer *http.Server
|
||||
var port_http string = "80"
|
||||
|
||||
// GetHTTPStatus возвращает статус HTTP сервера
|
||||
func GetHTTPStatus() bool {
|
||||
return httpServer != nil
|
||||
}
|
||||
|
||||
// Запуск HTTP сервера
|
||||
func StartHTTP() {
|
||||
|
||||
|
||||
@@ -18,6 +18,11 @@ var fallbackCert *tls.Certificate
|
||||
var httpsServer *http.Server
|
||||
var port_https string = "443"
|
||||
|
||||
// GetHTTPSStatus возвращает статус HTTPS сервера
|
||||
func GetHTTPSStatus() bool {
|
||||
return httpsServer != nil
|
||||
}
|
||||
|
||||
// Запуск https сервера
|
||||
func StartHTTPS() {
|
||||
|
||||
|
||||
@@ -13,6 +13,7 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"syscall"
|
||||
"time"
|
||||
config "vServer/Backend/config"
|
||||
tools "vServer/Backend/tools"
|
||||
@@ -30,6 +31,11 @@ var (
|
||||
var address_php string
|
||||
var Сonsole_php bool = false
|
||||
|
||||
// GetPHPStatus возвращает статус PHP сервера
|
||||
func GetPHPStatus() bool {
|
||||
return len(phpProcesses) > 0 && !stopping
|
||||
}
|
||||
|
||||
// FastCGI константы
|
||||
const (
|
||||
FCGI_VERSION_1 = 1
|
||||
@@ -99,6 +105,12 @@ func startFastCGIWorker(port int, workerID int) {
|
||||
"PHP_FCGI_MAX_REQUESTS=1000", // Перезапуск после 1000 запросов
|
||||
)
|
||||
|
||||
// Скрываем консольное окно
|
||||
cmd.SysProcAttr = &syscall.SysProcAttr{
|
||||
HideWindow: true,
|
||||
CreationFlags: 0x08000000, // CREATE_NO_WINDOW
|
||||
}
|
||||
|
||||
if !Сonsole_php {
|
||||
cmd.Stdout = nil
|
||||
cmd.Stderr = nil
|
||||
@@ -499,6 +511,10 @@ func PHP_Stop() {
|
||||
|
||||
// Дополнительно убиваем все процессы php-cgi.exe
|
||||
cmd := exec.Command("taskkill", "/F", "/IM", "php-cgi.exe")
|
||||
cmd.SysProcAttr = &syscall.SysProcAttr{
|
||||
HideWindow: true,
|
||||
CreationFlags: 0x08000000,
|
||||
}
|
||||
cmd.Run()
|
||||
|
||||
tools.Logs_file(0, "PHP", "🛑 Все FastCGI процессы остановлены", "logs_php.log", true)
|
||||
|
||||
@@ -21,6 +21,11 @@ func StartHandlerProxy(w http.ResponseWriter, r *http.Request) (valid bool) {
|
||||
configMutex.RLock()
|
||||
defer configMutex.RUnlock()
|
||||
|
||||
// Проверяем глобальный флаг прокси
|
||||
if !config.ConfigData.Soft_Settings.Proxy_enabled {
|
||||
return false
|
||||
}
|
||||
|
||||
// Проходим по всем прокси конфигурациям
|
||||
for _, proxyConfig := range config.ConfigData.Proxy_Service {
|
||||
// Пропускаем отключенные прокси
|
||||
|
||||
@@ -136,15 +136,21 @@ func findVAccessFiles(requestPath string, host string) []string {
|
||||
// Базовый путь к сайту (НЕ public_www, а уровень выше)
|
||||
basePath := "WebServer/www/" + host
|
||||
|
||||
// Получаем абсолютный базовый путь
|
||||
absBasePath, err := tools.AbsPath(basePath)
|
||||
if err != nil {
|
||||
return configFiles
|
||||
}
|
||||
|
||||
// Проверяем корневой vAccess.conf
|
||||
rootConfigPath := filepath.Join(basePath, "vAccess.conf")
|
||||
rootConfigPath := filepath.Join(absBasePath, "vAccess.conf")
|
||||
if _, err := os.Stat(rootConfigPath); err == nil {
|
||||
configFiles = append(configFiles, rootConfigPath)
|
||||
}
|
||||
|
||||
// Разбиваем путь на части для поиска вложенных конфигов
|
||||
pathParts := strings.Split(strings.Trim(requestPath, "/"), "/")
|
||||
currentPath := basePath
|
||||
currentPath := absBasePath
|
||||
|
||||
for _, part := range pathParts {
|
||||
if part == "" {
|
||||
@@ -439,7 +445,8 @@ func HandleVAccessError(w http.ResponseWriter, r *http.Request, errorPage string
|
||||
switch {
|
||||
case errorPage == "404":
|
||||
// Стандартная 404 страница
|
||||
http.ServeFile(w, r, "WebServer/tools/error_page/index.html")
|
||||
errorPagePath, _ := tools.AbsPath("WebServer/tools/error_page/index.html")
|
||||
http.ServeFile(w, r, errorPagePath)
|
||||
|
||||
case strings.HasPrefix(errorPage, "http://") || strings.HasPrefix(errorPage, "https://"):
|
||||
// Внешний сайт - редирект
|
||||
@@ -448,11 +455,13 @@ func HandleVAccessError(w http.ResponseWriter, r *http.Request, errorPage string
|
||||
default:
|
||||
// Локальный путь от public_www
|
||||
localPath := "WebServer/www/" + host + "/public_www" + errorPage
|
||||
if _, err := os.Stat(localPath); err == nil {
|
||||
http.ServeFile(w, r, localPath)
|
||||
absLocalPath, _ := tools.AbsPath(localPath)
|
||||
if _, err := os.Stat(absLocalPath); err == nil {
|
||||
http.ServeFile(w, r, absLocalPath)
|
||||
} else {
|
||||
// Файл не найден - показываем стандартную 404
|
||||
http.ServeFile(w, r, "WebServer/tools/error_page/index.html")
|
||||
errorPagePath, _ := tools.AbsPath("WebServer/tools/error_page/index.html")
|
||||
http.ServeFile(w, r, errorPagePath)
|
||||
tools.Logs_file(1, "vAccess", "❌ Страница ошибки не найдена: "+localPath, "logs_vaccess.log", false)
|
||||
}
|
||||
}
|
||||
@@ -468,14 +477,21 @@ func CheckProxyVAccess(requestPath string, domain string, r *http.Request) (bool
|
||||
// Путь к конфигурационному файлу прокси
|
||||
configPath := "WebServer/tools/Proxy_vAccess/" + domain + "_vAccess.conf"
|
||||
|
||||
// Получаем абсолютный путь
|
||||
absConfigPath, err := tools.AbsPath(configPath)
|
||||
if err != nil {
|
||||
// При ошибке получения пути - разрешаем доступ
|
||||
return true, ""
|
||||
}
|
||||
|
||||
// Проверяем существование файла
|
||||
if _, err := os.Stat(configPath); os.IsNotExist(err) {
|
||||
if _, err := os.Stat(absConfigPath); os.IsNotExist(err) {
|
||||
// Нет конфигурационного файла - разрешаем доступ
|
||||
return true, ""
|
||||
}
|
||||
|
||||
// Парсим конфигурационный файл
|
||||
config, err := parseVAccessFile(configPath)
|
||||
config, err := parseVAccessFile(absConfigPath)
|
||||
if err != nil {
|
||||
tools.Logs_file(1, "vAccess-Proxy", "❌ Ошибка парсинга "+configPath+": "+err.Error(), "logs_vaccess_proxy.log", false)
|
||||
return true, "" // При ошибке парсинга разрешаем доступ
|
||||
@@ -491,7 +507,8 @@ func HandleProxyVAccessError(w http.ResponseWriter, r *http.Request, errorPage s
|
||||
case errorPage == "404":
|
||||
// Стандартная 404 страница
|
||||
w.WriteHeader(http.StatusForbidden)
|
||||
http.ServeFile(w, r, "WebServer/tools/error_page/index.html")
|
||||
errorPagePath, _ := tools.AbsPath("WebServer/tools/error_page/index.html")
|
||||
http.ServeFile(w, r, errorPagePath)
|
||||
|
||||
case strings.HasPrefix(errorPage, "http://") || strings.HasPrefix(errorPage, "https://"):
|
||||
// Внешний сайт - редирект
|
||||
@@ -500,6 +517,7 @@ func HandleProxyVAccessError(w http.ResponseWriter, r *http.Request, errorPage s
|
||||
default:
|
||||
// Для прокси возвращаем 403 Forbidden
|
||||
w.WriteHeader(http.StatusForbidden)
|
||||
http.ServeFile(w, r, "WebServer/tools/error_page/index.html")
|
||||
errorPagePath, _ := tools.AbsPath("WebServer/tools/error_page/index.html")
|
||||
http.ServeFile(w, r, errorPagePath)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user