Инициализация проекта

Стабильный рабочий проект.
This commit is contained in:
Falknat
2025-10-02 06:02:45 +07:00
commit 7a87617282
47 changed files with 6057 additions and 0 deletions

View File

@@ -0,0 +1,122 @@
package command
import (
"io/fs"
"net/http"
"path/filepath"
"strings"
webserver "vServer/Backend/WebServer"
admin "vServer/Backend/admin"
json "vServer/Backend/admin/go/json"
)
func SecurePost(w http.ResponseWriter, r *http.Request) bool {
// Проверяем, что запрос POST (не GET из браузера)
if webserver.Secure_post {
if r.Method != "POST" {
http.Error(w, "Метод не разрешен. Используйте POST", http.StatusMethodNotAllowed)
return false
}
}
return true
}
// API обработчик для /api/*
func ApiHandler(w http.ResponseWriter, r *http.Request) {
path := r.URL.Path
switch path {
case "/api/metrics":
json.GetAllMetrics(w)
default:
http.NotFound(w, r)
}
}
// JSON обработчик для /json/*
func JsonHandler(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
path := r.URL.Path
switch path {
case "/json/server_status.json":
w.Write(json.GetServerStatusJSON())
case "/json/menu.json":
w.Write(json.GetMenuJSON())
default:
http.NotFound(w, r)
}
}
// Обработчик сервисных команд для /service/*
func ServiceHandler(w http.ResponseWriter, r *http.Request) {
path := r.URL.Path
if !SecurePost(w, r) {
return
}
if SiteList(w, r, path) {
return
}
if site_add(w, path) {
return
}
if Service_Run(w, r, path) {
return
}
http.NotFound(w, r)
}
// Обработчик статических файлов из embed
func StaticHandler(w http.ResponseWriter, r *http.Request) {
path := r.URL.Path
// Убираем ведущий слэш
path = strings.TrimPrefix(path, "/")
// Если пустой путь, показываем index.html
if path == "" {
path = "html/index.html"
} else {
path = "html/" + path
}
// Читаем файл из файловой системы (embed или диск)
fileSystem := admin.GetFileSystem()
content, err := fs.ReadFile(fileSystem, path)
if err != nil {
http.NotFound(w, r)
return
}
// Устанавливаем правильный Content-Type
ext := filepath.Ext(path)
switch ext {
case ".css":
w.Header().Set("Content-Type", "text/css")
case ".js":
w.Header().Set("Content-Type", "application/javascript")
case ".json":
w.Header().Set("Content-Type", "application/json")
case ".html":
w.Header().Set("Content-Type", "text/html")
}
// Предотвращаем кеширование в режиме разработки (когда UseEmbedded = false)
if !admin.UseEmbedded {
w.Header().Set("Cache-Control", "no-cache, no-store, must-revalidate")
w.Header().Set("Pragma", "no-cache")
w.Header().Set("Expires", "0")
}
// Отдаем файл
w.Write(content)
}

View File

@@ -0,0 +1,57 @@
package command
import (
"net/http"
webserver "vServer/Backend/WebServer"
json "vServer/Backend/admin/go/json"
)
// Обработчик команд управления серверами
func Service_Run(w http.ResponseWriter, r *http.Request, path string) bool {
switch path {
case "/service/MySql_Stop":
webserver.StopMySQLServer()
json.UpdateServerStatus("MySQL Server", "stopped")
return true
case "/service/MySql_Start":
webserver.StartMySQLServer(false)
json.UpdateServerStatus("MySQL Server", "running")
return true
case "/service/Http_Stop":
webserver.StopHTTPServer()
json.UpdateServerStatus("HTTP Server", "stopped")
return true
case "/service/Http_Start":
go webserver.StartHTTP()
json.UpdateServerStatus("HTTP Server", "running")
return true
case "/service/Https_Stop":
webserver.StopHTTPSServer()
json.UpdateServerStatus("HTTPS Server", "stopped")
return true
case "/service/Https_Start":
go webserver.StartHTTPS()
json.UpdateServerStatus("HTTPS Server", "running")
return true
case "/service/Php_Start":
webserver.PHP_Start()
json.UpdateServerStatus("PHP Server", "running")
return true
case "/service/Php_Stop":
webserver.PHP_Stop()
json.UpdateServerStatus("PHP Server", "stopped")
return true
default:
http.NotFound(w, r)
return false // Команда не найдена
}
}

View File

