From b8d263bf865dc739c8a7f4ab96d1f10e128014f0 Mon Sep 17 00:00:00 2001 From: godo Date: Tue, 3 Dec 2024 11:14:31 +0800 Subject: [PATCH] add cloud server --- cloud/.gitignore | 3 ++ cloud/cmd/main.go | 69 +++++++++++++++++++++++++ cloud/cmd/msg.go | 54 +++++++++++++++++++ cloud/cmd/serve.go | 97 +++++++++++++++++++++++++++++++++++ cloud/deps/frontend.go | 6 +++ cloud/go.mod | 5 ++ cloud/go.sum | 2 + cloud/main.go | 7 +++ frontend/src/system/config.ts | 7 +-- 9 files changed, 245 insertions(+), 5 deletions(-) create mode 100644 cloud/.gitignore create mode 100644 cloud/cmd/main.go create mode 100644 cloud/cmd/msg.go create mode 100644 cloud/cmd/serve.go create mode 100644 cloud/deps/frontend.go create mode 100644 cloud/go.mod create mode 100644 cloud/go.sum create mode 100644 cloud/main.go diff --git a/cloud/.gitignore b/cloud/.gitignore new file mode 100644 index 0000000..655212e --- /dev/null +++ b/cloud/.gitignore @@ -0,0 +1,3 @@ +tmp +deps/dist +deps/*.zip diff --git a/cloud/cmd/main.go b/cloud/cmd/main.go new file mode 100644 index 0000000..e9937b2 --- /dev/null +++ b/cloud/cmd/main.go @@ -0,0 +1,69 @@ +/* + * GodoOS - A lightweight cloud desktop + * Copyright (C) 2024 https://godoos.com + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 2.1 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package cmd + +import ( + "context" + "godocloud/deps" + "io/fs" + "log" + "net/http" + "time" + + "github.com/gorilla/mux" +) + +const serverAddress = ":56781" + +var srv *http.Server + +func OsStart() { + //InitServer() + router := mux.NewRouter() + router.Use(recoverMiddleware) + router.Use(corsMiddleware()) + // 使用带有日志装饰的处理器注册路由 + router.Use(loggingMiddleware{}.Middleware) + + // 注册根路径的处理函数 + distFS, _ := fs.Sub(deps.Frontendassets, "dist") + fileServer := http.FileServer(http.FS(distFS)) + + // 注册根路径的处理函数 + router.PathPrefix("/").Handler(fileServer) + + //serverAddress := ":56781" + log.Printf("Listening on port: %v", serverAddress) + srv = &http.Server{Addr: serverAddress, Handler: router} + Serve(srv) +} +func OsStop() { + ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second) + defer cancel() + if err := srv.Shutdown(ctx); err != nil { + log.Fatalf("Server forced to shutdown: %v", err) + } + log.Println("Server stopped.") +} +func OsRestart() { + // 停止当前服务 + OsStop() + // 重新启动服务 + OsStart() +} diff --git a/cloud/cmd/msg.go b/cloud/cmd/msg.go new file mode 100644 index 0000000..f6319cb --- /dev/null +++ b/cloud/cmd/msg.go @@ -0,0 +1,54 @@ +/* + * GodoOS - A lightweight cloud desktop + * Copyright (C) 2024 https://godoos.com + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 2.1 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package cmd + +import ( + "encoding/json" + "net/http" +) + +type APIResponse struct { + Message string `json:"message"` + Code int `json:"code"` + Data any `json:"data,omitempty"` + Error string `json:"error,omitempty"` +} + +func WriteJSONResponse(w http.ResponseWriter, res APIResponse, status int) { + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(status) + json.NewEncoder(w).Encode(res) +} + +// HTTPError 返回带有JSON错误消息的HTTP错误 +func HTTPError(w http.ResponseWriter, status int, message string) { + WriteJSONResponse(w, APIResponse{Message: message, Code: -1}, status) +} +func ErrorMsg(w http.ResponseWriter, message string) { + WriteJSONResponse(w, APIResponse{Message: message, Code: -1}, 200) +} +func ErrorData(w http.ResponseWriter, data any, message string) { + WriteJSONResponse(w, APIResponse{Message: message, Data: data, Code: -1}, 200) +} +func Error(w http.ResponseWriter, message string, err string) { + WriteJSONResponse(w, APIResponse{Message: message, Error: err, Code: -1}, 200) +} +func SuccessMsg(w http.ResponseWriter, data any, message string) { + WriteJSONResponse(w, APIResponse{Message: message, Data: data, Code: 0}, 200) +} diff --git a/cloud/cmd/serve.go b/cloud/cmd/serve.go new file mode 100644 index 0000000..51bd6bc --- /dev/null +++ b/cloud/cmd/serve.go @@ -0,0 +1,97 @@ +package cmd + +import ( + "context" + "fmt" + "log" + "net/http" + "os" + "os/signal" + "sync" + "syscall" + "time" + + "github.com/gorilla/mux" +) + +func Serve(srv *http.Server) { + var wg sync.WaitGroup + wg.Add(1) + + go func() { + defer wg.Done() + if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed { + log.Fatalf("Error starting server: %v\n", err) + } + }() + // 监听退出信号 + ctx, cancel := context.WithCancel(context.Background()) + go func() { + c := make(chan os.Signal, 1) + signal.Notify(c, syscall.SIGINT, syscall.SIGTERM) + <-c + log.Println("Received signal, gracefully shutting down...") + cancel() + }() + + <-ctx.Done() + shutdownCtx, shutdownCancel := context.WithTimeout(context.Background(), 5*time.Second) + defer shutdownCancel() + if err := srv.Shutdown(shutdownCtx); err != nil { + log.Printf("Error during server shutdown: %v\n", err) + } + wg.Wait() +} + +type loggingMiddleware struct { +} + +func (l loggingMiddleware) Middleware(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + startTime := time.Now() + defer func() { + log.Printf( + "%s %s %s %v", + r.Method, + r.URL.Path, + r.Proto, + time.Since(startTime), + ) + }() + next.ServeHTTP(w, r) + }) +} +func recoverMiddleware(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + defer func() { + if err := recover(); err != nil { + // log.Printf("Recovered from panic: %v", err) + // http.Error(w, "Internal Server Error", http.StatusInternalServerError) + ErrorMsg(w, "Internal Server Error:"+fmt.Sprintf("%v", err)) + } + }() + next.ServeHTTP(w, r) + }) +} + +// CORS 中间件 +func corsMiddleware() mux.MiddlewareFunc { + allowHeaders := "Content-Type, Accept, Authorization, Origin,Pwd" + allowMethods := "GET, POST, PUT, DELETE, OPTIONS" + + return func(next http.Handler) http.Handler { + return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + w.Header().Set("Access-Control-Allow-Origin", "*") + w.Header().Set("Access-Control-Allow-Methods", allowMethods) + w.Header().Set("Access-Control-Allow-Headers", allowHeaders) + + // 如果是预检请求(OPTIONS),直接返回 200 OK + if r.Method == http.MethodOptions { + w.WriteHeader(http.StatusOK) + return + } + + next.ServeHTTP(w, r) + }) + } +} diff --git a/cloud/deps/frontend.go b/cloud/deps/frontend.go new file mode 100644 index 0000000..5ae8944 --- /dev/null +++ b/cloud/deps/frontend.go @@ -0,0 +1,6 @@ +package deps + +import "embed" + +//go:embed dist +var Frontendassets embed.FS diff --git a/cloud/go.mod b/cloud/go.mod new file mode 100644 index 0000000..5130b88 --- /dev/null +++ b/cloud/go.mod @@ -0,0 +1,5 @@ +module godocloud + +go 1.23.2 + +require github.com/gorilla/mux v1.8.1 diff --git a/cloud/go.sum b/cloud/go.sum new file mode 100644 index 0000000..7128337 --- /dev/null +++ b/cloud/go.sum @@ -0,0 +1,2 @@ +github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= +github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ= diff --git a/cloud/main.go b/cloud/main.go new file mode 100644 index 0000000..cbc419b --- /dev/null +++ b/cloud/main.go @@ -0,0 +1,7 @@ +package main + +import "godocloud/cmd" + +func main() { + cmd.OsStart() +} diff --git a/frontend/src/system/config.ts b/frontend/src/system/config.ts index 520ec9d..80c1f18 100644 --- a/frontend/src/system/config.ts +++ b/frontend/src/system/config.ts @@ -28,7 +28,7 @@ export const getSystemConfig = (ifset = false) => { config.apiUrl = `${window.location.protocol}//${window.location.hostname}:56780`; } if (!config.userType) { - config.userType = 'person' + config.userType = 'person'//如果是企业版请改为member } if (!config.file) { config.file = { @@ -43,7 +43,7 @@ export const getSystemConfig = (ifset = false) => { // 初始化用户信息,若本地存储中已存在则不进行覆盖 if (!config.userInfo) { config.userInfo = { - url: '', + url: '',//如果是企业版请改为服务器地址,不要加斜线 username: '', password: '', id: 0, @@ -88,9 +88,6 @@ export const getSystemConfig = (ifset = false) => { if(!config.netPort) { config.netPort = "56780"; } - if (!config.userType) { - config.userType = 'person'; - } // 初始化背景设置,若本地存储中已存在则不进行覆盖 if (!config.background) { config.background = {