@@ -0,0 +1,269 @@
package command
import (
"encoding/json"
"net/http"
"os"
"regexp"
"strings"
"vServer/Backend/config"
"vServer/Backend/tools"
)
var entries []os.DirEntry
func path_www() {
wwwPath, err := tools.AbsPath("WebServer/www")
tools.Error_check(err, "Ошибка получения пути")
entries, err = os.ReadDir(wwwPath)
tools.Error_check(err, "Ошибка чтения директории")
}
func site_type(entry os.DirEntry) string {
certPath, err := tools.AbsPath("WebServer/cert/" + entry.Name())
if err == nil {
if _, err := os.Stat(certPath); err == nil {
return "https"
}
}
return "http"
}
func site_alliace(siteName string) []string {
// Получаем абсолютный путь к config.json
configPath, err := tools.AbsPath("WebServer/config.json")
tools.Error_check(err, "Ошибка получения пути к config.json")
// Читаем содержимое config.json
configData, err := os.ReadFile(configPath)
tools.Error_check(err, "Ошибка чтения config.json")
// Структура для парсинга Site_www
type SiteConfig struct {
Name string `json:"name"`
Host string `json:"host"`
Alias []string `json:"alias"`
Status string `json:"status"`
}
type Config struct {
SiteWWW []SiteConfig `json:"Site_www"`
}
var config Config
err = json.Unmarshal(configData, &config)
tools.Error_check(err, "Ошибка парсинга config.json")
// Ищем алиасы для конкретного сайта
for _, site := range config.SiteWWW {
if site.Host == siteName {
return site.Alias
}
}
// Возвращаем пустой массив если сайт не найден
return []string{}
}
func site_status(siteName string) string {
configPath := "WebServer/config.json"
// Читаем конфигурационный файл
data, err := os.ReadFile(configPath)
if err != nil {
return "error"
}
// Парсим JSON
var config map[string]interface{}
if err := json.Unmarshal(data, &config); err != nil {
return "error"
}
// Получаем список сайтов
siteWww, ok := config["Site_www"].([]interface{})
if !ok {
return "error"
}
// Ищем сайт по host
for _, siteInterface := range siteWww {
site, ok := siteInterface.(map[string]interface{})
if !ok {
continue
}
// Проверяем только по host (имя папки)
if host, ok := site["host"].(string); ok && host == siteName {
if status, ok := site["status"].(string); ok {
return status
}
}
}
return "inactive"
}
func SiteList(w http.ResponseWriter, r *http.Request, path string) bool {
switch path {
case "/service/Site_List":
sites := []map[string]interface{}{}
path_www()
for _, entry := range entries {
if entry.IsDir() {
site := map[string]interface{}{
"host": entry.Name(),
"type": site_type(entry),
"aliases": site_alliace(entry.Name()),
"status": site_status(entry.Name()),
}
sites = append(sites, site)
}
}
metrics := map[string]interface{}{
"sites": sites,
}
data, _ := json.MarshalIndent(metrics, "", " ")
w.Write(data)
return true
}
return false
}
func addSiteToConfig(siteName string) error {
// Получаем абсолютный путь к config.json
configPath, err := tools.AbsPath("WebServer/config.json")
if err != nil {
return err
}
// Читаем содержимое config.json
configData, err := os.ReadFile(configPath)
if err != nil {
return err
}
// Парсим как общий JSON объект
var config map[string]interface{}
err = json.Unmarshal(configData, &config)
if err != nil {
return err
}
// Получаем массив сайтов
siteWWW, ok := config["Site_www"].([]interface{})
if !ok {
siteWWW = []interface{}{}
}
// Создаем новый сайт в том же формате что уже есть
newSite := map[string]interface{}{
"name": siteName,
"host": siteName,
"alias": []string{""},
"status": "active",
}
// Добавляем новый сайт в массив
config["Site_www"] = append(siteWWW, newSite)
// Сохраняем обновленный конфиг
updatedData, err := json.MarshalIndent(config, "", " ")
if err != nil {
return err
}
// Делаем массивы алиасов в одну строку
re := regexp.MustCompile(`"alias": \[\s+"([^"]*?)"\s+\]`)
compactData := re.ReplaceAll(updatedData, []byte(`"alias": ["$1"]`))
// Исправляем отступы после Site_www
dataStr := string(compactData)
dataStr = strings.ReplaceAll(dataStr, ` ],
"Soft_Settings"`, ` ],
"Soft_Settings"`)
compactData = []byte(dataStr)
err = os.WriteFile(configPath, compactData, 0644)
if err != nil {
return err
}
return nil
}
func site_add(w http.ResponseWriter, path string) bool {
// URL параметры: /service/Site_Add/sitename
if strings.HasPrefix(path, "/service/Site_Add/") {
siteName := strings.TrimPrefix(path, "/service/Site_Add/")
if siteName == "" {
w.WriteHeader(400)
w.Write([]byte(`{"status":"error","message":"Не указано имя сайта в URL"}`))
return true
}
wwwPath := "WebServer/www/" + siteName
// Проверяем существует ли уже такой сайт
if _, err := os.Stat(wwwPath); err == nil {
w.WriteHeader(409) // Conflict
w.Write([]byte(`{"status":"error","message":"Сайт ` + siteName + ` уже существует"}`))
return true
}
err := os.MkdirAll(wwwPath, 0755)
if err != nil {
w.WriteHeader(500)
w.Write([]byte(`{"status":"error","message":"Ошибка создания папки сайта"}`))
return true
}
// Добавляем сайт в config.json
err = addSiteToConfig(siteName)
if err != nil {
w.WriteHeader(500)
w.Write([]byte(`{"status":"error","message":"Ошибка добавления в конфигурацию: ` + err.Error() + `"}`))
return true
}
// Создаем папку public_www
publicWwwPath := wwwPath + "/public_www"
err = os.MkdirAll(publicWwwPath, 0755)
if err != nil {
w.WriteHeader(500)
w.Write([]byte(`{"status":"error","message":"Ошибка создания папки public_www"}`))
return true
}
indexFilePath := wwwPath + "/public_www/index.html"
indexContent := "Привет друг! Твой сайт создан!"
err = os.WriteFile(indexFilePath, []byte(indexContent), 0644)
if err != nil {
w.WriteHeader(500)
w.Write([]byte(`{"status":"error","message":"Ошибка создания index.html: ` + err.Error() + `"}`))
return true
}
w.Write([]byte(`{"status":"ok","message":"Сайт ` + siteName + ` успешно создан и добавлен в конфигурацию"}`))
config.LoadConfig()
return true
}
return false
}